Skip to content

Commit ff0e102

Browse files
committed
Merge branch 'dev' into feature/garrett
2 parents 8df2a7c + 030d2d2 commit ff0e102

File tree

7 files changed

+61
-38
lines changed

7 files changed

+61
-38
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: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -210,8 +210,7 @@ export default function createTree(currentFiberNode: Fiber): Tree {
210210
console.log('hook states', hooksStates);
211211
// Get the hooks names by parsing the elementType
212212
const hooksNames = getHooksNames(elementType.toString());
213-
console.log('hook names', hooksNames);
214-
213+
// Intialize state & index:
215214
componentData.hooksState = {};
216215
componentData.reducerState = null;
217216
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: 53 additions & 32 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) {
@@ -341,12 +340,24 @@ chrome.runtime.onConnect.addListener(async (port) => {
341340
});
342341
}
343342

344-
// every time devtool is closed, remove the port from portsArr
343+
// Handles port disconnection by removing the disconnected port and attempting reconnection after 1s delay
344+
// This prevents permanent connection loss during idle periods or temporary disconnects -ellie
345345
port.onDisconnect.addListener((e) => {
346346
for (let i = 0; i < portsArr.length; i += 1) {
347347
if (portsArr[i] === e) {
348348
portsArr.splice(i, 1);
349-
chrome.runtime.sendMessage({ action: 'portDisconnect', port: e.name });
349+
setTimeout(async () => {
350+
try {
351+
const response = await chrome.runtime.sendMessage({
352+
action: 'attemptReconnect',
353+
});
354+
if (response && response.success) {
355+
console.log('Port successfully reconnected');
356+
}
357+
} catch (error) {
358+
console.warn('Port reconnection failed:', error);
359+
}
360+
}, 1000);
350361
break;
351362
}
352363
}
@@ -428,7 +439,6 @@ chrome.runtime.onConnect.addListener(async (port) => {
428439
toggleAxRecord = !toggleAxRecord;
429440

430441
await replaceEmptySnap(tabsObj, tabId, toggleAxRecord);
431-
432442
// sends new tabs obj to devtools
433443
if (portsArr.length > 0) {
434444
portsArr.forEach((bg) =>
@@ -599,13 +609,26 @@ chrome.runtime.onMessage.addListener(async (request, sender, sendResponse) => {
599609
break;
600610
}
601611

602-
// DUPLICATE SNAPSHOT CHECK
603-
// This may be where the bug is coming from that when Reactime fails to collect
604-
// 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) {
612+
// DUPLICATE SNAPSHOT CHECK -ellie
613+
const isDuplicateSnapshot = (previous, incoming) => {
614+
if (!previous || !incoming) return false;
615+
const prevData = previous?.componentData;
616+
const incomingData = incoming?.componentData;
617+
618+
// Check if both snapshots have required data
619+
if (!prevData || !incomingData) return false;
620+
621+
const timeDiff = Math.abs(
622+
(incomingData.timestamp || Date.now()) - (prevData.timestamp || Date.now()),
623+
);
624+
return prevData.actualDuration === incomingData.actualDuration && timeDiff < 1000;
625+
};
626+
627+
const previousSnap = tabsObj[tabId]?.currLocation?.stateSnapshot?.children[0];
628+
const incomingSnap = request.payload.children[0];
629+
630+
if (isDuplicateSnapshot(previousSnap, incomingSnap)) {
631+
console.warn('Duplicate snapshot detected, skipping');
609632
break;
610633
}
611634

@@ -626,7 +649,6 @@ chrome.runtime.onMessage.addListener(async (request, sender, sendResponse) => {
626649
addedAxSnap = 'emptyAxSnap';
627650
tabsObj[tabId].axSnapshots.push(addedAxSnap);
628651
}
629-
630652
sendToHierarchy(
631653
tabsObj[tabId],
632654
new HistoryNode(tabsObj[tabId], request.payload, addedAxSnap),
@@ -705,13 +727,12 @@ chrome.tabs.onActivated.addListener((info) => {
705727
if (!tab.pendingUrl?.match('^chrome-extension')) {
706728
activeTab = tab;
707729

708-
/**this setInterval is here to make sure that the app does not stop working even
709-
* if chrome pauses to save energy. There is probably a better solution, but v25 did
710-
* not have time to complete.
711-
*/
712-
setInterval(() => {
713-
console.log(activeTab)
714-
}, 10000);
730+
/**this setKeepAlive is here to make sure that the app does not stop working even
731+
* if chrome pauses to save energy.
732+
*/
733+
chrome.runtime.onStartup.addListener(() => {
734+
chrome.runtime.setKeepAlive(true);
735+
});
715736
if (portsArr.length > 0) {
716737
portsArr.forEach((bg) =>
717738
bg.postMessage({

src/extension/contentScript.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ window.addEventListener('message', (msg) => {
2727
const { action }: { action: string } = msg.data;
2828
if (action === 'recordSnap') {
2929
if (isRecording) {
30+
// add timestamp to payload for the purposes of duplicate screenshot check in backgroundscript -ellie
31+
msg.data.payload.children[0].componentData.timestamp = Date.now();
3032
chrome.runtime.sendMessage(msg.data);
3133
}
3234
}

0 commit comments

Comments
 (0)