Skip to content

Commit a47cb88

Browse files
committed
Merge commit '5f45c21'
2 parents a208619 + 5f45c21 commit a47cb88

2 files changed

Lines changed: 75 additions & 85 deletions

File tree

src/content/overlay.css

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -100,16 +100,16 @@ img.mwe-math-fallback-image-display.hoverlatex-hover {
100100

101101
/* Dark mode */
102102
@media (prefers-color-scheme: dark) {
103-
.hoverlatex-overlay {
103+
.hoverlatex-overlay:not(.theme-light):not(.theme-dark) {
104104
background: #1e1e1e;
105105
color: #f0f0f0;
106106
box-shadow: 0 3px 10px rgba(0,0,0,0.6);
107107
}
108-
.hoverlatex-overlay.copied {
108+
.hoverlatex-overlay:not(.theme-light):not(.theme-dark).copied {
109109
background: #052e16;
110110
color: #dcfce7;
111111
}
112-
.hoverlatex-overlay .check-icon {
112+
.hoverlatex-overlay:not(.theme-light):not(.theme-dark) .check-icon {
113113
color: #dcfce7;
114114
}
115115
}

src/content/overlay.js

Lines changed: 72 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -6,90 +6,86 @@
66
lastMathJaxV3Latex: null,
77
lastCopyGestureTs: 0,
88
lastCopiedTex: null,
9+
themeMode: 'system',
10+
themeModeLoaded: false,
911
};
1012

11-
function getOverlay() {
12-
return ns.state.overlay;
13-
}
14-
15-
function setOverlay(el) {
16-
ns.state.overlay = el;
17-
}
18-
19-
async function setOverlayThemeClass() {
20-
const overlay = getOverlay();
21-
if (!overlay) return;
22-
// Remove any previous theme class
23-
overlay.classList.remove('theme-light', 'theme-dark');
24-
let theme = 'system';
25-
13+
async function loadThemeModeOnce() {
14+
if (ns.state.themeModeLoaded) return;
2615
try {
2716
const result = await browser.storage.local.get('themeMode');
28-
// console.log('[Copy LaTeX] setOverlayThemeClass: browser.storage.local themeMode =', result.themeMode);
29-
theme = result.themeMode || 'system';
17+
ns.state.themeMode = result.themeMode || 'system';
3018
} catch (e) {
3119
// This can happen during navigation/refresh or extension reload: the content-script
3220
// context is torn down while an async storage call is in-flight.
3321
const message = e && typeof e === 'object' && 'message' in e ? String(e.message) : String(e);
3422
if (!message.includes('Extension context invalidated')) {
35-
console.warn('[Copy LaTeX] setOverlayThemeClass: error reading browser.storage.local', e);
23+
console.warn('[Copy LaTeX] loadThemeModeOnce: error reading browser.storage.local', e);
3624
}
25+
// Keep default themeMode='system'
26+
} finally {
27+
ns.state.themeModeLoaded = true;
28+
// If the overlay already exists, apply the loaded theme immediately.
29+
applyOverlayThemeClass();
3730
}
31+
}
32+
33+
function applyOverlayThemeClass() {
34+
const overlay = getOverlay();
35+
if (!overlay) return;
36+
37+
const theme = ns.state.themeMode || 'system';
38+
const wantsLight = theme === 'light';
39+
const wantsDark = theme === 'dark';
40+
41+
// Avoid class churn: only touch DOM if we need to.
42+
const hasLight = overlay.classList.contains('theme-light');
43+
const hasDark = overlay.classList.contains('theme-dark');
44+
if (wantsLight === hasLight && wantsDark === hasDark) return;
45+
46+
overlay.classList.toggle('theme-light', wantsLight);
47+
overlay.classList.toggle('theme-dark', wantsDark);
48+
}
49+
50+
// Keep ns.state.themeMode in sync without doing async work on hover.
51+
try {
52+
browser.storage.onChanged.addListener((changes, areaName) => {
53+
if (areaName !== 'local') return;
54+
if (!changes.themeMode) return;
55+
ns.state.themeMode = changes.themeMode.newValue || 'system';
56+
ns.state.themeModeLoaded = true;
57+
applyOverlayThemeClass();
58+
});
59+
} catch (e) {
60+
// Defensive: some environments may not expose storage listeners in this context.
61+
}
62+
63+
// Kick off a single async load early.
64+
loadThemeModeOnce();
3865

39-
// console.log('[Copy LaTeX] setOverlayThemeClass: using theme =', theme);
40-
if (theme === 'light') overlay.classList.add('theme-light');
41-
else if (theme === 'dark') overlay.classList.add('theme-dark');
42-
// If system, do not add any theme class (prefers-color-scheme CSS media query will apply)
43-
}
66+
function getOverlay() {
67+
return ns.state.overlay;
68+
}
69+
70+
function setOverlay(el) {
71+
ns.state.overlay = el;
72+
}
73+
74+
async function setOverlayThemeClass() {
75+
// Backwards-compatible async signature.
76+
// We *never* do async theme reads on hover; we apply the cached state.
77+
if (!ns.state.themeModeLoaded) loadThemeModeOnce();
78+
applyOverlayThemeClass();
79+
}
4480

4581
function createOverlay() {
4682
const overlay = document.createElement('div');
4783
overlay.className = 'hoverlatex-overlay';
48-
// console.log('[Copy LaTeX] Overlay created. Initial class:', overlay.className);
4984

5085
setOverlay(overlay);
5186

52-
// Set theme class based on user preference
53-
setOverlayThemeClass().then(() => {
54-
console.log('[Copy LaTeX] Overlay after theme set. Classes:', overlay.className);
55-
const bg = window.getComputedStyle(overlay).backgroundColor;
56-
console.log('[Copy LaTeX] Overlay computed background after theme set:', bg);
57-
});
58-
59-
// MutationObserver to log class/style changes (I'll remove it later)
60-
const observer = new MutationObserver((mutationsList) => {
61-
for (const mutation of mutationsList) {
62-
if (
63-
mutation.type === 'attributes' &&
64-
(mutation.attributeName === 'class' || mutation.attributeName === 'style')
65-
) {
66-
console.log('[Copy LaTeX][MutationObserver] Overlay attribute changed:', mutation.attributeName, {
67-
class: overlay.className,
68-
style: overlay.getAttribute('style'),
69-
computedBg: window.getComputedStyle(overlay).backgroundColor,
70-
});
71-
}
72-
}
73-
});
74-
observer.observe(overlay, { attributes: true, attributeFilter: ['class', 'style'] });
75-
76-
// Random interval observer: logs computed background color at random intervals (10-100ms)
77-
let lastBg = '';
78-
function randomBgLogger() {
79-
const currentOverlay = getOverlay();
80-
if (currentOverlay) {
81-
const bg = window.getComputedStyle(currentOverlay).backgroundColor;
82-
if (bg !== lastBg) {
83-
console.log('[Copy LaTeX][RandomBgObserver] Overlay computed background:', bg);
84-
lastBg = bg;
85-
}
86-
}
87-
88-
// Schedule next check at a random interval between 10ms and 100ms
89-
const nextDelay = Math.floor(Math.random() * 91) + 10;
90-
setTimeout(randomBgLogger, nextDelay);
91-
}
92-
randomBgLogger();
87+
// Apply cached theme immediately (no async waits).
88+
setOverlayThemeClass();
9389

9490
// HTML overlay content with inline SVG icon and 'Click to copy' text
9591
overlay.appendChild(ns.svg.createSvgFromString(ns.svg.copy_svg));
@@ -110,23 +106,17 @@
110106
// console.log('[Copy LaTeX] showOverlay: overlay exists, reusing. Classes:', overlay.className);
111107
}
112108

113-
// Only make overlay visible after theme is set
114-
setOverlayThemeClass().then(() => {
115-
// Remove .visible if present before theme is set
116-
overlay.classList.remove('visible');
117-
// console.log('[Copy LaTeX] showOverlay: after theme set. Classes:', overlay.className);
118-
const bg = window.getComputedStyle(overlay).backgroundColor;
119-
// console.log('[Copy LaTeX] showOverlay: computed background:', bg);
120-
overlay.dataset.tex = tex;
121-
122-
const rect = target.getBoundingClientRect();
123-
const overlayWidth = overlay.offsetWidth;
124-
const top = rect.top + window.scrollY - overlay.offsetHeight - 8;
125-
const left = rect.left + window.scrollX + rect.width / 2 - overlayWidth / 2;
126-
overlay.style.top = `${top}px`;
127-
overlay.style.left = `${left}px`;
128-
overlay.classList.add('visible');
129-
});
109+
// Ensure theme is applied synchronously to avoid flicker.
110+
setOverlayThemeClass();
111+
overlay.dataset.tex = tex;
112+
113+
const rect = target.getBoundingClientRect();
114+
const overlayWidth = overlay.offsetWidth;
115+
const top = rect.top + window.scrollY - overlay.offsetHeight - 8;
116+
const left = rect.left + window.scrollX + rect.width / 2 - overlayWidth / 2;
117+
overlay.style.top = `${top}px`;
118+
overlay.style.left = `${left}px`;
119+
overlay.classList.add('visible');
130120
}
131121

132122
function hideOverlay() {

0 commit comments

Comments
 (0)