Skip to content

feat: implement wallpaper match color mode with fallback extractor#330

Merged
SamXop123 merged 3 commits into
SamXop123:mainfrom
bhavyasanthoshi02:feature/wallpaper-accent-palette
Jul 5, 2026
Merged

feat: implement wallpaper match color mode with fallback extractor#330
SamXop123 merged 3 commits into
SamXop123:mainfrom
bhavyasanthoshi02:feature/wallpaper-accent-palette

Conversation

@bhavyasanthoshi02

@bhavyasanthoshi02 bhavyasanthoshi02 commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Description

This PR implements the "Wallpaper Match" color mode feature, allowing Paraline to dynamically capture and adapt to the dominant accent colors of the user's active Windows desktop wallpaper.

Key Changes

  1. Registry & Color Extraction (C# Helper): Updated the audio-bridge helper to monitor the Windows registry wallpaper path, downsample the image, and run a distinct color bucket extraction algorithm to yield the 3 most dominant/distinct colors.
  2. Node.js Fallback Extractor: Implemented a pure Node.js fallback in main.js that triggers if the C# helper is unavailable or in simulated mode, using Electron's nativeImage to ensure robustness.
  3. Settings Page: Added the "Wallpaper Match" option to the Color Mode select dropdown in settings.html and integrated validation in settingsStore.js.
  4. Renderer Transition: Overrode visualizer themes in renderer.js to dynamically apply the wallpaper colors with smooth animation blending.
  5. Testing: Added settingsStore sanitization tests to verify wallpaperColors format safety; all 15 unit tests pass cleanly.

Summary by CodeRabbit

  • New Features

    • Added a new Wallpaper Match color mode.
    • The app can now derive and apply theme colors from the current Windows wallpaper.
    • Wallpaper colors are now shared across the app and reflected in visual settings.
  • Bug Fixes

    • Improved color mode handling so wallpaper-based themes update reliably.
    • Added validation to keep wallpaper color values consistent and well-formed.
  • Tests

    • Added coverage for wallpaper color sanitization behavior.

@vercel

vercel Bot commented Jul 2, 2026

Copy link
Copy Markdown

@bhavyasanthoshi02 is attempting to deploy a commit to the Dot_NotSam's projects Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai

coderabbitai Bot commented Jul 2, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Adds a "Wallpaper Match" color mode: a native audio-helper WallpaperColorExtractor reads the Windows wallpaper registry path, quantizes the image into up to three colors, and emits them via stdout JSON. audioBridge.js and main.js relay these colors to the renderer, which resolves theme/palette settings accordingly, with new settings validation and a UI option.

Changes

Wallpaper Match Feature

Layer / File(s) Summary
Native wallpaper color extraction
audio-helper/Paraline.AudioBridge.csproj, audio-helper/Program.cs
Adds System.Drawing.Common dependency and a WallpaperColorExtractor class that reads the wallpaper registry path, quantizes the wallpaper image into up to three colors, and periodically writes {type:"colors", value:[...]} to stdout from the capture loop.
Bridge transport and main process polling
audioBridge.js, main.js
createAudioBridge gains a sendColors callback dispatched on type === "colors" messages; main.js adds wallpaper polling state (latestWallpaperColors), registry/image extraction fallback logic, exposes wallpaperColors via getRendererSettings(), and reconciles polling on settings updates, status changes, startup, and shutdown cleanup.
Renderer palette/theme integration and settings validation
renderer.js, settings.html, settingsStore.js, test/settingsStore.test.js
renderer.js adds a wallpaper branch in palette syncing, stepping, and theme resolution (including auroraDrift gradient stops); settings.html adds a "Wallpaper Match" selector option; settingsStore.js validates colorMode: "wallpaper" and sanitizes wallpaperColors, with new unit tests covering sanitization behavior.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Helper as AudioHelperProcess
  participant Bridge as audioBridge.js
  participant Main as main.js
  participant Renderer as renderer.js

  Helper->>Helper: WallpaperColorExtractor.GetWallpaperColors()
  Helper->>Bridge: stdout {type:"colors", value}
  Bridge->>Main: sendColors(colors)
  Main->>Main: updateWallpaperColors(colors)
  Main->>Main: reconcileWallpaperPolling()
  Main->>Renderer: sendVisualizerSettings(wallpaperColors)
  Renderer->>Renderer: syncAdaptivePaletteTarget() / getResolvedThemeSettings()
  Renderer->>Renderer: render themed visualizer with wallpaper palette
Loading

Possibly related issues

Possibly related PRs

  • SamXop123/Paraline#90: Both extend the same colorMode/palette-resolution pipeline in renderer.js and related settings plumbing, with this PR adding a wallpaper-driven mode alongside the existing adaptive mode.

Suggested reviewers: SamXop123

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: adding a wallpaper match color mode with a fallback extractor.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

@SamXop123 SamXop123 left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Great work on the PR 👍🏻
The code is very well written

@vercel

vercel Bot commented Jul 5, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
paraline Ready Ready Preview, Comment Jul 5, 2026 6:31pm

@SamXop123 SamXop123 force-pushed the feature/wallpaper-accent-palette branch from 81f71b6 to e933409 Compare July 5, 2026 18:29
@SamXop123

Copy link
Copy Markdown
Owner

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 5, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@SamXop123 SamXop123 merged commit dbaae83 into SamXop123:main Jul 5, 2026
5 of 6 checks passed
@github-actions

github-actions Bot commented Jul 5, 2026

Copy link
Copy Markdown

🎉 Congratulations @bhavyasanthoshi02! 🎉

Your pull request has been successfully merged into Paraline! Thank you so much for your valuable contribution and effort. Every single improvement helps make Paraline a better desktop experience for everyone! 🙌

🚀 What's Next?

  • Keep the momentum going! Feel free to browse through our open Issues and grab another one that interests you!
  • Support the Project: If you enjoyed contributing to Paraline, please take a second to star our repository! It helps increase the project's visibility and supports our community. ⭐

💬 Stay Connected:
Have any questions, want feedback, or just want to discuss further contributions? Feel free to reach out directly to the maintainer on Discord: dot_notsam!

Thank you again, and keep up the amazing work! 💻✨

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

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)
audio-helper/Program.cs (1)

585-610: 🎯 Functional Correctness | 🔵 Trivial | 💤 Low value

Relaxed second pass may emit near-duplicate colors.

The fallback loop only rejects colors within < 5.0 distance, so when fewer than 3 distinct colors are found it can add visually indistinguishable buckets. Consider progressively lowering the primary 45.0 threshold rather than dropping to 5.0, to keep the palette meaningfully distinct.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@audio-helper/Program.cs` around lines 585 - 610, The fallback palette
selection in Program.cs can still add visually near-duplicate colors because the
second pass only checks a very small ColorDistance threshold. Update the
distinct-colors logic in the fallback loop to keep using a meaningful separation
by progressively relaxing the primary threshold from the initial distinct-colors
pass instead of switching to the much looser check; focus on the distinctColors,
sortedBuckets, and ColorDistance logic so the final three colors remain clearly
different.
main.js (1)

221-223: 🔒 Security & Privacy | 🔵 Trivial | 💤 Low value

Prefer execFile over exec for the static registry query.

The command has no user input so this isn't exploitable, but execFile("reg", ["query", "HKCU\\Control Panel\\Desktop", "/v", "Wallpaper"]) avoids a shell and silences the detect-child-process warning.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@main.js` around lines 221 - 223, The Windows wallpaper lookup in the registry
query block uses child_process exec for a static command, which triggers an
unnecessary shell warning. Update the logic around the exec call in main.js to
use execFile instead, invoking reg with the fixed query arguments directly from
the same Windows-only branch so the behavior stays the same without a shell.

Source: Linters/SAST tools

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@audio-helper/Program.cs`:
- Around line 36-52: Move wallpaper color extraction out of the main capture
loop so `ReadLevel()` and level emission are not delayed by
`WallpaperColorExtractor.GetWallpaperColors()`. Refactor the wallpaper refresh
logic in `Program.Main` into a separate background worker or `Timer`, and keep
the existing `while (true)` loop focused on audio capture and payload output.
Preserve the current `lastWallpaperCheck` cadence or equivalent scheduling in
the background path, and continue serializing and writing the colors payload
from there.

In `@main.js`:
- Around line 225-226: The fallback wallpaper registry parsing in stdout.match
is using a regex that matches literal backslash-s sequences instead of
whitespace, so it returns early on normal reg query output. Update the regex in
the main.js fallback logic around stdout.match and the match check to use a
whitespace matcher that correctly captures the Wallpaper REG_SZ value, while
keeping the early return only when the capture is actually missing.

---

Nitpick comments:
In `@audio-helper/Program.cs`:
- Around line 585-610: The fallback palette selection in Program.cs can still
add visually near-duplicate colors because the second pass only checks a very
small ColorDistance threshold. Update the distinct-colors logic in the fallback
loop to keep using a meaningful separation by progressively relaxing the primary
threshold from the initial distinct-colors pass instead of switching to the much
looser check; focus on the distinctColors, sortedBuckets, and ColorDistance
logic so the final three colors remain clearly different.

In `@main.js`:
- Around line 221-223: The Windows wallpaper lookup in the registry query block
uses child_process exec for a static command, which triggers an unnecessary
shell warning. Update the logic around the exec call in main.js to use execFile
instead, invoking reg with the fixed query arguments directly from the same
Windows-only branch so the behavior stays the same without a shell.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: f9af7f0b-128b-4911-9117-82ca344b84fa

📥 Commits

Reviewing files that changed from the base of the PR and between b207f7c and 1b25b6c.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (8)
  • audio-helper/Paraline.AudioBridge.csproj
  • audio-helper/Program.cs
  • audioBridge.js
  • main.js
  • renderer.js
  • settings.html
  • settingsStore.js
  • test/settingsStore.test.js

Comment thread audio-helper/Program.cs
Comment on lines +36 to +52

// Periodically check wallpaper (every 5 seconds)
if ((DateTime.Now - lastWallpaperCheck).TotalSeconds >= 5)
{
lastWallpaperCheck = DateTime.Now;
var colors = WallpaperColorExtractor.GetWallpaperColors();
if (colors != null)
{
var colorsPayload = JsonSerializer.Serialize(new
{
type = "colors",
value = colors
});
Console.WriteLine(colorsPayload);
}
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🚀 Performance & Scalability | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Map the relevant file and inspect the surrounding code.
git ls-files audio-helper/Program.cs
wc -l audio-helper/Program.cs
cat -n audio-helper/Program.cs | sed -n '1,220p'

Repository: SamXop123/Paraline

Length of output: 9433


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect the wallpaper extraction implementation and any related call sites.
ast-grep outline audio-helper/Program.cs --view expanded
printf '\n---\n'
rg -n "GetWallpaperColors|WallpaperColorExtractor|GetPixel|Resize|Clone|Bitmap" audio-helper/Program.cs
printf '\n--- function slice ---\n'
cat -n audio-helper/Program.cs | sed -n '520,640p'

Repository: SamXop123/Paraline

Length of output: 6481


Move wallpaper extraction off the capture loop. GetWallpaperColors() runs synchronously in the same while (true) loop as ReadLevel(), so every wallpaper refresh can delay level emission. A background worker/Timer would keep the audio cadence steady.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@audio-helper/Program.cs` around lines 36 - 52, Move wallpaper color
extraction out of the main capture loop so `ReadLevel()` and level emission are
not delayed by `WallpaperColorExtractor.GetWallpaperColors()`. Refactor the
wallpaper refresh logic in `Program.Main` into a separate background worker or
`Timer`, and keep the existing `while (true)` loop focused on audio capture and
payload output. Preserve the current `lastWallpaperCheck` cadence or equivalent
scheduling in the background path, and continue serializing and writing the
colors payload from there.

Comment thread main.js
Comment on lines +225 to +226
const match = stdout.match(/Wallpaper\\s+REG_SZ\\s+(.*)/);
if (!match || !match[1]) return;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Confirm the buggy escaping in the wallpaper registry parse
rg -nP 'Wallpaper\\\\s\+REG_SZ' main.js

Repository: SamXop123/Paraline

Length of output: 223


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect the relevant section of main.js with line numbers.
sed -n '210,240p' main.js

# Show the exact regex text and nearby logic.
grep -n "Wallpaper\\\\s\\+REG_SZ" -n main.js || true

# Demonstrate how the current regex behaves against typical reg query output.
node - <<'JS'
const samples = [
  'Wallpaper    REG_SZ    C:\\Users\\me\\wall.jpg',
  'Wallpaper\tREG_SZ\tC:\\Users\\me\\wall.jpg',
  'Wallpaper\\sREG_SZ\\sC:\\Users\\me\\wall.jpg',
];
const re = /Wallpaper\\s+REG_SZ\\s+(.*)/;
for (const s of samples) {
  const m = s.match(re);
  console.log(JSON.stringify({sample: s, matched: !!m, capture: m && m[1] || null}));
}
JS

Repository: SamXop123/Paraline

Length of output: 1367


Fix the wallpaper registry regex

stdout.match() never hits here because /Wallpaper\\s+REG_SZ\\s+(.*)/ looks for literal \s, not whitespace. The Node fallback returns early on normal reg query output, so wallpaper colors stay at defaults when the C# helper isn’t used.

Proposed fix
-    const match = stdout.match(/Wallpaper\\s+REG_SZ\\s+(.*)/);
+    const match = stdout.match(/Wallpaper\s+REG_SZ\s+(.*)/);
📝 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 match = stdout.match(/Wallpaper\\s+REG_SZ\\s+(.*)/);
if (!match || !match[1]) return;
const match = stdout.match(/Wallpaper\s+REG_SZ\s+(.*)/);
if (!match || !match[1]) return;
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@main.js` around lines 225 - 226, The fallback wallpaper registry parsing in
stdout.match is using a regex that matches literal backslash-s sequences instead
of whitespace, so it returns early on normal reg query output. Update the regex
in the main.js fallback logic around stdout.match and the match check to use a
whitespace matcher that correctly captures the Wallpaper REG_SZ value, while
keeping the early return only when the capture is actually missing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants