Skip to content

issue #11: favicon fix#58

Open
sushilbang wants to merge 1 commit intosohzm:masterfrom
sushilbang:favicon
Open

issue #11: favicon fix#58
sushilbang wants to merge 1 commit intosohzm:masterfrom
sushilbang:favicon

Conversation

@sushilbang
Copy link
Contributor

@sushilbang sushilbang commented Jan 4, 2026

solves the problem but has a flicker.

Summary by CodeRabbit

  • Bug Fixes
    • Fixed an issue where the theme setting was not properly maintained when navigating through the application. Users' theme preferences now persist consistently across page navigation.

✏️ Tip: You can customize this high-level summary in your review settings.

@vercel
Copy link

vercel bot commented Jan 4, 2026

@sushilbang is attempting to deploy a commit to the sz47's projects Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai
Copy link

coderabbitai bot commented Jan 4, 2026

📝 Walkthrough

Walkthrough

A popstate event listener is added to re-apply the current theme during browser navigation using deferred execution via a zero-delay timeout to ensure proper theme persistence across page transitions.

Changes

Cohort / File(s) Change Summary
Theme Navigation Handling
js/theme/theme.js
Adds window popstate event listener that defers and re-applies the current theme on navigation by calling wisk.theme.setTheme() with the cached theme value

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~8 minutes

Poem

🐰 A rabbit hops through pages with care,
Theme in tow through the popstate air,
With timers deferred, the colors stay true,
Navigation won't fade what the user once knew! ✨

Pre-merge checks and finishing touches

❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Title check ⚠️ Warning The PR title claims to be a 'favicon fix' but the actual change adds a theme popstate event listener with no favicon-related modifications. Update the title to accurately describe the change, such as 'Apply theme on navigation popstate events' or similar, to reflect the actual implementation.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
✨ Finishing touches
  • 📝 Generate docstrings

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.

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)
js/theme/theme.js (1)

35-46: Fix memory leaks in setTheme that are exacerbated by the new popstate listener.

The setTheme function has memory leaks that will accumulate more rapidly with the new popstate listener:

  1. Style element leak (lines 35-46): A new <style> element is created and appended on every call without removing previous ones. With the popstate listener, this accumulates on every navigation.

  2. Blob URL leak (lines 50-54, 153): URL.createObjectURL creates blob URLs that are never revoked, causing memory leaks. The previous blob URL should be revoked before creating a new one.

🔎 Proposed fixes for memory leaks

Fix 1: Reuse or remove old style elements

-    const styleSheet = document.createElement('style');
+    let styleSheet = document.querySelector('style[data-theme-selection]');
+    if (!styleSheet) {
+        styleSheet = document.createElement('style');
+        styleSheet.setAttribute('data-theme-selection', 'true');
+        document.head.appendChild(styleSheet);
+    }
     styleSheet.textContent = `
         ::selection {
             background-color: var(--fg-accent);
             color: var(--bg-accent);
         }
         ::-moz-selection {
             background-color: var(--fg-accent);
             color: var(--bg-accent);
         }
     `;
-    document.head.appendChild(styleSheet);

Fix 2: Revoke previous blob URL before creating a new one

     const textColor = theme['--fg-1'] || '#000000';
     const bgColor = theme['--bg-1'] || '#ffffff';
     const favicon = document.querySelector('link[rel="icon"]') || document.createElement('link');
+    // Revoke previous blob URL to prevent memory leak
+    if (favicon.href && favicon.href.startsWith('blob:')) {
+        URL.revokeObjectURL(favicon.href);
+    }
     favicon.rel = 'icon';
     favicon.type = 'image/svg+xml';
     favicon.href = createThemedFaviconSVG(textColor, bgColor);
     document.head.appendChild(favicon);

Also applies to: 50-54

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1825148 and 901e6a2.

📒 Files selected for processing (1)
  • js/theme/theme.js
🧰 Additional context used
🧬 Code graph analysis (1)
js/theme/theme.js (1)
js/wisk.js (1)
  • wisk (3-3)

Comment on lines +157 to +159
window.addEventListener('popstate', () => {
setTimeout(() => wisk.theme.setTheme(wisk.theme.getTheme()), 0);
});
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Search for favicon and popstate references in the codebase
echo "=== Searching for favicon and popstate references ==="
rg -n -C3 'favicon|popstate' --type=js -g '!js/theme/theme.js'

Repository: sohzm/wisk

Length of output: 5652


🏁 Script executed:

#!/bin/bash
# Examine the theme.js file to understand the setTheme function and the new popstate listener
echo "=== Checking file size first ==="
wc -l js/theme/theme.js

echo -e "\n=== Examining the popstate listener (lines 155-160) ==="
sed -n '155,160p' js/theme/theme.js

echo -e "\n=== Examining the setTheme function (lines 1-65) ==="
sed -n '1,65p' js/theme/theme.js

echo -e "\n=== Searching for URL.revokeObjectURL to check blob cleanup ==="
rg -n 'revokeObjectURL' js/theme/theme.js

Repository: sohzm/wisk

Length of output: 2582


🏁 Script executed:

#!/bin/bash
# Look for any issue tracking or comments about issue #11
echo "=== Searching for issue #11 references ==="
rg -n '#11|issue.*11' --type=js --type=md

echo -e "\n=== Checking if there are git logs or comments ==="
git log --oneline --all 2>/dev/null | head -20

Repository: sohzm/wisk

Length of output: 50367


This approach causes memory leaks and flicker—investigate why the favicon is lost on navigation instead.

The zero-delay setTimeout and the need to re-apply the theme on every popstate event indicate this is a workaround for the underlying issue.

Issues with the current implementation:

  • Style element accumulation: Every setTheme call appends a new <style> element to document.head without cleaning up previous ones, causing memory growth on each navigation.
  • Blob URL leaks: createThemedFaviconSVG creates blob URLs via URL.createObjectURL (line 153), but there is no corresponding URL.revokeObjectURL call, leaking memory.
  • Favicon flicker: Updating the favicon's href on every popstate event forces the browser to reload the favicon, causing visible flicker.

Instead of re-applying the theme on navigation, determine why the favicon is lost in the first place. Is the browser naturally handling favicon persistence? Is there a DOM mutation or style reset happening elsewhere that this listener is trying to mask?

🤖 Prompt for AI Agents
In js/theme/theme.js around lines 157 to 159, the popstate + zero-delay
setTimeout is a workaround causing style element accumulation, blob URL leaks,
and favicon flicker; remove or disable the popstate handler and instead make
setTheme idempotent by: when applying a theme, replace/cleanup any previously
injected <style> (use a stable id or data-attribute and remove the old element
before appending the new one) and when creating a themed favicon revoke any
previous blob URL via URL.revokeObjectURL before assigning a new href (store the
current blob URL on the favicon element or module state), and only update the
favicon when the theme actually changes; also investigate why navigation is
losing the favicon (e.g., head re-render or router logic) rather than
re-applying the theme on every popstate.

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.

1 participant