|
| 1 | +// import 'core-js'; |
| 2 | + |
| 3 | +import { invoke } from 'lodash'; |
| 4 | + |
1 | 5 | // Store ports in an array.
|
2 | 6 | const portsArr = [];
|
3 | 7 | const reloaded = {};
|
@@ -360,28 +364,53 @@ chrome.runtime.onConnect.addListener(async (port) => {
|
360 | 364 | }
|
361 | 365 |
|
362 | 366 | if (Object.keys(tabsObj).length > 0) {
|
363 |
| - console.log('Sending initial snapshots to devtools:', tabsObj); |
364 | 367 | port.postMessage({
|
365 | 368 | action: 'initialConnectSnapshots',
|
366 | 369 | payload: tabsObj,
|
367 | 370 | });
|
368 |
| - } else { |
369 |
| - console.log('No snapshots to send to devtools on reconnect.'); |
370 | 371 | }
|
371 | 372 |
|
372 |
| - // Handles port disconnection by removing the disconnected port -ellie |
373 |
| - port.onDisconnect.addListener(() => { |
374 |
| - const index = portsArr.indexOf(port); |
375 |
| - if (index !== -1) { |
376 |
| - console.warn(`Port at index ${index} disconnected. Removing it.`); |
377 |
| - portsArr.splice(index, 1); |
| 373 | + // Handles port disconnection by removing the disconnected port and attempting reconnection after 1s delay |
| 374 | + // This prevents permanent connection loss during idle periods or temporary disconnects -ellie |
| 375 | + port.onDisconnect.addListener((e) => { |
| 376 | + for (let i = 0; i < portsArr.length; i += 1) { |
| 377 | + if (portsArr[i] === e) { |
| 378 | + portsArr.splice(i, 1); |
| 379 | + // chrome.runtime.sendMessage({ action: 'portDisconnect', port: e.name }); |
| 380 | + setTimeout(async () => { |
| 381 | + try { |
| 382 | + const newPort = chrome.runtime.connect({ name: 'reconnected' }); // Attempt to reconnect |
| 383 | + if (newPort) { |
| 384 | + portsArr.push(newPort); // Add the new port to the array |
| 385 | + newPort.onMessage.addListener((msg) => { |
| 386 | + console.log('Message received on reconnected port:', msg); |
| 387 | + }); |
| 388 | + console.log('Port successfully reconnected'); |
| 389 | + } else { |
| 390 | + console.warn('Failed to reconnect port'); |
| 391 | + } |
| 392 | + } catch (error) { |
| 393 | + console.warn('Port reconnection attempt failed:', error); |
| 394 | + } |
| 395 | + }, 1000); |
| 396 | + break; |
| 397 | + } |
378 | 398 | }
|
379 | 399 | });
|
380 | 400 |
|
381 | 401 | // INCOMING MESSAGE FROM FRONTEND (MainContainer) TO BACKGROUND.js
|
382 | 402 | // listen for message containing a snapshot from devtools and send it to contentScript -
|
383 | 403 | // (i.e. they're all related to the button actions on Reactime)
|
384 | 404 | port.onMessage.addListener(async (msg) => {
|
| 405 | + // msg is action denoting a time jump in devtools |
| 406 | + // --------------------------------------------------------------- |
| 407 | + // message incoming from devTools should look like this: |
| 408 | + // { |
| 409 | + // action: 'emptySnap', |
| 410 | + // payload: tabsObj, |
| 411 | + // tabId: 101 |
| 412 | + // } |
| 413 | + // --------------------------------------------------------------- |
385 | 414 | const { action, payload, tabId } = msg;
|
386 | 415 |
|
387 | 416 | switch (action) {
|
@@ -664,21 +693,15 @@ chrome.runtime.onMessage.addListener(async (request, sender, sendResponse) => {
|
664 | 693 |
|
665 | 694 | // sends new tabs obj to devtools
|
666 | 695 | if (portsArr.length > 0) {
|
667 |
| - portsArr.forEach((bg, index) => { |
668 |
| - try { |
669 |
| - bg.postMessage({ |
670 |
| - action: 'sendSnapshots', |
671 |
| - payload: tabsObj, |
672 |
| - sourceTab, |
673 |
| - }); |
674 |
| - console.log(`Sent snapshots to port at index ${index}`); |
675 |
| - } catch (error) { |
676 |
| - console.warn(`Failed to send snapshots to port at index ${index}:`, error); |
677 |
| - } |
678 |
| - }); |
679 |
| - } else { |
680 |
| - console.warn('No active ports to send snapshots to.'); |
| 696 | + portsArr.forEach((bg) => |
| 697 | + bg.postMessage({ |
| 698 | + action: 'sendSnapshots', |
| 699 | + payload: tabsObj, |
| 700 | + sourceTab, |
| 701 | + }), |
| 702 | + ); |
681 | 703 | }
|
| 704 | + break; |
682 | 705 | }
|
683 | 706 | default:
|
684 | 707 | break;
|
@@ -752,6 +775,59 @@ chrome.tabs.onActivated.addListener((info) => {
|
752 | 775 | });
|
753 | 776 | });
|
754 | 777 |
|
| 778 | +// when reactime is installed |
| 779 | +// create a context menu that will open our devtools in a new window |
| 780 | +chrome.runtime.onInstalled.addListener(() => { |
| 781 | + chrome.contextMenus.create({ |
| 782 | + id: 'reactime', |
| 783 | + title: 'Reactime', |
| 784 | + contexts: ['page', 'selection', 'image', 'link'], |
| 785 | + }); |
| 786 | + setupKeepAlive(); |
| 787 | +}); |
| 788 | + |
755 | 789 | chrome.runtime.onStartup.addListener(() => {
|
756 | 790 | setupKeepAlive();
|
757 | 791 | });
|
| 792 | +// when context menu is clicked, listen for the menuItemId, |
| 793 | +// if user clicked on reactime, open the devtools window |
| 794 | + |
| 795 | +// JR 12.19.23 |
| 796 | +// As of V22, if multiple monitors are used, it would open the reactime panel on the other screen, which was inconvenient when opening repeatedly for debugging. |
| 797 | +// V23 fixes this by making use of chrome.windows.getCurrent to get the top and left of the screen which invoked the extension. |
| 798 | +// As of chrome manifest V3, background.js is a 'service worker', which does not have access to the DOM or to the native 'window' method, so we use chrome.windows.getCurrent(callback) |
| 799 | +// chrome.windows.getCurrent returns a promise (asynchronous), so all resulting functionality must happen in the callback function, or it will run before 'invokedScreen' variables have been captured. |
| 800 | +chrome.contextMenus.onClicked.addListener(({ menuItemId }) => { |
| 801 | + // // this was a test to see if I could dynamically set the left property to be the 0 origin of the invoked DISPLAY (as opposed to invoked window). |
| 802 | + // // this would allow you to split your screen, keep the browser open on the right side, and reactime always opens at the top left corner. |
| 803 | + // // however it does not tell you which display is the one that invoked it, just gives the array of all available displays. Depending on your monitor setup, it may differ. Leaving for future iterators |
| 804 | + // chrome.system.display.getInfo((displayUnitInfo) => { |
| 805 | + // console.log(displayUnitInfo); |
| 806 | + // }); |
| 807 | + chrome.windows.getCurrent((window) => { |
| 808 | + const invokedScreenTop = 75; // window.top || 0; |
| 809 | + const invokedScreenLeft = window.width < 1000 ? window.left + window.width - 1000 : window.left; |
| 810 | + const invokedScreenWidth = 1000; |
| 811 | + const invokedScreenHeight = window.height - invokedScreenTop || 1000; |
| 812 | + const options = { |
| 813 | + type: 'panel', |
| 814 | + left: invokedScreenLeft, |
| 815 | + top: invokedScreenTop, |
| 816 | + width: invokedScreenWidth, |
| 817 | + height: invokedScreenHeight, |
| 818 | + url: chrome.runtime.getURL('panel.html'), |
| 819 | + }; |
| 820 | + if (menuItemId === 'reactime') chrome.windows.create(options); |
| 821 | + }); |
| 822 | + |
| 823 | + // JR 1.9.23: this code fixes the no target error on load by triggering chrome tab reload before the panel spins up. |
| 824 | + // It does not solve the root issue, which was deeply researched during v23 but we ran out of time to solve. Please see the readme for more information. |
| 825 | + chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => { |
| 826 | + if (tabs.length) { |
| 827 | + const invokedTab = tabs[0]; |
| 828 | + const invokedTabId = invokedTab.id; |
| 829 | + const invokedTabTitle = invokedTab.title; |
| 830 | + chrome.tabs.reload(invokedTabId); |
| 831 | + } |
| 832 | + }); |
| 833 | +}); |
0 commit comments