Skip to content

Commit 7a18221

Browse files
author
Manu Nair
committed
Improve activation logic, enhance background connection handling, and ensure DOM elements are present in popup
1 parent eccef79 commit 7a18221

File tree

4 files changed

+62
-21
lines changed

4 files changed

+62
-21
lines changed

packages/clarity-devtools/src/clarity.ts

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { clarity, version, helper } from "clarity-js";
55
if (typeof window !== "undefined") {
66
const w = window as any;
77
const c = 'clarity';
8+
let isStarted = false;
89

910
// Stop any existing instance of clarity-js
1011
if (w[c]) { w[c]("stop"); }
@@ -18,8 +19,15 @@ import { clarity, version, helper } from "clarity-js";
1819
window.postMessage({ action: "wireup" }, "*");
1920

2021
// V3 CSP: Listen for settings via CustomEvent (replaces inline script injection)
21-
window.addEventListener('clarity-devtools-settings', (event: any) => {
22+
const settingsHandler = (event: any) => {
23+
if (isStarted) {
24+
console.log('[Clarity DevTools] Clarity: Already started, ignoring duplicate settings event');
25+
return;
26+
}
27+
2228
const settings = event.detail;
29+
isStarted = true;
30+
2331
w[c]("start", {
2432
delay: 500,
2533
lean: settings.leanMode,
@@ -32,6 +40,8 @@ import { clarity, version, helper } from "clarity-js";
3240
upload: (data: string): void => { window.postMessage({ action: "upload", payload: data }, "*"); },
3341
projectId: "devtools"
3442
});
35-
});
43+
};
44+
45+
window.addEventListener('clarity-devtools-settings', settingsHandler, { once: true });
3646
}
3747
})();

packages/clarity-devtools/src/content.ts

Lines changed: 24 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -37,44 +37,53 @@ async function activate(): Promise<void> {
3737
return;
3838
}
3939

40+
// Set flag immediately to prevent race condition
41+
isActivated = true;
4042
console.log('[Clarity DevTools] Content: Activating Clarity tracking...');
4143

4244
if (document.body) {
43-
setup(chrome.runtime.getURL('clarity.js'));
44-
isActivated = true;
45-
console.log('[Clarity DevTools] Content: Clarity activated successfully');
45+
if (!setup(chrome.runtime.getURL('clarity.js'))) {
46+
isActivated = false; // Reset if setup fails
47+
console.error('[Clarity DevTools] Content: Clarity activation failed');
48+
} else {
49+
console.log('[Clarity DevTools] Content: Clarity activated successfully');
50+
}
4651
} else {
4752
if (document.readyState === 'loading') {
4853
await new Promise<void>(resolve => {
4954
document.addEventListener('DOMContentLoaded', () => {
50-
setup(chrome.runtime.getURL('clarity.js'));
51-
isActivated = true;
55+
if (!setup(chrome.runtime.getURL('clarity.js'))) {
56+
isActivated = false; // Reset if setup fails
57+
}
5258
resolve();
5359
}, { once: true });
5460
});
5561
} else {
5662
await new Promise(resolve => setTimeout(resolve, 100));
57-
setup(chrome.runtime.getURL('clarity.js'));
58-
isActivated = true;
63+
if (!setup(chrome.runtime.getURL('clarity.js'))) {
64+
isActivated = false; // Reset if setup fails
65+
}
5966
}
6067
}
6168
}
6269

63-
function setup(url: string): void {
70+
function setup(url: string): boolean {
6471
if (!document.body) {
65-
console.error('Clarity DevTools: document.body not available');
66-
return;
72+
console.error('[Clarity DevTools] Content: document.body not available, setup failed');
73+
return false;
74+
}
75+
76+
// Only set up once - if already set up, return success
77+
if (messageListener) {
78+
console.log('[Clarity DevTools] Content: Message listener already registered, skipping setup');
79+
return true;
6780
}
6881

6982
const script = document.createElement("script");
7083
script.setAttribute('type', 'text/javascript');
7184
script.setAttribute('src', url);
7285
document.body.appendChild(script);
7386

74-
if (messageListener) {
75-
window.removeEventListener("message", messageListener);
76-
}
77-
7887
messageListener = function(event: MessageEvent): void {
7988
if (event.source === window && event.data?.action) {
8089
switch (event.data.action) {
@@ -106,6 +115,7 @@ function setup(url: string): void {
106115
};
107116

108117
window.addEventListener("message", messageListener);
118+
return true;
109119
}
110120

111121
async function upload(data: string): Promise<void> {

packages/clarity-devtools/src/panel.ts

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ let retryCount = 0;
1010
const MAX_RETRIES = 5;
1111
const RETRY_DELAY = 200;
1212
let isReconnecting = false;
13+
let disconnectListener: (() => void) | null = null;
14+
let messageListener: ((message: { action?: string; payload?: string }) => void) | null = null;
1315

1416
let sessionId = "";
1517
let pageNum = 0;
@@ -53,6 +55,12 @@ function connectToBackground(): void {
5355
try {
5456
if (background) {
5557
try {
58+
if (disconnectListener) {
59+
background.onDisconnect.removeListener(disconnectListener);
60+
}
61+
if (messageListener) {
62+
background.onMessage.removeListener(messageListener);
63+
}
5664
background.disconnect();
5765
} catch (e) {
5866
// Ignore disconnect errors
@@ -62,7 +70,7 @@ function connectToBackground(): void {
6270
background = chrome.runtime.connect({ name: "panel" });
6371
console.log('[Clarity DevTools] Panel: Connected to background, port name:', background.name);
6472

65-
background.onDisconnect.addListener(() => {
73+
disconnectListener = () => {
6674
console.log('[Clarity DevTools] Panel: Background connection disconnected');
6775
isReconnecting = false;
6876

@@ -73,9 +81,11 @@ function connectToBackground(): void {
7381
} else {
7482
console.error('[Clarity DevTools] Panel: Max reconnection attempts reached');
7583
}
76-
});
84+
};
85+
background.onDisconnect.addListener(disconnectListener);
7786

78-
background.onMessage.addListener(handleMessage);
87+
messageListener = handleMessage;
88+
background.onMessage.addListener(messageListener);
7989

8090
console.log('[Clarity DevTools] Panel: Sending init message for tab', activeTabId);
8191
background.postMessage({ action: "init", tabId: activeTabId });

packages/clarity-devtools/src/popup.ts

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,13 @@
1-
(async function(): Promise<void> {
1+
async function init(): Promise<void> {
22
let state = { showText: true, leanMode : false };
33
let showText = (document.getElementById("showText") as HTMLInputElement);
44
let leanMode = (document.getElementById("leanMode") as HTMLInputElement);
55

6+
if (!showText || !leanMode) {
7+
console.error('[Clarity DevTools] Popup: DOM elements not found');
8+
return;
9+
}
10+
611
try {
712
const items = await chrome.storage.sync.get({clarity: state});
813
state = items.clarity;
@@ -36,4 +41,10 @@
3641
showText.checked = update.showText;
3742
leanMode.checked = update.leanMode;
3843
}
39-
})();
44+
}
45+
46+
if (document.readyState === 'loading') {
47+
document.addEventListener('DOMContentLoaded', init);
48+
} else {
49+
init();
50+
}

0 commit comments

Comments
 (0)