Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
153 changes: 46 additions & 107 deletions apps/desktop/src/routes/editor/ConfigSidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ import IconLucideTimer from "~icons/lucide/timer";
import IconLucideType from "~icons/lucide/type";
import IconLucideWind from "~icons/lucide/wind";
import { CaptionsTab } from "./CaptionsTab";
import { type CornerRoundingType, useEditorContext } from "./context";
import { useEditorContext } from "./context";
import { evaluateMask, type MaskKind, type MaskSegment } from "./masks";
import {
DEFAULT_GRADIENT_FROM,
Expand Down Expand Up @@ -219,11 +219,6 @@ const CAMERA_SHAPES = [
},
] satisfies Array<{ name: string; value: CameraShape }>;

const CORNER_STYLE_OPTIONS = [
{ name: "Squircle", value: "squircle" },
{ name: "Rounded", value: "rounded" },
] satisfies Array<{ name: string; value: CornerRoundingType }>;

const BACKGROUND_THEMES = {
macOS: "macOS",
dark: "Dark",
Expand Down Expand Up @@ -1718,9 +1713,9 @@ function BackgroundConfig(props: { scrollRef: HTMLDivElement }) {
if (!file) return;

/*
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
*/
Comment on lines 1715 to +1718
Copy link
Contributor

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.

const validExtensions = [
"jpg",
"jpeg",
Expand Down Expand Up @@ -1986,23 +1981,27 @@ function BackgroundConfig(props: { scrollRef: HTMLDivElement }) {
/>
</Field>
<Field name="Rounded Corners" icon={<IconCapCorners class="size-4" />}>
<div class="flex flex-col gap-3">
<Slider
value={[project.background.rounding]}
onChange={(v) => setProject("background", "rounding", v[0])}
minValue={0}
maxValue={100}
step={0.1}
formatTooltip="%"
/>
<CornerStyleSelect
label="Corner Style"
value={project.background.roundingType}
onChange={(value) =>
setProject("background", "roundingType", value)
}
/>
</div>
<Slider
value={[project.background.rounding]}
onChange={(v) => setProject("background", "rounding", v[0])}
minValue={0}
maxValue={100}
step={0.1}
formatTooltip="%"
/>
</Field>
<Field
name="Corner Smoothness"
icon={<IconLucideSquareRoundCorner class="size-4" />}
>
<Slider
value={[project.background.roundingSmoothness ?? 0]}
onChange={(v) => setProject("background", "roundingSmoothness", v[0])}
minValue={0}
maxValue={1}
step={0.01}
formatTooltip={(value) => `${Math.round(value * 100)}%`}
/>
</Field>
<Field name="Motion Blur" icon={<IconLucideWind class="size-4" />}>
<Slider
Expand Down Expand Up @@ -2340,21 +2339,27 @@ function CameraConfig(props: { scrollRef: HTMLDivElement }) {
/>
</Field>
<Field name="Rounded Corners" icon={<IconCapCorners class="size-4" />}>
<div class="flex flex-col gap-3">
<Slider
value={[project.camera.rounding!]}
onChange={(v) => setProject("camera", "rounding", v[0])}
minValue={0}
maxValue={100}
step={0.1}
formatTooltip="%"
/>
<CornerStyleSelect
label="Corner Style"
value={project.camera.roundingType}
onChange={(value) => setProject("camera", "roundingType", value)}
/>
</div>
<Slider
value={[project.camera.rounding!]}
onChange={(v) => setProject("camera", "rounding", v[0])}
minValue={0}
maxValue={100}
step={0.1}
formatTooltip="%"
/>
</Field>
<Field
name="Corner Smoothness"
icon={<IconLucideSquareRoundCorner class="size-4" />}
>
<Slider
value={[project.camera.roundingSmoothness ?? 0]}
onChange={(v) => setProject("camera", "roundingSmoothness", v[0])}
minValue={0}
maxValue={1}
step={0.01}
formatTooltip={(value) => `${Math.round(value * 100)}%`}
/>
</Field>
<Field name="Shadow" icon={<IconCapShadow class="size-4" />}>
<div class="space-y-8">
Expand Down Expand Up @@ -2425,72 +2430,6 @@ function CameraConfig(props: { scrollRef: HTMLDivElement }) {
);
}

function CornerStyleSelect(props: {
label?: string;
value: CornerRoundingType;
onChange: (value: CornerRoundingType) => void;
}) {
return (
<div class="flex flex-col gap-1.5">
<Show when={props.label}>
{(label) => (
<span class="text-[0.65rem] uppercase tracking-wide text-gray-11">
{label()}
</span>
)}
</Show>
<KSelect<{ name: string; value: CornerRoundingType }>
options={CORNER_STYLE_OPTIONS}
optionValue="value"
optionTextValue="name"
value={CORNER_STYLE_OPTIONS.find(
(option) => option.value === props.value,
)}
onChange={(option) => option && props.onChange(option.value)}
disallowEmptySelection
itemComponent={(itemProps) => (
<MenuItem<typeof KSelect.Item>
as={KSelect.Item}
item={itemProps.item}
>
<KSelect.ItemLabel class="flex-1">
{itemProps.item.rawValue.name}
</KSelect.ItemLabel>
</MenuItem>
)}
>
<KSelect.Trigger class="flex flex-row gap-2 items-center px-2 w-full h-8 rounded-lg transition-colors bg-gray-3 disabled:text-gray-11">
<KSelect.Value<{
name: string;
value: CornerRoundingType;
}> class="flex-1 text-sm text-left truncate text-[--gray-500] font-normal">
{(state) => <span>{state.selectedOption().name}</span>}
</KSelect.Value>
<KSelect.Icon<ValidComponent>
as={(iconProps) => (
<IconCapChevronDown
{...iconProps}
class="size-4 shrink-0 transform transition-transform ui-expanded:rotate-180 text-[--gray-500]"
/>
)}
/>
</KSelect.Trigger>
<KSelect.Portal>
<PopperContent<typeof KSelect.Content>
as={KSelect.Content}
class={cx(topSlideAnimateClasses, "z-50")}
>
<MenuItemList<typeof KSelect.Listbox>
class="overflow-y-auto max-h-32"
as={KSelect.Listbox}
/>
</PopperContent>
</KSelect.Portal>
</KSelect>
</div>
);
}

const TEXT_FONT_OPTIONS = [
{ value: "sans-serif", label: "Sans" },
{ value: "serif", label: "Serif" },
Expand Down
36 changes: 4 additions & 32 deletions apps/desktop/src/routes/editor/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,10 +86,6 @@ export type CustomDomainResponse = {
domain_verified: boolean | null;
};

export type CornerRoundingType = "rounded" | "squircle";

type WithCornerStyle<T> = T & { roundingType: CornerRoundingType };

type EditorTimelineConfiguration = Omit<
TimelineConfiguration,
"sceneSegments" | "maskSegments"
Expand All @@ -103,25 +99,12 @@ export type EditorProjectConfiguration = Omit<
ProjectConfiguration,
"background" | "camera" | "timeline"
> & {
background: WithCornerStyle<ProjectConfiguration["background"]>;
camera: WithCornerStyle<ProjectConfiguration["camera"]>;
background: ProjectConfiguration["background"];
camera: ProjectConfiguration["camera"];
timeline?: EditorTimelineConfiguration | null;
hiddenTextSegments?: number[];
};

function withCornerDefaults<
T extends {
roundingType?: CornerRoundingType;
rounding_type?: CornerRoundingType;
},
>(value: T): T & { roundingType: CornerRoundingType } {
const roundingType = value.roundingType ?? value.rounding_type ?? "squircle";
return {
...value,
roundingType,
};
}

export function normalizeProject(
config: ProjectConfiguration,
): EditorProjectConfiguration {
Expand All @@ -147,18 +130,13 @@ export function normalizeProject(
return {
...config,
timeline,
background: withCornerDefaults(config.background),
camera: withCornerDefaults(config.camera),
};
}

export function serializeProjectConfiguration(
project: EditorProjectConfiguration,
): ProjectConfiguration {
const { background, camera, ...rest } = project;
const { roundingType: backgroundRoundingType, ...backgroundRest } =
background;
const { roundingType: cameraRoundingType, ...cameraRest } = camera;

const timeline = project.timeline
? {
Expand All @@ -171,14 +149,8 @@ export function serializeProjectConfiguration(
return {
...rest,
timeline: timeline as unknown as ProjectConfiguration["timeline"],
background: {
...backgroundRest,
roundingType: backgroundRoundingType,
},
camera: {
...cameraRest,
roundingType: cameraRoundingType,
},
background,
camera,
};
}

Expand Down
5 changes: 2 additions & 3 deletions apps/desktop/src/utils/tauri.ts
Original file line number Diff line number Diff line change
Expand Up @@ -357,10 +357,10 @@ export type AudioMeta = { path: string;
start_time?: number | null }
export type AuthSecret = { api_key: string } | { token: string; expires: number }
export type AuthStore = { secret: AuthSecret; user_id: string | null; plan: Plan | null; intercom_hash: string | null; organizations?: Organization[] }
export type BackgroundConfiguration = { source: BackgroundSource; blur: number; padding: number; rounding: number; roundingType?: CornerStyle; inset: number; crop: Crop | null; shadow?: number; advancedShadow?: ShadowConfiguration | null; border?: BorderConfiguration | null }
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 }
Copy link

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.

Fix in Cursor Fix in Web

export type Camera = { hide: boolean; mirror: boolean; position: CameraPosition; size: number; zoomSize: number | null; rounding?: number; shadow?: number; advancedShadow?: ShadowConfiguration | null; shape?: CameraShape; roundingSmoothness?: number }
export type CameraInfo = { device_id: string; model_id: ModelIDType | null; display_name: string }
export type CameraPosition = { x: CameraXPosition; y: CameraYPosition }
export type CameraPreviewShape = "round" | "square" | "full"
Expand All @@ -380,7 +380,6 @@ export type CaptureWindowWithThumbnail = { id: WindowId; owner_name: string; nam
export type ClipConfiguration = { index: number; offsets: ClipOffsets }
export type ClipOffsets = { camera?: number; mic?: number; system_audio?: number }
export type CommercialLicense = { licenseKey: string; expiryDate: number | null; refresh: number; activatedOn: number }
export type CornerStyle = "squircle" | "rounded"
export type Crop = { position: XY<number>; size: XY<number> }
export type CurrentRecording = { target: CurrentRecordingTarget; mode: RecordingMode; status: RecordingStatus }
export type CurrentRecordingChanged = null
Expand Down
12 changes: 6 additions & 6 deletions crates/project/src/configuration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,7 @@ pub struct BackgroundConfiguration {
pub padding: f64,
pub rounding: f64,
#[serde(default)]
pub rounding_type: CornerStyle,
pub rounding_smoothness: f32,
pub inset: u32,
pub crop: Option<Crop>,
#[serde(default)]
Expand Down Expand Up @@ -256,12 +256,12 @@ impl Default for BackgroundConfiguration {
blur: 0.0,
padding: 0.0,
rounding: 0.0,
rounding_type: CornerStyle::default(),
rounding_smoothness: 0.6,
inset: 0,
crop: None,
shadow: 73.6,
advanced_shadow: Some(ShadowConfiguration::default()),
border: None, // Border is disabled by default for backwards compatibility
border: None,
}
}
}
Expand Down Expand Up @@ -307,8 +307,8 @@ pub struct Camera {
pub advanced_shadow: Option<ShadowConfiguration>,
#[serde(default)]
pub shape: CameraShape,
#[serde(alias = "rounding_type", default)]
pub rounding_type: CornerStyle,
#[serde(default)]
pub rounding_smoothness: f32,
}

#[derive(Debug, Clone, Copy, Serialize, Deserialize, Type, Default)]
Expand Down Expand Up @@ -345,7 +345,7 @@ impl Default for Camera {
blur: 10.5,
}),
shape: CameraShape::Square,
rounding_type: CornerStyle::default(),
rounding_smoothness: 0.0,
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions crates/rendering/src/composite_frame.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ pub struct CompositeVideoFrameUniforms {
pub motion_blur_params: [f32; 4],
pub target_size: [f32; 2],
pub rounding_px: f32,
pub rounding_type: f32,
pub corner_exponent: f32,
pub mirror_x: f32,
pub shadow: f32,
pub shadow_size: f32,
Expand Down Expand Up @@ -48,7 +48,7 @@ impl Default for CompositeVideoFrameUniforms {
motion_blur_params: Default::default(),
target_size: Default::default(),
rounding_px: Default::default(),
rounding_type: 0.0,
corner_exponent: Default::default(),
mirror_x: Default::default(),
shadow: Default::default(),
shadow_size: Default::default(),
Expand Down
Loading
Loading