Skip to content

Comments

fix#24

Merged
epavanello merged 7 commits intomainfrom
feat/test
Feb 16, 2026
Merged

fix#24
epavanello merged 7 commits intomainfrom
feat/test

Conversation

@epavanello
Copy link
Owner

@epavanello epavanello commented Feb 15, 2026

Summary by CodeRabbit

  • New Features

    • Project Settings added as a dedicated, non-removable entry at the top of the Layers panel for editing project properties (resolution, duration, background, default font). Project icon and name appear in the header.
  • Changes

    • Settings button removed from the toolbar; access project configuration via the Layers panel.
    • Properties panel now exposes project-specific controls and hides layer-only controls for the virtual project entry.
    • Empty-layer message updated to "No animation layers yet".
    • Export dialog default format/height binding behavior adjusted.

claude and others added 3 commits February 15, 2026 17:12
…list

Replace the project settings modal with a virtual "project-settings" layer
that sits fixed at the top of the layers panel. When selected, the properties
panel shows project-level fields (dimensions, duration, background, font)
using the same dynamic property system as regular layers, but without
transform, style, time range, keyframe, or animation preset sections.

Key changes:
- New ProjectSettingsLayer.svelte component registered in the layer system
- New project-layer.ts with constants, virtual layer synthesis, and helpers
- ProjectStore auto-selects the project layer on init and loadProject
- Layers panel renders project layer as a fixed, non-draggable, non-deletable item
- Properties panel routes project layer property updates to updateProject()
- Toolbar and project-settings-dialog modal references removed

https://claude.ai/code/session_01REigfXtKvZKtz2JF8sF5HL
Clarify that the empty state refers to animation layers, not the project
settings layer which is always visible. Add a visual separator and update
the message to be more specific and helpful.

Changes:
- Message: "No layers yet" → "No animation layers yet"
- Action: "Add layers from the toolbar" → "Click the + button above to add your first layer"
- Added border-top separator to visually distinguish from project settings layer

https://claude.ai/code/session_01REigfXtKvZKtz2JF8sF5HL
@coderabbitai
Copy link

coderabbitai bot commented Feb 15, 2026

Warning

Rate limit exceeded

@epavanello has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 15 minutes and 46 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📝 Walkthrough

Walkthrough

Adds a virtual "Project Settings" layer accessible in the layers panel and properties panel, backed by a new project-layer type and schema. Project properties (size, duration, background, default font, name) are edited via the properties panel and routed to the project store; the old toolbar dialog is removed.

Changes

Cohort / File(s) Summary
Project Settings Layer Definition
src/lib/layers/components/ProjectSettingsLayer.svelte
New layer meta and Zod schema for project-level settings (size, duration, background, fontFamily). Exports meta typed as LayerMeta.
Project Layer Utilities
src/lib/layers/project-layer.ts
Adds PROJECT_LAYER_ID, PROJECT_LAYER_TYPE, isProjectLayer(), createVirtualProjectLayer(), and mapProjectLayerPropsToProject() to synthesize and map virtual project layer ↔ project state.
Type Registry
src/lib/layers/typed-registry.ts
Registers 'project-settings' in LayerPropsMap with schema-inferred props.
Project Store
src/lib/stores/project.svelte.ts
Treats project layer as virtual: auto-selects project layer on creation/load, prevents its removal, and returns virtual layer via createVirtualProjectLayer() when selected.
Panels & UI
src/lib/components/editor/panels/add-layer.svelte, src/lib/components/editor/panels/layers-panel.svelte, src/lib/components/editor/panels/properties-panel.svelte
Hides project-settings from add-layer menu; adds fixed, non-draggable Project Settings entry at top of layers panel with divider; properties panel gains branching for project-settings (project-centric labels, hides time/content controls, routes updates to projectStore).
Toolbar
src/lib/components/editor/toolbar.svelte
Removes Settings icon, ProjectSettingsDialog import/state, and toolbar settings button (desktop + mobile).
Other edits
src/lib/components/editor/export-dialog.svelte, src/lib/ai/schemas.ts
Small edits: removed Shared PositionSchema; changed export dialog default/binding details.
Add-layer tweak
src/lib/components/editor/panels/add-layer.svelte
Added 'project-settings' to hiddenTypes set (excludes it from grouping/creation UI).

Sequence Diagram

sequenceDiagram
    participant User
    participant LayersPanel as Layers Panel
    participant ProjectStore as Project Store
    participant PropertiesPanel as Properties Panel
    participant ProjectLayer as Virtual Project Layer

    User->>LayersPanel: Open editor / view layers
    LayersPanel->>ProjectStore: request layers
    ProjectStore->>ProjectLayer: createVirtualProjectLayer(state)
    ProjectLayer-->>LayersPanel: synthesized virtual project layer
    LayersPanel->>User: render Project Settings entry at top

    User->>LayersPanel: select Project Settings
    LayersPanel->>ProjectStore: select PROJECT_LAYER_ID
    ProjectStore-->>PropertiesPanel: provide virtual project layer as selectedLayer
    PropertiesPanel->>User: render project-centric UI (Project Name, Resolution, Duration, Background, Font)

    User->>PropertiesPanel: change width/duration/background/font
    PropertiesPanel->>PropertiesPanel: mapProjectLayerPropsToProject(props)
    PropertiesPanel->>ProjectStore: updateProject(partialProject)
    ProjectStore->>ProjectStore: apply project state update
    ProjectStore-->>User: project state updated
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

  • Feat/store #17: Touches project-layer, project-store, and editor panels — strong overlap with virtual project layer integration.
  • Server side video render #13: Modifies export-dialog.svelte and export-related behavior; related to the small export-dialog edits in this diff.
  • file uploads timeline layers #16: Changes selection/remove logic in project store and layers UI; likely intersects with store and layers-panel adjustments here.

Poem

🐰✨ A little rabbit hops to say,
Project settings now live in play.
No dialog box — just a layer on top,
Resize, color, font — edit nonstop! 🎨

🚥 Pre-merge checks | ✅ 3 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Title check ❓ Inconclusive The pull request title 'fix' is too vague and generic; it provides no meaningful information about the actual changes made to the codebase. Replace the title with a specific, descriptive summary of the main change, such as 'Add virtual project settings layer to layers panel' or similar.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Merge Conflict Detection ✅ Passed ✅ No merge conflicts detected when merging into main

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

✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/test

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

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.

Caution

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

⚠️ Outside diff range comments (1)
src/lib/layers/typed-registry.ts (1)

21-41: ⚠️ Potential issue | 🟠 Major

Filter project-settings from AI layer creation tools to prevent real layer instantiation of this virtual-only type.

Adding 'project-settings' to the LayerPropsMap in typed-registry.ts is correct, but it now gets auto-registered and exposed as a creatable layer to the AI. However, project-settings is designed as a virtual layer synthesized from top-level project fields—it should never be instantiated as a real layer in project.layers[].

The issue: generateLayerCreationTools() in src/lib/ai/schemas.ts lacks a guard. While 'group' is explicitly filtered out (line 144), 'project-settings' is not. This will create a create_project_settings_layer tool available to the AI, bypassing the UI-level hiding in add-layer.svelte.

Add the check after line 144:

if (layerType === 'project-settings') continue;

This follows the same pattern already in place for 'group' and ensures the AI respects the architectural constraint that project-settings exists only as a virtual layer.

🧹 Nitpick comments (3)
src/lib/stores/project.svelte.ts (1)

143-146: Consider falling back to PROJECT_LAYER_ID instead of null when a layer is removed.

After removing a selected layer, selectedLayerId is set to null, which shows the "No layer selected" empty state. Since the project settings layer is always available, falling back to it would provide a better UX — the user always sees something useful in the properties panel.

The same applies to ungroupLayers (Line 267) and other places that reset to null.

Proposed fix
     this.state.layers = this.state.layers.filter((l) => l.id !== layerId);
     if (this.selectedLayerId === layerId) {
-      this.selectedLayerId = null;
+      this.selectedLayerId = PROJECT_LAYER_ID;
     }
src/lib/layers/project-layer.ts (1)

60-69: Type assertions bypass Zod validation.

The as number / as Project['background'] casts trust that values are already valid. Since these props flow from the schema-backed UI inputs, this is likely safe in practice. However, per coding guidelines, src/lib/**/*.ts files should validate external data with Zod schemas. Consider using the schema from ProjectSettingsLayer.svelte to parse/validate before mapping, especially if this function could be called from other contexts (e.g., AI mutations).

As per coding guidelines, "Validate all external data with Zod schemas before using in the application".

src/lib/components/editor/panels/properties-panel.svelte (1)

609-619: X/Y swap in Rotation ScrubXyz appears intentional but could confuse maintainers.

valueX is bound to rotationY and valueY to rotationX, with onchangeX updating rotationY and vice versa. This X↔Y swap is presumably for the 3D scrub control's visual axis mapping, but it's not new to this PR — just flagging it as pre-existing and worth a brief comment.

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.

Caution

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

⚠️ Outside diff range comments (1)
src/lib/components/editor/export-dialog.svelte (1)

416-424: ⚠️ Potential issue | 🟡 Minor

Height input is editable but changes are silently discarded.

The binding was changed from bind:value to a one-way value, yet unlike the FPS (line 401) and Width (line 412) inputs, this one is missing the readonly attribute. The user can type into the field, but the value won't propagate back to exportSettings, making it a no-op that misleads the user.

Add readonly to match the other inputs, or restore bind:value if user editing is intended.

Proposed fix
         <Input
           id="export-height"
           type="number"
           value={exportSettings.height}
           class="col-span-3"
+          readonly
         />
🧹 Nitpick comments (2)
src/lib/components/editor/panels/properties-panel.svelte (2)

295-300: Consider guarding all targets for the project settings layer, not just props.

Currently only target === 'props' is intercepted for the project settings layer. If updateProperty is ever called with target === 'transform' or 'style' for the virtual layer (e.g., from a custom property component), it would fall through to projectStore.updateLayer with the virtual layer ID, which could produce unexpected behavior.

The UI currently prevents this, but a defensive early return would be safer:

Suggested improvement
     // For the project settings layer, route props directly to updateProject
-    if (isProjectSettings && target === 'props') {
+    if (isProjectSettings) {
+      if (target !== 'props') return; // transform/style not applicable
       const projectUpdates = mapProjectLayerPropsToProject({ [propertyName]: value });
       projectStore.updateProject(projectUpdates);
       return;
     }

807-813: addKeyframe is passed unconditionally to custom property components.

For the project settings layer, keyframes are not applicable. If a custom property component for this layer type ever calls addKeyframe, it would attempt to manipulate keyframes on the virtual layer. Consider conditionally passing it like the grouped/ungrouped fields above:

             <CustomPropertyComponent
               layer={selectedLayer}
               onUpdateProp={(name, v) => updateProperty(name, v, 'props')}
-              {addKeyframe}
+              addKeyframe={isProjectSettings ? undefined : addKeyframe}
             />

@epavanello epavanello merged commit a8e8d3d into main Feb 16, 2026
1 check passed
This was referenced Feb 16, 2026
Merged
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