diff --git a/Lib/profiling/sampling/_heatmap_assets/heatmap.js b/Lib/profiling/sampling/_heatmap_assets/heatmap.js index d6a91ef290309b..90b5b111d36a8f 100644 --- a/Lib/profiling/sampling/_heatmap_assets/heatmap.js +++ b/Lib/profiling/sampling/_heatmap_assets/heatmap.js @@ -15,37 +15,13 @@ let coldCodeHidden = false; // ============================================================================ function toggleTheme() { - const html = document.documentElement; - const current = html.getAttribute('data-theme') || 'light'; - const next = current === 'light' ? 'dark' : 'light'; - html.setAttribute('data-theme', next); - localStorage.setItem('heatmap-theme', next); - - // Update theme button icon - const btn = document.getElementById('theme-btn'); - if (btn) { - btn.querySelector('.icon-moon').style.display = next === 'dark' ? 'none' : ''; - btn.querySelector('.icon-sun').style.display = next === 'dark' ? '' : 'none'; - } + toggleAndSaveTheme(); applyLineColors(); // Rebuild scroll marker with new theme colors buildScrollMarker(); } -function restoreUIState() { - // Restore theme - const savedTheme = localStorage.getItem('heatmap-theme'); - if (savedTheme) { - document.documentElement.setAttribute('data-theme', savedTheme); - const btn = document.getElementById('theme-btn'); - if (btn) { - btn.querySelector('.icon-moon').style.display = savedTheme === 'dark' ? 'none' : ''; - btn.querySelector('.icon-sun').style.display = savedTheme === 'dark' ? '' : 'none'; - } - } -} - // ============================================================================ // Utility Functions // ============================================================================ diff --git a/Lib/profiling/sampling/_heatmap_assets/heatmap_index.js b/Lib/profiling/sampling/_heatmap_assets/heatmap_index.js index 8eb6af0db5335e..db4b5485056217 100644 --- a/Lib/profiling/sampling/_heatmap_assets/heatmap_index.js +++ b/Lib/profiling/sampling/_heatmap_assets/heatmap_index.js @@ -19,35 +19,10 @@ function applyHeatmapBarColors() { // ============================================================================ function toggleTheme() { - const html = document.documentElement; - const current = html.getAttribute('data-theme') || 'light'; - const next = current === 'light' ? 'dark' : 'light'; - html.setAttribute('data-theme', next); - localStorage.setItem('heatmap-theme', next); - - // Update theme button icon - const btn = document.getElementById('theme-btn'); - if (btn) { - btn.querySelector('.icon-moon').style.display = next === 'dark' ? 'none' : ''; - btn.querySelector('.icon-sun').style.display = next === 'dark' ? '' : 'none'; - } - + toggleAndSaveTheme(); applyHeatmapBarColors(); } -function restoreUIState() { - // Restore theme - const savedTheme = localStorage.getItem('heatmap-theme'); - if (savedTheme) { - document.documentElement.setAttribute('data-theme', savedTheme); - const btn = document.getElementById('theme-btn'); - if (btn) { - btn.querySelector('.icon-moon').style.display = savedTheme === 'dark' ? 'none' : ''; - btn.querySelector('.icon-sun').style.display = savedTheme === 'dark' ? '' : 'none'; - } - } -} - // ============================================================================ // Type Section Toggle (stdlib, project, etc) // ============================================================================ diff --git a/Lib/profiling/sampling/_heatmap_assets/heatmap_index_template.html b/Lib/profiling/sampling/_heatmap_assets/heatmap_index_template.html index 3620f8efb8058a..8d04149abe3014 100644 --- a/Lib/profiling/sampling/_heatmap_assets/heatmap_index_template.html +++ b/Lib/profiling/sampling/_heatmap_assets/heatmap_index_template.html @@ -1,5 +1,5 @@ - + diff --git a/Lib/profiling/sampling/_heatmap_assets/heatmap_pyfile_template.html b/Lib/profiling/sampling/_heatmap_assets/heatmap_pyfile_template.html index 91b629b2628244..2a9c07647e64cd 100644 --- a/Lib/profiling/sampling/_heatmap_assets/heatmap_pyfile_template.html +++ b/Lib/profiling/sampling/_heatmap_assets/heatmap_pyfile_template.html @@ -1,5 +1,5 @@ - + diff --git a/Lib/profiling/sampling/_heatmap_assets/heatmap_shared.js b/Lib/profiling/sampling/_heatmap_assets/heatmap_shared.js index 7fcd720d45d7b3..84b13ca0a9682b 100644 --- a/Lib/profiling/sampling/_heatmap_assets/heatmap_shared.js +++ b/Lib/profiling/sampling/_heatmap_assets/heatmap_shared.js @@ -39,6 +39,42 @@ function intensityToColor(intensity) { return rootStyle.getPropertyValue(`--heat-${level}`).trim(); } +// ============================================================================ +// Theme Support +// ============================================================================ + +// Get the preferred theme from localStorage or browser preference +function getPreferredTheme() { + const saved = localStorage.getItem('heatmap-theme'); + if (saved) return saved; + return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'; +} + +// Apply theme and update UI. Returns the applied theme. +function applyTheme(theme) { + document.documentElement.setAttribute('data-theme', theme); + const btn = document.getElementById('theme-btn'); + if (btn) { + btn.querySelector('.icon-moon').style.display = theme === 'dark' ? 'none' : ''; + btn.querySelector('.icon-sun').style.display = theme === 'dark' ? '' : 'none'; + } + return theme; +} + +// Toggle theme and save preference. Returns the new theme. +function toggleAndSaveTheme() { + const current = document.documentElement.getAttribute('data-theme') || 'light'; + const next = current === 'light' ? 'dark' : 'light'; + applyTheme(next); + localStorage.setItem('heatmap-theme', next); + return next; +} + +// Restore theme from localStorage, or use browser preference +function restoreUIState() { + applyTheme(getPreferredTheme()); +} + // ============================================================================ // Favicon (Reuse logo image as favicon) // ============================================================================