Skip to content

feat: Added smooth wallpaper fade-in and fixed the widget transparency delay on page load#217

Open
prem-k-r wants to merge 3 commits into
mainfrom
fade-wallpaper
Open

feat: Added smooth wallpaper fade-in and fixed the widget transparency delay on page load#217
prem-k-r wants to merge 3 commits into
mainfrom
fade-wallpaper

Conversation

@prem-k-r

@prem-k-r prem-k-r commented May 15, 2026

Copy link
Copy Markdown
Owner

Replace CSS background-image with a fixed element for wallpapers. Adds the DOM element in index.html and styles it for full-viewport coverage and an opacity-based fade. Update wallpaper.js to set the image via URL.createObjectURL, handle load-based fade-in, revoke previous object URLs, and persist state with localStorage.hasWallpaper. Also remove the persisted flag on errors or when clearing the image and adjust toggle logic accordingly.


Summary

This PR refactors the wallpaper implementation from a CSS background-image approach to a dedicated fixed-position <img id="bg-img"> element, enabling smooth fade-in animations on page load and resolving widget transparency rendering delays.

Changes

HTML (index.html)

  • Added a new background image element (<img id="bg-img">) in the loading screen area, positioned after the existing loading screen element

JavaScript (scripts/wallpaper.js)

  • Refactored setBackground(blob) to:
    • Create an object URL and apply it to the new bg-img element
    • Implement fade-in via nested requestAnimationFrame calls that apply the bg-visible class after image load
    • Revoke previous object URLs to prevent memory leaks
    • Remove the direct --bg-image CSS variable assignment from the body element
  • Updated checkAndUpdateImage() to remove localStorage.hasWallpaper when stored data is invalid or when loading fails
  • Modified the "clear image" handler to:
    • Remove localStorage.hasWallpaper
    • Remove the bg-visible class from bg-img to hide the image
    • Revoke and nullify currentBgUrl

CSS (style.css)

  • Removed body background-image styling with fixed attachment and cover sizing
  • Added #bg-img styling with:
    • Fixed positioning to cover the full viewport
    • Visibility control via the bg-visible class using opacity transitions
    • pointer-events: none to prevent interaction
  • Ensured body maintains height: 100% and margin: 0

Documentation (CHANGELOG.md)

  • Added entry for smooth wallpaper fade-in on page load
  • Added entry for widget transparency delay fix when wallpaper is set

Review Change Stack

Replace CSS background-image with a fixed <img id="bg-img"> element for wallpapers. Adds the DOM element in index.html and styles it for full-viewport coverage and an opacity-based fade. Update wallpaper.js to set the image via URL.createObjectURL, handle load-based fade-in, revoke previous object URLs, and persist state with localStorage.hasWallpaper. Also remove the persisted flag on errors or when clearing the image and adjust toggle logic accordingly.
@prem-k-r prem-k-r added enhancement New feature or request under-review Currently being reviewed. Please wait for feedback. labels May 15, 2026
@coderabbitai

coderabbitai Bot commented May 15, 2026

Copy link
Copy Markdown

Caution

Review failed

Failed to post review comments

📝 Walkthrough

Walkthrough

This PR refactors wallpaper rendering from direct CSS variable updates to a dedicated DOM element with opacity-based fade-in. The changes introduce a background image element with staged loading, revoke prior object URLs after transitions, clean up localStorage state consistently across initialization and clear workflows, and update release documentation.

Changes

Wallpaper Fade-In Feature

Layer / File(s) Summary
Background image element and fade styling
index.html, style.css
Adds #bg-img element to markup; replaces body background-image rules with a fixed-position image container styled to fade in via opacity transitions on the bg-visible class.
Wallpaper loading and fade-in orchestration
scripts/wallpaper.js (lines 18–42)
Refactors setBackground() to manage object URL lifecycle: creates URL, waits for image load, applies bg-visible class through nested requestAnimationFrame calls to synchronize with the browser paint cycle, then revokes the prior URL.
State management and cleanup
scripts/wallpaper.js (lines 152, 171, 193–201)
Adds storage cleanup across three paths: invalid data during initialization, loading errors during startup, and the clear-image handler; each removes localStorage.hasWallpaper, resets #bg-img visibility state, and revokes object URLs.
Release documentation
CHANGELOG.md
Documents smooth wallpaper fade-in on page load and fixes widget transparency delay when wallpaper is set.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • prem-k-r/MaterialYouNewTab#209: Both PRs modify scripts/wallpaper.js to change the wallpaper blob/object-URL lifecycle—specifically deferring URL.revokeObjectURL until the new background bg-img/background is applied—so the changes are directly related.

Suggested labels

bugfix

Suggested reviewers

  • itz-rj-here
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Description check ⚠️ Warning The PR description provides a clear overview of changes but is missing several required template sections including visual evidence, issue links, and the completion checklist. Add the missing template sections: Visual Changes (screenshots/videos), Related Issues, and the Checklist with all required items marked appropriately.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely summarizes the two main changes: adding smooth wallpaper fade-in and fixing widget transparency delay on page load.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
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.

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


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.

Comment thread scripts/wallpaper.js
});
});
};
img.src = newUrl;

@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: 1

🤖 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 `@scripts/wallpaper.js`:
- Around line 24-43: The onload callback can fire after a clear and revive an
old wallpaper and leak object URLs; implement a token-based cancellation and
pending URL tracking: add a numeric bgLoadToken and pendingBgUrl variables,
increment bgLoadToken and clear img.onload/img.onerror/removeAttribute("src")
when clearing, revoke pendingBgUrl if present, and when creating newUrl set
pendingBgUrl = newUrl and capture the current token in the onload/onerror
handlers so they ignore stale tokens before assigning currentBgUrl, adding
"bg-visible" or revoking previousUrl; also ensure any errored or cancelled
newUrl is revoked and pendingBgUrl cleared to avoid leaks.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: a4862cad-2f28-4978-8c18-e341b90dec3a

📥 Commits

Reviewing files that changed from the base of the PR and between 6db3db4 and 4d367a9.

📒 Files selected for processing (6)
  • CHANGELOG.md
  • index.html
  • manifest(firefox).json
  • manifest.json
  • scripts/wallpaper.js
  • style.css

Comment thread scripts/wallpaper.js
Comment on lines +24 to 43
const img = document.getElementById("bg-img");
const previousUrl = currentBgUrl;
const newUrl = URL.createObjectURL(blob);
currentBgUrl = newUrl;
document.body.style.setProperty("--bg-image", `url(${newUrl})`);

toggleBackgroundType(true);
if (previousUrl) {
URL.revokeObjectURL(previousUrl);
}
localStorage.setItem("hasWallpaper", "true");

img.classList.remove("bg-visible"); // reset opacity for the fade-in

img.onload = () => {
requestAnimationFrame(() => {
requestAnimationFrame(() => {
currentBgUrl = newUrl;
img.classList.add("bg-visible"); // fade in only the image
if (previousUrl) URL.revokeObjectURL(previousUrl);
});
});
};
img.src = newUrl;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Prevent stale onload callbacks from restoring cleared wallpapers and leaking object URLs.

Line 33’s async onload path is not cancellable. A fast re-apply/clear sequence can let an older load callback re-show the image after clear, and intermediate object URLs can remain unreleased.

💡 Proposed fix (token-based cancellation + pending URL cleanup)
 let currentBgUrl = null;
+let pendingBgUrl = null;
+let bgLoadToken = 0;

 function setBackground(blob) {
     const img = document.getElementById("bg-img");
     const previousUrl = currentBgUrl;
     const newUrl = URL.createObjectURL(blob);
+    const loadToken = ++bgLoadToken;
+
+    // Revoke any not-yet-committed URL from a previous in-flight load.
+    if (pendingBgUrl) {
+        URL.revokeObjectURL(pendingBgUrl);
+        pendingBgUrl = null;
+    }

     toggleBackgroundType(true);
     localStorage.setItem("hasWallpaper", "true");

     img.classList.remove("bg-visible"); // reset opacity for the fade-in

     img.onload = () => {
+        if (loadToken !== bgLoadToken) {
+            URL.revokeObjectURL(newUrl);
+            return;
+        }
         requestAnimationFrame(() => {
             requestAnimationFrame(() => {
                 currentBgUrl = newUrl;
+                pendingBgUrl = null;
                 img.classList.add("bg-visible"); // fade in only the image
                 if (previousUrl) URL.revokeObjectURL(previousUrl);
             });
         });
     };
+
+    img.onerror = () => {
+        if (loadToken !== bgLoadToken) return;
+        URL.revokeObjectURL(newUrl);
+        pendingBgUrl = null;
+        localStorage.removeItem("hasWallpaper");
+        toggleBackgroundType(false);
+    };
+
+    pendingBgUrl = newUrl;
     img.src = newUrl;
 }

And when clearing, cancel in-flight loads before hiding:

const img = document.getElementById("bg-img");
bgLoadToken++;
img.onload = null;
img.onerror = null;
img.removeAttribute("src");
if (pendingBgUrl) {
  URL.revokeObjectURL(pendingBgUrl);
  pendingBgUrl = null;
}
📝 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 img = document.getElementById("bg-img");
const previousUrl = currentBgUrl;
const newUrl = URL.createObjectURL(blob);
currentBgUrl = newUrl;
document.body.style.setProperty("--bg-image", `url(${newUrl})`);
toggleBackgroundType(true);
if (previousUrl) {
URL.revokeObjectURL(previousUrl);
}
localStorage.setItem("hasWallpaper", "true");
img.classList.remove("bg-visible"); // reset opacity for the fade-in
img.onload = () => {
requestAnimationFrame(() => {
requestAnimationFrame(() => {
currentBgUrl = newUrl;
img.classList.add("bg-visible"); // fade in only the image
if (previousUrl) URL.revokeObjectURL(previousUrl);
});
});
};
img.src = newUrl;
}
let currentBgUrl = null;
let pendingBgUrl = null;
let bgLoadToken = 0;
function setBackground(blob) {
const img = document.getElementById("bg-img");
const previousUrl = currentBgUrl;
const newUrl = URL.createObjectURL(blob);
const loadToken = ++bgLoadToken;
// Revoke any not-yet-committed URL from a previous in-flight load.
if (pendingBgUrl) {
URL.revokeObjectURL(pendingBgUrl);
pendingBgUrl = null;
}
toggleBackgroundType(true);
localStorage.setItem("hasWallpaper", "true");
img.classList.remove("bg-visible"); // reset opacity for the fade-in
img.onload = () => {
if (loadToken !== bgLoadToken) {
URL.revokeObjectURL(newUrl);
return;
}
requestAnimationFrame(() => {
requestAnimationFrame(() => {
currentBgUrl = newUrl;
pendingBgUrl = null;
img.classList.add("bg-visible"); // fade in only the image
if (previousUrl) URL.revokeObjectURL(previousUrl);
});
});
};
img.onerror = () => {
if (loadToken !== bgLoadToken) return;
URL.revokeObjectURL(newUrl);
pendingBgUrl = null;
localStorage.removeItem("hasWallpaper");
toggleBackgroundType(false);
};
pendingBgUrl = newUrl;
img.src = newUrl;
}
🤖 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 `@scripts/wallpaper.js` around lines 24 - 43, The onload callback can fire
after a clear and revive an old wallpaper and leak object URLs; implement a
token-based cancellation and pending URL tracking: add a numeric bgLoadToken and
pendingBgUrl variables, increment bgLoadToken and clear
img.onload/img.onerror/removeAttribute("src") when clearing, revoke pendingBgUrl
if present, and when creating newUrl set pendingBgUrl = newUrl and capture the
current token in the onload/onerror handlers so they ignore stale tokens before
assigning currentBgUrl, adding "bg-visible" or revoking previousUrl; also ensure
any errored or cancelled newUrl is revoked and pendingBgUrl cleared to avoid
leaks.

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

Labels

enhancement New feature or request under-review Currently being reviewed. Please wait for feedback.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants