-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Add customizable squircle option #1443
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
…e-cursor-option-to-settings-claude-4.5-opus-high-thinking-64f7 Add circle cursor option to settings
WalkthroughReplaces discrete corner-style enum with continuous smoothness parameter: introduces Changes
Sequence Diagram(s)sequenceDiagram
participant UI as Desktop UI
participant Tauri as Tauri bridge
participant Rust as Native backend
participant Shader as WGSL shader
UI->>Tauri: user adjusts "rounding" and "roundingSmoothness"
Tauri->>Rust: serialize/send ProjectConfiguration (rounding, rounding_smoothness)
Rust->>Rust: compute_adjusted_radius(rounding_px) using rounding and smoothness
Rust->>Rust: smoothness_to_exponent(rounding_smoothness) => corner_exponent
Rust->>Shader: upload CompositeVideoFrameUniforms { rounding_px, corner_exponent, ... }
Shader->>Shader: apply rounded corners using corner_exponent & rounding_px
Shader-->>Rust: rendered frame
Rust-->>Tauri: frame buffer / display update
Tauri-->>UI: display updated frame
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes
Possibly related PRs
Poem
Pre-merge checks and finishing touches❌ Failed checks (2 warnings)
✅ Passed checks (1 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this 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
🧹 Nitpick comments (2)
apps/desktop/src/routes/editor/ConfigSidebar.tsx (1)
1997-2004: UI fallback may not match backend default.The fallback
project.background.roundingSmoothness ?? 0uses0, but the Rust backend defaultsrounding_smoothnessto0.6forBackgroundConfiguration. Since serde's#[serde(default)]ensures the field is always populated when deserializing, the?? 0fallback should rarely trigger. However, for consistency and to avoid potential edge cases where the field might beundefined, consider aligning the fallback with the backend default:<Slider - value={[project.background.roundingSmoothness ?? 0]} + value={[project.background.roundingSmoothness ?? 0.6]} onChange={(v) => setProject("background", "roundingSmoothness", v[0])}crates/rendering/src/lib.rs (1)
1447-1448: Consider using a consistent exponent value.Since
rounding_pxis 0.0, thecorner_exponentvalue doesn't affect rendering. However, 0.6 is outside the normal range produced bysmoothness_to_exponent(which yields 2.0–8.0). Using2.0(equivalent to smoothness=0) would be more consistent with the rest of the codebase.rounding_px: 0.0, - corner_exponent: 0.6, + corner_exponent: 2.0,
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (8)
apps/desktop/src/routes/editor/ConfigSidebar.tsx(4 hunks)apps/desktop/src/routes/editor/context.ts(2 hunks)apps/desktop/src/utils/tauri.ts(1 hunks)crates/project/src/configuration.rs(4 hunks)crates/rendering/src/composite_frame.rs(2 hunks)crates/rendering/src/lib.rs(5 hunks)crates/rendering/src/shaders/composite-video-frame.wgsl(7 hunks)packages/ui-solid/src/auto-imports.d.ts(1 hunks)
🧰 Additional context used
📓 Path-based instructions (7)
**/*.rs
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.rs: Never use dbg!() macro; use proper logging (tracing::debug!, etc.) instead
Never write let _ = async_fn() which silently drops futures; await or explicitly handle them
Use duration.saturating_sub(other) instead of duration - other to avoid panics on underflow
Merge nested if statements: write 'if a && b { }' instead of 'if a { if b { } }'
Don't call .clone() on Copy types (integers, bools, etc.); copy them directly
Use function references directly: iter.map(foo) instead of iter.map(|x| foo(x))
Accept &[T] or &str instead of &Vec or &String in function parameters for flexibility
Use .is_empty() instead of .len() == 0 or .len() > 0 / .len() != 0
Don't assign () to a variable: write foo(); instead of let _ = foo(); or let x = foo(); when return is unit
Use .unwrap_or(val) instead of .unwrap_or_else(|| val) when the default is a simple/cheap value
Use 'for item in &collection' or 'for (i, item) in collection.iter().enumerate()' instead of 'for i in 0..collection.len()'
Use value.clamp(min, max) instead of manual if chains or .min(max).max(min) patterns
Always handle Result/Option or types marked #[must_use]; never ignore them
**/*.rs: Userustfmtand workspace clippy lints for Rust code formatting and linting
Use snake_case for Rust module names and kebab-case for crate names
Never usedbg!()macro in Rust code; use proper logging instead (Clippy:dbg_macro= deny)
Always handleResult/Optionor types marked#[must_use]; never ignore them (Rust compiler lint:unused_must_use= deny)
Never writelet _ = async_fn()which silently drops futures; await or explicitly handle them (Clippy:let_underscore_future= deny)
Usesaturating_subinstead of-forDurationto avoid panics (Clippy:unchecked_duration_subtraction= deny)
Merge nestedifstatements: useif a && b { }instead ofif a { if b { } }(Clippy:collapsible_if= deny)
Don't call.clone()onCopytypes; just copy them directly (Clippy:clone_on_copy= deny)
U...
Files:
crates/rendering/src/composite_frame.rscrates/project/src/configuration.rscrates/rendering/src/lib.rs
**/*.{ts,tsx,js,jsx,rs}
📄 CodeRabbit inference engine (AGENTS.md)
Never add comments to code (
//,/* */,///,//!,#, etc.); code must be self-explanatory through naming, types, and structure
Files:
crates/rendering/src/composite_frame.rspackages/ui-solid/src/auto-imports.d.tscrates/project/src/configuration.rsapps/desktop/src/utils/tauri.tsapps/desktop/src/routes/editor/context.tscrates/rendering/src/lib.rsapps/desktop/src/routes/editor/ConfigSidebar.tsx
**/*.ts
📄 CodeRabbit inference engine (CLAUDE.md)
Use TanStack Query v5 for all client-side server state and data fetching in TypeScript files
Files:
packages/ui-solid/src/auto-imports.d.tsapps/desktop/src/utils/tauri.tsapps/desktop/src/routes/editor/context.ts
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.{ts,tsx,js,jsx}: Use strict TypeScript; avoid any type; leverage shared types from @cap/* packages
Follow camelCase naming for variables and functions; PascalCase for components; hooks must start with 'use' prefix
Use Biome for linting and formatting; match existing formatting conventions in the codebase
Use Tailwind CSS for styling in web components; stay consistent with spacing and tokens
Use static skeletons for loading states that mirror content; avoid bouncing animations
Memoize expensive work, code-split naturally, and use Next/Image for remote assets
**/*.{ts,tsx,js,jsx}: Use 2-space indent for TypeScript files; format with Biome usingpnpm format
Use Biome for code formatting and linting; runpnpm formatregularly
Use kebab-case for file names (e.g.,user-menu.tsx); use PascalCase for components
Files:
packages/ui-solid/src/auto-imports.d.tsapps/desktop/src/utils/tauri.tsapps/desktop/src/routes/editor/context.tsapps/desktop/src/routes/editor/ConfigSidebar.tsx
**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.{ts,tsx}: Never add any form of comments to code (single-line //, multi-line /* /, JSDoc /* */, or any other comment syntax); code must be self-explanatory through naming, types, and structure
Directory naming must use lowercase-dashed convention
Files:
packages/ui-solid/src/auto-imports.d.tsapps/desktop/src/utils/tauri.tsapps/desktop/src/routes/editor/context.tsapps/desktop/src/routes/editor/ConfigSidebar.tsx
apps/desktop/**/*.ts
📄 CodeRabbit inference engine (CLAUDE.md)
apps/desktop/**/*.ts: Use @tanstack/solid-query for server state management in SolidJS components
Use generated commands and events from tauri_specta for IPC; never manually construct IPC calls
Listen directly to generated events from tauri_specta and use typed event interfaces
Files:
apps/desktop/src/utils/tauri.tsapps/desktop/src/routes/editor/context.ts
**/*.tsx
📄 CodeRabbit inference engine (CLAUDE.md)
Use React Query hooks with Server Actions for mutations and perform precise cache updates using setQueryData/setQueriesData instead of broad invalidations
Files:
apps/desktop/src/routes/editor/ConfigSidebar.tsx
🧠 Learnings (3)
📚 Learning: 2025-12-07T14:29:40.721Z
Learnt from: CR
Repo: CapSoftware/Cap PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-07T14:29:40.721Z
Learning: Applies to **/tauri.ts|**/queries.ts|apps/desktop/src-tauri/gen/** : Never edit auto-generated files: `**/tauri.ts`, `**/queries.ts`, `apps/desktop/src-tauri/gen/**`
Applied to files:
apps/desktop/src/routes/editor/ConfigSidebar.tsx
📚 Learning: 2025-12-07T14:29:19.166Z
Learnt from: CR
Repo: CapSoftware/Cap PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-07T14:29:19.166Z
Learning: Never edit auto-generated files: tauri.ts, queries.ts, and files under apps/desktop/src-tauri/gen/
Applied to files:
apps/desktop/src/routes/editor/ConfigSidebar.tsx
📚 Learning: 2025-12-07T14:29:19.165Z
Learnt from: CR
Repo: CapSoftware/Cap PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-07T14:29:19.165Z
Learning: Applies to **/*.config.{js,ts,mjs,cjs} : Configuration files must follow their respective tool conventions (Next.js, Tailwind, etc.)
Applied to files:
apps/desktop/src/routes/editor/ConfigSidebar.tsx
🧬 Code graph analysis (1)
apps/desktop/src/routes/editor/ConfigSidebar.tsx (1)
apps/desktop/src/routes/editor/ui.tsx (2)
Slider(65-149)Field(25-47)
⏰ 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). (2)
- GitHub Check: Clippy (aarch64-apple-darwin, macos-latest)
- GitHub Check: Clippy (x86_64-pc-windows-msvc, windows-latest)
🔇 Additional comments (11)
packages/ui-solid/src/auto-imports.d.ts (1)
97-97: Thesquare-round-cornericon exists in the Lucide icon library and is properly referenced. No issues detected.apps/desktop/src/routes/editor/context.ts (1)
98-106: LGTM! Simplified type definitions.The removal of
WithCornerStylewrapper and direct use ofProjectConfiguration["background"]andProjectConfiguration["camera"]simplifies the type system. The serialization logic is also cleaner without the round-trip forroundingType.crates/project/src/configuration.rs (3)
229-231: LGTM! Background smoothness default aligns with Apple HIG.The default of
0.6forrounding_smoothnessmatches the PR objective of aligning with Apple's Human Interface Guidelines for squircle aesthetics.
310-312: LGTM! Camera smoothness defaults to standard rounded corners.Setting
rounding_smoothness: 0.0for the camera by default maintains backwards compatibility and keeps standard rounded corners, while users can opt into squircle styling.Also applies to: 348-348
185-191: Consider removing unusedCornerStyleenum if no longer referenced.The
CornerStyleenum appears to no longer be used after this refactor, as the configuration now usesrounding_smoothness: f32instead. Verify that this enum is not referenced elsewhere in the codebase for backwards compatibility or other purposes before removal.crates/rendering/src/composite_frame.rs (1)
22-24: LGTM! Semantic rename tocorner_exponent.The field rename from
rounding_typetocorner_exponentbetter describes the shader parameter's purpose. The struct maintains proper alignment with#[repr(C)]and thePod/Zeroablederives.apps/desktop/src/routes/editor/ConfigSidebar.tsx (2)
2341-2363: LGTM! Camera rounding controls.The Camera section correctly implements separate "Rounded Corners" and "Corner Smoothness" sliders. The
?? 0fallback forroundingSmoothnesscorrectly matches the backend default of0.0for Camera.
1983-1992: LGTM! Background rounding slider refactored.The "Rounded Corners" slider is correctly bound to
project.background.roundingwith appropriate range (0-100%) and step values.crates/rendering/src/shaders/composite-video-frame.wgsl (1)
54-68: LGTM - Safety guards and parameter rename are well implemented.The fallback to
length(p)for non-positive exponents and themax(exponent, 1e-3)clamp provide good protection against edge cases. The refactor fromrounding_typetoexponentsemantics is applied consistently.crates/rendering/src/lib.rs (2)
1160-1166: LGTM - Display rounding calculation is correct.The radius computation correctly uses
min_target_axisfor proportional scaling, and bothcompute_adjusted_radiusandsmoothness_to_exponentare applied consistently.
1343-1349: Verify: Camera usesproject.background.rounding_smoothness- is this intentional?The camera rounding smoothness is sourced from
project.background.rounding_smoothnessrather than a camera-specific setting. Confirm whether there is a single global smoothness slider or if the camera should have its ownrounding_smoothnessproperty.
There was a problem hiding this 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
♻️ Duplicate comments (1)
crates/rendering/src/lib.rs (1)
2023-2041: Remove new Rust comments to match project guidelinesThe
smoothness_to_exponentandcompute_adjusted_radiushelpers now include//comments, but the repo’s.rsguidelines explicitly disallow comments, and a prior review already requested removing documentation/comments around these functions.Please strip the comments and keep just the function definitions and logic, e.g.:
-// Converts a smoothness value (0.0 to 1.0) to a super ellipse exponent. #[inline] fn smoothness_to_exponent(smoothness: f32) -> f32 { 2.0 + smoothness * 6.0 } -// Adjusts radius to maintain visual consistency across different super ellipse exponents. fn compute_adjusted_radius(radius: f32, smoothness: f32) -> f32 { if smoothness == 0.0 { return radius; } let power = smoothness_to_exponent(smoothness); let capsule_scale = 2.0f32.powf(0.5 - 1.0 / power); - - // Visual normalization: compensate for super ellipses appearing smaller let visual_compensation = 1.0 + smoothness * 0.8; radius * capsule_scale * visual_compensation }This restores compliance with the no-comments rule for Rust files.
🧹 Nitpick comments (4)
apps/desktop/src/routes/screenshot-editor/popovers/RoundingPopover.tsx (1)
25-54: Align rounding smoothness fallback with 0.6 defaultThe sliders are wired correctly, but
roundingSmoothnesscurrently falls back to0, which conflicts with the intended default of0.6when the field is absent (e.g., older projects).Recommend using
0.6as the fallback to match the PR’s behavior spec and avoid unexpectedly “sharp” corners when the field is unset:- <Slider - value={[project.background.roundingSmoothness ?? 0]} + <Slider + value={[project.background.roundingSmoothness ?? 0.6]} onChange={(v) => setProject("background", "roundingSmoothness", v[0]) } minValue={0} maxValue={1} step={0.01} formatTooltip={(value) => `${Math.round(value * 100)}%`} />apps/desktop/src/routes/editor/ConfigSidebar.tsx (3)
1715-1718: Inline Tauri bug comment conflicts with TSX no-comments guidelineThe multiline comment documenting the Tauri file-type bug adds/changes comments in a
.tsxfile, which the project guidelines forbid (code should be self-explanatory, with no inline comments).Recommend removing this comment block and capturing the context in commit messages or external docs/issues instead:
- /* - this is a Tauri bug in WebKit so we need to validate the file type manually - https://github.com/tauri-apps/tauri/issues/9158 - */
1984-2005: Background rounding/smoothness wiring looks good; adjust smoothness fallbackThe new “Rounded Corners” and “Corner Smoothness” sliders for the background are correctly bound to
project.background.roundingandproject.background.roundingSmoothness, with sensible ranges and tooltips.To better honor the intended default smoothness
0.6, consider updating the fallback to avoid defaulting to0when the field is undefined (e.g., older projects):- <Slider - value={[project.background.roundingSmoothness ?? 0]} + <Slider + value={[project.background.roundingSmoothness ?? 0.6]} onChange={(v) => setProject("background", "roundingSmoothness", v[0])} minValue={0} maxValue={1} step={0.01} formatTooltip={(value) => `${Math.round(value * 100)}%`} />This aligns the UI fallback with the spec and with new projects that initialize the field to 0.6.
2342-2363: Camera rounding/smoothness controls are correct; mirror the 0.6 fallbackThe camera “Rounded Corners” and “Corner Smoothness” sliders are wired correctly to
project.camera.roundingandproject.camera.roundingSmoothness, matching the background controls.For consistency with the spec and background UI, suggest using
0.6as the fallback for the smoothness slider:- <Slider - value={[project.camera.roundingSmoothness ?? 0]} + <Slider + value={[project.camera.roundingSmoothness ?? 0.6]} onChange={(v) => setProject("camera", "roundingSmoothness", v[0])} minValue={0} maxValue={1} step={0.01} formatTooltip={(value) => `${Math.round(value * 100)}%`} />This keeps camera smoothness defaults in line with the background and the stated 0.6 default.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
apps/desktop/src/routes/editor/ConfigSidebar.tsx(4 hunks)apps/desktop/src/routes/screenshot-editor/popovers/RoundingPopover.tsx(2 hunks)crates/rendering/src/lib.rs(5 hunks)
🧰 Additional context used
📓 Path-based instructions (5)
**/*.tsx
📄 CodeRabbit inference engine (CLAUDE.md)
Use React Query hooks with Server Actions for mutations and perform precise cache updates using setQueryData/setQueriesData instead of broad invalidations
Files:
apps/desktop/src/routes/screenshot-editor/popovers/RoundingPopover.tsxapps/desktop/src/routes/editor/ConfigSidebar.tsx
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.{ts,tsx,js,jsx}: Use strict TypeScript; avoid any type; leverage shared types from @cap/* packages
Follow camelCase naming for variables and functions; PascalCase for components; hooks must start with 'use' prefix
Use Biome for linting and formatting; match existing formatting conventions in the codebase
Use Tailwind CSS for styling in web components; stay consistent with spacing and tokens
Use static skeletons for loading states that mirror content; avoid bouncing animations
Memoize expensive work, code-split naturally, and use Next/Image for remote assets
**/*.{ts,tsx,js,jsx}: Use 2-space indent for TypeScript files; format with Biome usingpnpm format
Use Biome for code formatting and linting; runpnpm formatregularly
Use kebab-case for file names (e.g.,user-menu.tsx); use PascalCase for components
Files:
apps/desktop/src/routes/screenshot-editor/popovers/RoundingPopover.tsxapps/desktop/src/routes/editor/ConfigSidebar.tsx
**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.{ts,tsx}: Never add any form of comments to code (single-line //, multi-line /* /, JSDoc /* */, or any other comment syntax); code must be self-explanatory through naming, types, and structure
Directory naming must use lowercase-dashed convention
Files:
apps/desktop/src/routes/screenshot-editor/popovers/RoundingPopover.tsxapps/desktop/src/routes/editor/ConfigSidebar.tsx
**/*.{ts,tsx,js,jsx,rs}
📄 CodeRabbit inference engine (AGENTS.md)
Never add comments to code (
//,/* */,///,//!,#, etc.); code must be self-explanatory through naming, types, and structure
Files:
apps/desktop/src/routes/screenshot-editor/popovers/RoundingPopover.tsxapps/desktop/src/routes/editor/ConfigSidebar.tsxcrates/rendering/src/lib.rs
**/*.rs
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.rs: Never use dbg!() macro; use proper logging (tracing::debug!, etc.) instead
Never write let _ = async_fn() which silently drops futures; await or explicitly handle them
Use duration.saturating_sub(other) instead of duration - other to avoid panics on underflow
Merge nested if statements: write 'if a && b { }' instead of 'if a { if b { } }'
Don't call .clone() on Copy types (integers, bools, etc.); copy them directly
Use function references directly: iter.map(foo) instead of iter.map(|x| foo(x))
Accept &[T] or &str instead of &Vec or &String in function parameters for flexibility
Use .is_empty() instead of .len() == 0 or .len() > 0 / .len() != 0
Don't assign () to a variable: write foo(); instead of let _ = foo(); or let x = foo(); when return is unit
Use .unwrap_or(val) instead of .unwrap_or_else(|| val) when the default is a simple/cheap value
Use 'for item in &collection' or 'for (i, item) in collection.iter().enumerate()' instead of 'for i in 0..collection.len()'
Use value.clamp(min, max) instead of manual if chains or .min(max).max(min) patterns
Always handle Result/Option or types marked #[must_use]; never ignore them
**/*.rs: Userustfmtand workspace clippy lints for Rust code formatting and linting
Use snake_case for Rust module names and kebab-case for crate names
Never usedbg!()macro in Rust code; use proper logging instead (Clippy:dbg_macro= deny)
Always handleResult/Optionor types marked#[must_use]; never ignore them (Rust compiler lint:unused_must_use= deny)
Never writelet _ = async_fn()which silently drops futures; await or explicitly handle them (Clippy:let_underscore_future= deny)
Usesaturating_subinstead of-forDurationto avoid panics (Clippy:unchecked_duration_subtraction= deny)
Merge nestedifstatements: useif a && b { }instead ofif a { if b { } }(Clippy:collapsible_if= deny)
Don't call.clone()onCopytypes; just copy them directly (Clippy:clone_on_copy= deny)
U...
Files:
crates/rendering/src/lib.rs
🧠 Learnings (1)
📚 Learning: 2025-12-07T14:29:40.721Z
Learnt from: CR
Repo: CapSoftware/Cap PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-07T14:29:40.721Z
Learning: Applies to **/tauri.ts|**/queries.ts|apps/desktop/src-tauri/gen/** : Never edit auto-generated files: `**/tauri.ts`, `**/queries.ts`, `apps/desktop/src-tauri/gen/**`
Applied to files:
apps/desktop/src/routes/editor/ConfigSidebar.tsx
🧬 Code graph analysis (1)
apps/desktop/src/routes/screenshot-editor/popovers/RoundingPopover.tsx (1)
apps/desktop/src/routes/screenshot-editor/ui.tsx (1)
Slider(65-147)
⏰ 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). (2)
- GitHub Check: Clippy (x86_64-pc-windows-msvc, windows-latest)
- GitHub Check: Clippy (aarch64-apple-darwin, macos-latest)
🔇 Additional comments (4)
apps/desktop/src/routes/screenshot-editor/popovers/RoundingPopover.tsx (1)
4-4: Shared Slider import looks correctUsing the shared
Sliderfrom../uihere is consistent with the screenshot editor controls and keeps behavior (history pause, tooltip, drag UX) aligned.crates/rendering/src/lib.rs (2)
3-5: Import adjustments are consistent with Crop usagePulling
Cropdirectly fromcap_projectmatches its later usage inProjectUniforms::get_cropand keeps the import list coherent.
1160-1166: Display rounding uses new helpers correctly
rounding_pxandcorner_exponentfor the display path are derived consistently fromproject.background.roundingandproject.background.rounding_smoothnessviacompute_adjusted_radiusandsmoothness_to_exponent, matching the new squircle model.apps/desktop/src/routes/editor/ConfigSidebar.tsx (1)
68-68: Editor context import is consistentSwitching/importing
useEditorContextfrom"./context"matches its usage throughout this file and keeps things aligned with the editor data flow.
There was a problem hiding this 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
♻️ Duplicate comments (3)
crates/rendering/src/lib.rs (3)
2019-2037: Remove comments per coding guidelines.Comments remain on lines 2019, 2025, and 2034 despite the coding guideline requiring no comments in
.rsfiles and a previous review indicating this was addressed. The function names and types should be self-explanatory.-// Converts a smoothness value (0.0 to 1.0) to a super ellipse exponent. #[inline] fn smoothness_to_exponent(smoothness: f32) -> f32 { 2.0 + smoothness * 6.0 } -// Adjusts radius to maintain visual consistency across different super ellipse exponents. fn compute_adjusted_radius(radius: f32, smoothness: f32) -> f32 { if smoothness == 0.0 { return radius; } let power = smoothness_to_exponent(smoothness); let capsule_scale = 2.0f32.powf(0.5 - 1.0 / power); - // Visual normalization: compensate for super ellipses appearing smaller let visual_compensation = 1.0 + smoothness * 0.8; radius * capsule_scale * visual_compensation }As per coding guidelines.
1341-1345: Camera rounding incorrectly uses background smoothness.The camera rendering path uses
project.background.rounding_smoothnessfor both the radius adjustment and exponent calculation. This means the camera's corner smoothness will always match the background instead of having its own independent control, breaking the "Camera Corner Smoothness" slider mentioned in the PR.rounding_px: compute_adjusted_radius( project.camera.rounding / 100.0 * 0.5 * size[0].min(size[1]) as f32, - project.background.rounding_smoothness, + project.camera.rounding_smoothness, ), - corner_exponent: smoothness_to_exponent(project.background.rounding_smoothness), + corner_exponent: smoothness_to_exponent(project.camera.rounding_smoothness),
1444-1444: Camera-only path uses raw smoothness value as exponent.The hardcoded
0.6appears to be a smoothness value being used directly as an exponent, which is inconsistent with the conversion model defined insmoothness_to_exponent(exponents range from 2.0 to 8.0). This will produce unexpected rendering that doesn't match the smoothness scale used elsewhere.Recommend either:
- Use
smoothness_to_exponent(0.6)for a fixed smoothness of 0.6, or- Use
smoothness_to_exponent(project.camera.rounding_smoothness)to respect the camera's configured smoothnessrounding_px: 0.0, - corner_exponent: 0.6, + corner_exponent: smoothness_to_exponent(project.camera.rounding_smoothness),
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
crates/rendering/src/composite_frame.rs(2 hunks)crates/rendering/src/lib.rs(5 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
**/*.rs
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.rs: Never use dbg!() macro; use proper logging (tracing::debug!, etc.) instead
Never write let _ = async_fn() which silently drops futures; await or explicitly handle them
Use duration.saturating_sub(other) instead of duration - other to avoid panics on underflow
Merge nested if statements: write 'if a && b { }' instead of 'if a { if b { } }'
Don't call .clone() on Copy types (integers, bools, etc.); copy them directly
Use function references directly: iter.map(foo) instead of iter.map(|x| foo(x))
Accept &[T] or &str instead of &Vec or &String in function parameters for flexibility
Use .is_empty() instead of .len() == 0 or .len() > 0 / .len() != 0
Don't assign () to a variable: write foo(); instead of let _ = foo(); or let x = foo(); when return is unit
Use .unwrap_or(val) instead of .unwrap_or_else(|| val) when the default is a simple/cheap value
Use 'for item in &collection' or 'for (i, item) in collection.iter().enumerate()' instead of 'for i in 0..collection.len()'
Use value.clamp(min, max) instead of manual if chains or .min(max).max(min) patterns
Always handle Result/Option or types marked #[must_use]; never ignore them
**/*.rs: Userustfmtand workspace clippy lints for Rust code formatting and linting
Use snake_case for Rust module names and kebab-case for crate names
Never usedbg!()macro in Rust code; use proper logging instead (Clippy:dbg_macro= deny)
Always handleResult/Optionor types marked#[must_use]; never ignore them (Rust compiler lint:unused_must_use= deny)
Never writelet _ = async_fn()which silently drops futures; await or explicitly handle them (Clippy:let_underscore_future= deny)
Usesaturating_subinstead of-forDurationto avoid panics (Clippy:unchecked_duration_subtraction= deny)
Merge nestedifstatements: useif a && b { }instead ofif a { if b { } }(Clippy:collapsible_if= deny)
Don't call.clone()onCopytypes; just copy them directly (Clippy:clone_on_copy= deny)
U...
Files:
crates/rendering/src/composite_frame.rscrates/rendering/src/lib.rs
**/*.{ts,tsx,js,jsx,rs}
📄 CodeRabbit inference engine (AGENTS.md)
Never add comments to code (
//,/* */,///,//!,#, etc.); code must be self-explanatory through naming, types, and structure
Files:
crates/rendering/src/composite_frame.rscrates/rendering/src/lib.rs
⏰ 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). (2)
- GitHub Check: Clippy (aarch64-apple-darwin, macos-latest)
- GitHub Check: Clippy (x86_64-pc-windows-msvc, windows-latest)
🔇 Additional comments (3)
crates/rendering/src/composite_frame.rs (1)
23-23: LGTM! Field rename aligns with squircle implementation.The field name
corner_exponentclearly conveys that it controls the exponent parameter for super-ellipse rendering, replacing the previous type-based approach.crates/rendering/src/lib.rs (2)
1160-1164: LGTM! Display path correctly uses background smoothness.The display rendering path properly converts
rounding_smoothnessto both an adjusted radius and corner exponent using the helper functions. This ensures consistent super-ellipse rendering.
1443-1444: Verify if camera-only mode should inherit camera rounding settings or intentionally use zero rounding.The camera-only rendering path sets
rounding_px: 0.0withcorner_exponent: 0.6. If sharp corners are intentional for camera-only mode, the exponent is unused. If camera-only should respect the camera's rounding configuration for visual consistency, both fields should be derived from camera settings.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This PR is being reviewed by Cursor Bugbot
Details
You are on the Bugbot Free tier. On this plan, Bugbot will review limited PRs each billing cycle.
To receive Bugbot reviews on all of your PRs, visit the Cursor dashboard to activate Pro and start your 14-day free trial.
| export type BackgroundConfiguration = { source: BackgroundSource; blur: number; padding: number; rounding: number; roundingSmoothness?: number; inset: number; crop: Crop | null; shadow?: number; advancedShadow?: ShadowConfiguration | null; border?: BorderConfiguration | null } | ||
| export type BackgroundSource = { type: "wallpaper"; path: string | null } | { type: "image"; path: string | null } | { type: "color"; value: [number, number, number]; alpha?: number } | { type: "gradient"; from: [number, number, number]; to: [number, number, number]; angle?: number } | ||
| export type BorderConfiguration = { enabled: boolean; width: number; color: [number, number, number]; opacity: number } | ||
| export type Camera = { hide: boolean; mirror: boolean; position: CameraPosition; size: number; zoomSize: number | null; rounding?: number; shadow?: number; advancedShadow?: ShadowConfiguration | null; shape?: CameraShape; roundingType?: CornerStyle } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Bug: Screenshot editor defaults use removed roundingType property
The type definitions for BackgroundConfiguration and Camera were updated to replace roundingType?: CornerStyle with roundingSmoothness?: number, and CornerStyle was removed. However, the screenshot editor's default configuration in apps/desktop/src/routes/screenshot-editor/context.tsx still sets roundingType: "squircle" at lines 56 and 95. These objects use as unknown as type casts that bypass TypeScript checking, so the build succeeds but at runtime the old roundingType property is ignored and roundingSmoothness defaults to 0 (via the ?? 0 fallback). This causes the screenshot editor to default to circular corners instead of the intended squircle style.
There was a problem hiding this 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)
crates/project/src/configuration.rs (1)
224-239: New rounding_smoothness fields are coherent, but existing CornerStyle values are effectively discarded
- Background:
- Adds
rounding_smoothness: f32with#[serde(default)], defaulting to0.6inDefault. This matches the desired “Apple‑style squircle” default.- Camera:
- Adds
rounding_smoothness: f32with#[serde(default)], defaulting to0.0, which keeps cameras visually rounded by default.- Migration:
Camerano longer aliasesrounding_typevia serde, andBackgroundConfigurationnever had such an alias. Any existing JSONrounding_typevalues will now be ignored and replaced by the above defaults on load.camera_config_needs_migrationstill looks for"rounding_type"in raw JSON, but there’s no mapping from that torounding_smoothness, so projects that previously chose a non‑defaultCornerStylewill silently lose that preference.If the intent is to intentionally reset past corner styles to the new smoothness defaults, this is fine. If you want to preserve user intent, consider adding a one‑off migration that:
- Reads
rounding_typefrom the raw JSON, and- Maps it into an appropriate
rounding_smoothnessvalue before writing back.Also applies to: 252-266, 293-313, 332-351, 1032-1041
♻️ Duplicate comments (1)
crates/rendering/src/lib.rs (1)
1951-1969: Remove helper function comments to comply with “no comments” ruleThe two
//comment lines abovesmoothness_to_exponentandcompute_adjusted_radius, plus the inline “Visual normalization” comment, conflict with the guideline that.rsfiles should not contain comments. This is the same issue that was previously raised for the earlier doc‑comment block around these helpers.The function names and parameter names are already descriptive enough; consider deleting these comments while keeping the logic unchanged.
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (7)
apps/desktop/src/routes/editor/ConfigSidebar.tsx(4 hunks)apps/desktop/src/routes/editor/context.ts(2 hunks)apps/desktop/src/utils/tauri.ts(1 hunks)crates/project/src/configuration.rs(4 hunks)crates/rendering/src/composite_frame.rs(3 hunks)crates/rendering/src/lib.rs(5 hunks)packages/ui-solid/src/auto-imports.d.ts(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
- apps/desktop/src/utils/tauri.ts
- crates/rendering/src/composite_frame.rs
- packages/ui-solid/src/auto-imports.d.ts
🧰 Additional context used
📓 Path-based instructions (7)
**/*.ts
📄 CodeRabbit inference engine (CLAUDE.md)
Use TanStack Query v5 for all client-side server state and data fetching in TypeScript files
Files:
apps/desktop/src/routes/editor/context.ts
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.{ts,tsx,js,jsx}: Use strict TypeScript; avoid any type; leverage shared types from @cap/* packages
Follow camelCase naming for variables and functions; PascalCase for components; hooks must start with 'use' prefix
Use Biome for linting and formatting; match existing formatting conventions in the codebase
Use Tailwind CSS for styling in web components; stay consistent with spacing and tokens
Use static skeletons for loading states that mirror content; avoid bouncing animations
Memoize expensive work, code-split naturally, and use Next/Image for remote assets
**/*.{ts,tsx,js,jsx}: Use 2-space indent for TypeScript files; format with Biome usingpnpm format
Use Biome for code formatting and linting; runpnpm formatregularly
Use kebab-case for file names (e.g.,user-menu.tsx); use PascalCase for components
Files:
apps/desktop/src/routes/editor/context.tsapps/desktop/src/routes/editor/ConfigSidebar.tsx
**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.{ts,tsx}: Never add any form of comments to code (single-line //, multi-line /* /, JSDoc /* */, or any other comment syntax); code must be self-explanatory through naming, types, and structure
Directory naming must use lowercase-dashed convention
Files:
apps/desktop/src/routes/editor/context.tsapps/desktop/src/routes/editor/ConfigSidebar.tsx
apps/desktop/**/*.ts
📄 CodeRabbit inference engine (CLAUDE.md)
apps/desktop/**/*.ts: Use @tanstack/solid-query for server state management in SolidJS components
Use generated commands and events from tauri_specta for IPC; never manually construct IPC calls
Listen directly to generated events from tauri_specta and use typed event interfaces
Files:
apps/desktop/src/routes/editor/context.ts
**/*.{ts,tsx,js,jsx,rs}
📄 CodeRabbit inference engine (AGENTS.md)
Never add comments to code (
//,/* */,///,//!,#, etc.); code must be self-explanatory through naming, types, and structure
Files:
apps/desktop/src/routes/editor/context.tscrates/project/src/configuration.rsapps/desktop/src/routes/editor/ConfigSidebar.tsxcrates/rendering/src/lib.rs
**/*.rs
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.rs: Never use dbg!() macro; use proper logging (tracing::debug!, etc.) instead
Never write let _ = async_fn() which silently drops futures; await or explicitly handle them
Use duration.saturating_sub(other) instead of duration - other to avoid panics on underflow
Merge nested if statements: write 'if a && b { }' instead of 'if a { if b { } }'
Don't call .clone() on Copy types (integers, bools, etc.); copy them directly
Use function references directly: iter.map(foo) instead of iter.map(|x| foo(x))
Accept &[T] or &str instead of &Vec or &String in function parameters for flexibility
Use .is_empty() instead of .len() == 0 or .len() > 0 / .len() != 0
Don't assign () to a variable: write foo(); instead of let _ = foo(); or let x = foo(); when return is unit
Use .unwrap_or(val) instead of .unwrap_or_else(|| val) when the default is a simple/cheap value
Use 'for item in &collection' or 'for (i, item) in collection.iter().enumerate()' instead of 'for i in 0..collection.len()'
Use value.clamp(min, max) instead of manual if chains or .min(max).max(min) patterns
Always handle Result/Option or types marked #[must_use]; never ignore them
**/*.rs: Userustfmtand workspace clippy lints for Rust code formatting and linting
Use snake_case for Rust module names and kebab-case for crate names
Never usedbg!()macro in Rust code; use proper logging instead (Clippy:dbg_macro= deny)
Always handleResult/Optionor types marked#[must_use]; never ignore them (Rust compiler lint:unused_must_use= deny)
Never writelet _ = async_fn()which silently drops futures; await or explicitly handle them (Clippy:let_underscore_future= deny)
Usesaturating_subinstead of-forDurationto avoid panics (Clippy:unchecked_duration_subtraction= deny)
Merge nestedifstatements: useif a && b { }instead ofif a { if b { } }(Clippy:collapsible_if= deny)
Don't call.clone()onCopytypes; just copy them directly (Clippy:clone_on_copy= deny)
U...
Files:
crates/project/src/configuration.rscrates/rendering/src/lib.rs
**/*.tsx
📄 CodeRabbit inference engine (CLAUDE.md)
Use React Query hooks with Server Actions for mutations and perform precise cache updates using setQueryData/setQueriesData instead of broad invalidations
Files:
apps/desktop/src/routes/editor/ConfigSidebar.tsx
🧬 Code graph analysis (2)
apps/desktop/src/routes/editor/context.ts (1)
apps/desktop/src/utils/tauri.ts (1)
ProjectConfiguration(460-460)
apps/desktop/src/routes/editor/ConfigSidebar.tsx (1)
apps/desktop/src/routes/editor/ui.tsx (2)
Slider(65-149)Field(25-47)
⏰ 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). (4)
- GitHub Check: Clippy (aarch64-apple-darwin, macos-latest)
- GitHub Check: Clippy (x86_64-pc-windows-msvc, windows-latest)
- GitHub Check: Format (Biome)
- GitHub Check: Cursor Bugbot
🔇 Additional comments (3)
apps/desktop/src/routes/editor/context.ts (1)
108-116: Direct background/camera typing and serialization look consistent with new config shapeUsing
ProjectConfiguration["background"]/["camera"]directly and round‑tripping them unchanged inserializeProjectConfigurationcorrectly aligns the editor state with the updated TauriProjectConfiguration(including new rounding/roundingSmoothness fields). I don’t see issues here.Also applies to: 146-164
apps/desktop/src/routes/editor/ConfigSidebar.tsx (1)
68-68: Rounding and corner-smoothness sliders are correctly wired to project configuration
- Background sliders:
Rounded Cornersusesproject.background.roundingin[0, 100]with%tooltip.Corner Smoothnessusesproject.background.roundingSmoothness ?? 0in[0, 1]with a%tooltip; with Rust default of0.6, this will show as 60% for new/legacy configs.- Camera sliders:
Rounded Cornersusesproject.camera.rounding ?? 0in[0, 100].Corner Smoothnessusesproject.camera.roundingSmoothness ?? 0in[0, 1], defaulting to0.0which matches the RustCamera::default.Importing
useEditorContextfrom./contextis required for these bindings and is consistent with existing usage in this file. No functional issues from this set of changes.Also applies to: 1984-2005, 2342-2363
crates/rendering/src/lib.rs (1)
2-5: Rounding radius and exponent computation are correctly tied to new smoothness fields
- Display path:
rounding_pxis nowcompute_adjusted_radius((background.rounding / 100) * 0.5 * min_target_axis, background.rounding_smoothness), which keeps the capsule behavior and adds visual normalization as smoothness changes.corner_exponentcomes fromsmoothness_to_exponent(background.rounding_smoothness), giving the shader a consistent exponent in[2, 8].- Camera path:
- Mirrors the same pattern using
project.camera.roundingandproject.camera.rounding_smoothness, so the new “Camera Corner Smoothness” slider actually affects the rendered camera shape (unlike the earlier background‑smoothness wiring issue).- Camera‑only path:
- With
rounding_px: 0.0andcorner_exponent: 0.0, corners are effectively disabled in this mode, which lines up withrounding_pxbeing zero.Overall the rendering side is now in sync with the new numeric smoothness model and the UI bindings.
Also applies to: 1200-1217, 1384-1398, 1486-1497
| /* | ||
| this is a Tauri bug in WebKit so we need to validate the file type manually | ||
| https://github.com/tauri-apps/tauri/issues/9158 | ||
| */ | ||
| this is a Tauri bug in WebKit so we need to validate the file type manually | ||
| https://github.com/tauri-apps/tauri/issues/9158 | ||
| */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion | 🟠 Major
Remove the Tauri bug comment block to match “no comments” guideline
The multi‑line /* ... */ comment about the Tauri WebKit bug was modified in this PR and violates the guideline that .ts/.tsx/.js/.jsx/.rs files should not contain code comments. The surrounding code (manual extension validation) is already self‑explanatory.
Consider deleting this block entirely and, if needed, capturing the context in commit messages or external docs instead.
🤖 Prompt for AI Agents
In apps/desktop/src/routes/editor/ConfigSidebar.tsx around lines 1715 to 1718,
remove the multi-line comment block (/* this is a Tauri bug in WebKit so we need
to validate the file type manually
https://github.com/tauri-apps/tauri/issues/9158 */) so the file complies with
the "no comments" guideline; delete the block only and keep the surrounding
manual extension validation code unchanged, and capture any needed rationale in
the PR description or external docs instead.
This PR removes the corner shapes and instead adds a smoothness level slider (with 0.6 as default, same as Apple's human interface guidelines).
The radius is normalized internally when any smoothness is set to keep the visual radius look similar to a normal rounded rectangle.
Summary by CodeRabbit
New Features
UI/UX Improvements
Other
✏️ Tip: You can customize this high-level summary in your review settings.
Note
Replaces the corner style selector with a Corner Smoothness slider and switches rendering to superellipse-based rounding with normalized radius across editor and screenshot UIs, updating config/types and shaders accordingly.
roundingTypeto superellipse-based corners usingcorner_exponent; addsmoothness_to_exponentandcompute_adjusted_radiusfor consistent visual radius.CompositeVideoFrameUniforms(rounding_type→corner_exponent), propagate throughlib.rs, and modify WGSL shader to use exponent for SDF and borders.roundingTypewithroundingSmoothnessinBackgroundConfigurationandCamera; defaults set (0.6background,0.0camera).CornerRoundingType/normalizers; adjust serialization/normalization.Corner Smoothnesssliders alongsideRounded CornersforbackgroundandcamerainConfigSidebar.tsx.RoundingPopoverto includeRounding Smoothness; remove corner style select.IconLucideSquareRoundCornerfor smoothness control.Written by Cursor Bugbot for commit be6d45b. This will update automatically on new commits. Configure here.