Skip to content

Commit c80d006

Browse files
committed
corrected bug where snapshots did not render after idle time. Implemented KeepAlive API and port reconnection, as well as improving the duplicate snapshot check by timestamping snapshots rather than checking intervals
1 parent 29f4f56 commit c80d006

File tree

7 files changed

+84
-29
lines changed

7 files changed

+84
-29
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@
4141
You can view your application's file structure and click on a snapshot to view
4242
your app's state. State can be visualized in a Component Graph, JSON Tree, or
4343
Performance Graph. Snapshot history can be visualized in the History tab.
44-
The Web Metrics tab provides some useful metrics for site performance. The accessibility tab
44+
The Web Metrics tab provides some useful metrics for site performance. The accessibility tab
4545
visualizes an app's accessibility tree per state change.
4646
Snapshots can be compared with the previous snapshot, which can be viewed in Diff mode.
4747
<br>
@@ -89,7 +89,7 @@ Download the recorded snapshots as a JSON file and upload them to access state t
8989
</p>
9090
<br>
9191

92-
### 🔹 Reconnect and Status
92+
### 🔹 and Status
9393

9494
If Reactime loses its connection to the tab you're monitoring, simply click the "reconnect" button to resume your work. You'll notice a circle located to the right of the button, which will appear as either red (indicating disconnection) or green (signifying a successful reconnection).
9595
<br>

src/app/components/Actions/SwitchApp.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,4 +53,4 @@ const SwitchAppDropdown = (): JSX.Element => {
5353
);
5454
};
5555

56-
export default SwitchAppDropdown;
56+
export default SwitchAppDropdown;

src/app/components/StateRoute/History.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ function History(props: Record<string, unknown>): JSX.Element {
101101
delete newObj.state; // delete the state property
102102
}
103103
if (newObj.stateSnaphot) {
104-
// if our new object has a stateSnaphot property
104+
// if our new object has a stateSnaphot propertys
105105
newObj.stateSnaphot = statelessCleaning(obj.stateSnaphot); // run statelessCleaning on the stateSnapshot
106106
}
107107

src/backend/controllers/createTree.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,6 @@ export default function createTree(currentFiberNode: Fiber): Tree {
223223
const hooksStates = getHooksStateAndUpdateMethod(memoizedState);
224224
// Obtain variable names by parsing the function definition stored in elementType.
225225
const hooksNames = getHooksNames(elementType.toString());
226-
227226
// Intialize state & index:
228227
componentData.hooksState = {};
229228
componentData.hooksIndex = [];

src/backend/controllers/timeJump.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ export default function timeJumpInitiation(mode: Status) {
2424
* @param targetSnapshot - The target snapshot to re-render. The payload from index.ts is assigned to targetSnapshot
2525
*/
2626
return async function timeJump(targetSnapshot: Tree): Promise<void> {
27+
console.log('Time jump initiated with targetSnapshot:', targetSnapshot); // logging to see if the re-rendering bug lives here
2728
mode.jumping = true;
2829
// Reset mode.navigating
2930
delete mode.navigating;

src/extension/background.js

Lines changed: 74 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -267,14 +267,14 @@ function changeCurrLocation(tabObj, rootNode, index, name) {
267267

268268
async function getActiveTab() {
269269
return new Promise((resolve, reject) => {
270-
chrome.tabs.query({ active: true, currentWindow: true }, function(tabs) {
270+
chrome.tabs.query({ active: true, currentWindow: true }, function (tabs) {
271271
if (tabs.length > 0) {
272272
resolve(tabs[0].id);
273273
} else {
274-
reject(new Error('No active tab'))
274+
reject(new Error('No active tab'));
275275
}
276276
});
277-
})
277+
});
278278
}
279279

280280
/*
@@ -307,19 +307,18 @@ chrome.runtime.onConnect.addListener(async (port) => {
307307
portsArr.push(port); // push each Reactime communication channel object to the portsArr
308308
// sets the current Title of the Reactime panel
309309

310-
/**
311-
* Sends messages to ports in the portsArr array, triggering a tab change action.
312-
*/
310+
/**
311+
* Sends messages to ports in the portsArr array, triggering a tab change action.
312+
*/
313313
function sendMessagesToPorts() {
314314
portsArr.forEach((bg, index) => {
315-
bg.postMessage({
316-
action: 'changeTab',
317-
payload: { tabId: activeTab.id, title: activeTab.title },
318-
});
315+
bg.postMessage({
316+
action: 'changeTab',
317+
payload: { tabId: activeTab.id, title: activeTab.title },
318+
});
319319
});
320-
}
320+
}
321321

322-
323322
if (portsArr.length > 0 && Object.keys(tabsObj).length > 0) {
324323
//if the activeTab is not set during the onActivate API, run a query to get the tabId and set activeTab
325324
if (!activeTab) {
@@ -330,8 +329,8 @@ chrome.runtime.onConnect.addListener(async (port) => {
330329
activeTab = tab;
331330
sendMessagesToPorts();
332331
}
333-
});
334-
};
332+
});
333+
}
335334
}
336335

337336
if (Object.keys(tabsObj).length > 0) {
@@ -342,11 +341,32 @@ chrome.runtime.onConnect.addListener(async (port) => {
342341
}
343342

344343
// every time devtool is closed, remove the port from portsArr
344+
// port.onDisconnect.addListener((e) => {
345+
// for (let i = 0; i < portsArr.length; i += 1) {
346+
// if (portsArr[i] === e) {
347+
// portsArr.splice(i, 1);
348+
// chrome.runtime.sendMessage({ action: 'portDisconnect', port: e.name });
349+
// break;
350+
// }
351+
// }
352+
// }); //ellie commented out
345353
port.onDisconnect.addListener((e) => {
354+
//ellie added reconnection attempt
346355
for (let i = 0; i < portsArr.length; i += 1) {
347356
if (portsArr[i] === e) {
348357
portsArr.splice(i, 1);
349-
chrome.runtime.sendMessage({ action: 'portDisconnect', port: e.name });
358+
setTimeout(async () => {
359+
try {
360+
const response = await chrome.runtime.sendMessage({
361+
action: 'attemptReconnect',
362+
});
363+
if (response && response.success) {
364+
console.log('Port successfully reconnected');
365+
}
366+
} catch (error) {
367+
console.warn('Port reconnection failed:', error);
368+
}
369+
}, 1000);
350370
break;
351371
}
352372
}
@@ -431,13 +451,15 @@ chrome.runtime.onConnect.addListener(async (port) => {
431451

432452
// sends new tabs obj to devtools
433453
if (portsArr.length > 0) {
454+
console.log('Sending snapshots to frontend:', tabsObj[tabId].snapshots); //ellie
434455
portsArr.forEach((bg) =>
435456
bg.postMessage({
436457
action: 'sendSnapshots',
437458
payload: tabsObj,
438459
tabId,
439460
}),
440461
);
462+
console.log('Current tabsObj:', tabsObj); //ellie
441463
}
442464
return true; // return true so that port remains open
443465

@@ -602,10 +624,32 @@ chrome.runtime.onMessage.addListener(async (request, sender, sendResponse) => {
602624
// DUPLICATE SNAPSHOT CHECK
603625
// This may be where the bug is coming from that when Reactime fails to collect
604626
// state. If they happen to take the same actual duration, it won't record the snapshot.
605-
const previousSnap =
606-
tabsObj[tabId]?.currLocation?.stateSnapshot?.children[0]?.componentData?.actualDuration;
607-
const incomingSnap = request.payload.children[0].componentData.actualDuration;
608-
if (previousSnap === incomingSnap) {
627+
// const previousSnap = //ellie commented out
628+
// tabsObj[tabId]?.currLocation?.stateSnapshot?.children[0]?.componentData?.actualDuration;
629+
// const incomingSnap = request.payload.children[0].componentData.actualDuration;
630+
// if (previousSnap === incomingSnap) {
631+
// break;
632+
// }
633+
// ellie added new duplicate snapshot check
634+
const isDuplicateSnapshot = (previous, incoming) => {
635+
if (!previous || !incoming) return false;
636+
const prevData = previous?.componentData;
637+
const incomingData = incoming?.componentData;
638+
639+
// Check if both snapshots have required data
640+
if (!prevData || !incomingData) return false;
641+
642+
const timeDiff = Math.abs(
643+
(incomingData.timestamp || Date.now()) - (prevData.timestamp || Date.now()),
644+
);
645+
return prevData.actualDuration === incomingData.actualDuration && timeDiff < 1000;
646+
};
647+
648+
const previousSnap = tabsObj[tabId]?.currLocation?.stateSnapshot?.children[0];
649+
const incomingSnap = request.payload.children[0];
650+
651+
if (isDuplicateSnapshot(previousSnap, incomingSnap)) {
652+
console.warn('Duplicate snapshot detected, skipping');
609653
break;
610654
}
611655

@@ -614,6 +658,7 @@ chrome.runtime.onMessage.addListener(async (request, sender, sendResponse) => {
614658
// don't add anything to snapshot storage if tab is reloaded for the initial snapshot
615659
reloaded[tabId] = false;
616660
} else {
661+
console.log('Adding new snapshot to snapshots array.'); //ellie
617662
tabsObj[tabId].snapshots.push(request.payload);
618663
// INVOKING buildHierarchy FIGURE OUT WHAT TO PASS IN
619664
if (!tabsObj[tabId][index]) {
@@ -626,11 +671,12 @@ chrome.runtime.onMessage.addListener(async (request, sender, sendResponse) => {
626671
addedAxSnap = 'emptyAxSnap';
627672
tabsObj[tabId].axSnapshots.push(addedAxSnap);
628673
}
629-
674+
console.log('Updating hierarchy with new snapshot.'); //ellie
630675
sendToHierarchy(
631676
tabsObj[tabId],
632677
new HistoryNode(tabsObj[tabId], request.payload, addedAxSnap),
633678
);
679+
console.log('Updated hierarchy:', tabsObj[tabId].hierarchy); //ellie
634680
}
635681
}
636682

@@ -708,10 +754,14 @@ chrome.tabs.onActivated.addListener((info) => {
708754
/**this setInterval is here to make sure that the app does not stop working even
709755
* if chrome pauses to save energy. There is probably a better solution, but v25 did
710756
* not have time to complete.
711-
*/
712-
setInterval(() => {
713-
console.log(activeTab)
714-
}, 10000);
757+
*/
758+
// setInterval(() => {
759+
// console.log(activeTab);
760+
// }, 10000); //ellie commented out
761+
chrome.runtime.onStartup.addListener(() => {
762+
//ellie replaced with this
763+
chrome.runtime.setKeepAlive(true);
764+
});
715765
if (portsArr.length > 0) {
716766
portsArr.forEach((bg) =>
717767
bg.postMessage({

src/extension/contentScript.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,12 @@ window.addEventListener('message', (msg) => {
2626
// will send snapshots of the test app's link fiber tree.
2727
const { action }: { action: string } = msg.data;
2828
if (action === 'recordSnap') {
29+
// if (isRecording) { //ellie commented out
30+
// chrome.runtime.sendMessage(msg.data);
31+
// }
2932
if (isRecording) {
33+
// ellie added, add timestamp to payload
34+
msg.data.payload.children[0].componentData.timestamp = Date.now();
3035
chrome.runtime.sendMessage(msg.data);
3136
}
3237
}

0 commit comments

Comments
 (0)