Skip to content
This repository has been archived by the owner on Sep 26, 2024. It is now read-only.

Commit

Permalink
Merge remote-tracking branch 'origin/main' into reactor_cleanup_09222024
Browse files Browse the repository at this point in the history
  • Loading branch information
jonathankap committed Sep 22, 2024
2 parents 45b2521 + eaaa9da commit 81b2997
Show file tree
Hide file tree
Showing 6 changed files with 415 additions and 263 deletions.
117 changes: 81 additions & 36 deletions apps/mocksi-lite-next/src/pages/background/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
import { AppEvents, AuthEvents, LayoutEvents } from "@pages/events";
import {
AppEvents,
AuthEvents,
DemoEditEvents,
LayoutEvents,
} from "@pages/events";
import { jwtDecode } from "jwt-decode";

console.log("background script loaded");
Expand All @@ -8,6 +13,26 @@ const MOCKSI_AUTH = "mocksi-auth";
let fallbackTab: null | chrome.tabs.Tab = null;
let prevLayoutEvent = "";

let mainIframeSrcPort: null | chrome.runtime.Port = null;
let topIframeSrcPort: null | chrome.runtime.Port = null;

addEventListener("install", () => {
// TODO test if this works on other browsers
chrome.tabs.create({
url: import.meta.env.VITE_NEST_APP,
});
});

chrome.runtime.onConnectExternal.addListener((port) => {
console.log("connecting...", port);
if (port.name === "extension/main") {
mainIframeSrcPort = port;
}
if (port.name === "extension/top") {
topIframeSrcPort = port;
}
});

const getAuth = async (): Promise<null | {
accessToken: string;
email: string;
Expand Down Expand Up @@ -102,18 +127,11 @@ async function showPlayIcon(tabId: number) {
});
}

addEventListener("install", () => {
// TODO test if this works on other browsers
chrome.tabs.create({
url: import.meta.env.VITE_NEST_APP,
});
});

// when user clicks toolbar mount extension
chrome.action.onClicked.addListener((tab) => {
if (!tab?.id) {
console.log("No tab exits click, could not mount extension");
return;
return true;
}
// store the tab they clicked on to open the extension
// so we can use it as a fallback
Expand All @@ -129,30 +147,36 @@ chrome.action.onClicked.addListener((tab) => {
});
prevLayoutEvent = LayoutEvents.HIDE;
}
return true;
});

chrome.runtime.onMessage.addListener(
(request, _sender, sendResponse): boolean => {
sendResponse({
data: request.data,
message: request.message,
status: "ok",
});
return true;
},
);

chrome.runtime.onMessageExternal.addListener(
(request, _sender, sendResponse) => {
console.log("on message external: ", request);

// execute in async block so that we return true
// synchronously, telling chrome to wait for the response
(async () => {
if (
request.source === "extension/top" &&
request.message === AppEvents.EDIT_DEMO_STOP
) {
if (mainIframeSrcPort) {
// notify extension/main that demo edit mode exited in extension/top
mainIframeSrcPort.postMessage({
...request,
message: AppEvents.EDIT_DEMO_STOP,
});
} else {
console.log("mainIframeSrcPort is not connected");
}
}

if (request.message === AuthEvents.AUTH_ERROR) {
await clearAuth();
sendResponse({
message: AuthEvents.RETRY,
source: "background",
status: "ok",
});
} else if (request.message === AuthEvents.UNAUTHORIZED) {
Expand All @@ -162,23 +186,22 @@ chrome.runtime.onMessageExternal.addListener(
const tab = await getCurrentTab();
sendResponse({
message: { accessToken, email, url: tab?.url },
source: "background",
status: "ok",
});
} else {
await showAuthTab(true);
sendResponse({
message: AuthEvents.AUTHENTICATING,
source: "background",
status: "ok",
});
}
} else {
const tab = await getCurrentTab();
if (!tab?.id) {
sendResponse({
message: LayoutEvents.NO_TAB,
status: "ok",
});
return;
console.error("No tab found: ");
return true;
}

if (
Expand All @@ -201,19 +224,41 @@ chrome.runtime.onMessageExternal.addListener(
showDefaultIcon(tab.id);
}

chrome.tabs.sendMessage(
tab.id,
{
data: request.data,
message: request.message,
},
(response) => {
sendResponse(response);
},
);
// send message to iframes and reactor in mocksi-extension
chrome.tabs.sendMessage(tab.id, request, async (response) => {
console.log("response from content script in background:", response);
if (response.message === DemoEditEvents.UNDO) {
// pass updated modifications from reactor to extension/main to store
if (mainIframeSrcPort) {
await mainIframeSrcPort.postMessage({
...response,
status: "ok", // response handler expects status
});
} else {
console.log("mainIframeSrcPort is not connected");
}
}
if (
response.message === AppEvents.EDIT_DEMO_START ||
response.message === DemoEditEvents.CHAT_RESPONSE ||
response.message === DemoEditEvents.NEW_EDIT
) {
// notify extension/top # of edits changed
if (topIframeSrcPort) {
await topIframeSrcPort.postMessage({
...response,
status: "ok",
});
} else {
console.log("topIframeSrcPort is not connected");
}
}

sendResponse(response);
return true;
});
}
})();

return true;
},
);
123 changes: 123 additions & 0 deletions apps/mocksi-lite-next/src/pages/content/main-iframe.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
import React from "react";
import ReactDOM from "react-dom";
import { LayoutEvents } from "../events";

export enum IframePosition {
BOTTOM_CENTER = "BOTTOM_CENTER",
TOP_RIGHT = "TOP_RIGHT",
BOTTOM_RIGHT = "BOTTOM_RIGHT",
}

export interface IframeResizeArgs {
height: number;
id?: string;
position:
| IframePosition.BOTTOM_CENTER
| IframePosition.BOTTOM_RIGHT
| IframePosition.TOP_RIGHT;
width: number;
}

function getIframeStyles({ height, position, width }: IframeResizeArgs) {
if (!height || !width || !position) {
console.error(
"Cannot update iframe size / position, make sure 'request.data.iframe' has 'height', 'width', and 'position' set correctly",
);
return;
}

const bounds = document.body.getBoundingClientRect();

let styles = {};
switch (position) {
case IframePosition.BOTTOM_CENTER:
styles = {
bottom: "0px",
right: `${bounds.width / 2 - width / 2}px`,
top: "auto",
};
break;
case IframePosition.BOTTOM_RIGHT:
styles = {
bottom: "10px",
right: "10px",
top: "auto",
};
break;
case IframePosition.TOP_RIGHT:
styles = {
bottom: "auto",
display: "block",
right: "10px",
top: "10px",
};
break;
}

return Object.assign(
{
bottom: "auto",
display: "block",
height: `${height}px`,
left: "auto",
right: "auto",
top: "auto",
width: `${width}px`,
},
styles,
);
}

function MainIframe() {
const iframeRef = React.useRef<HTMLIFrameElement>(null);

React.useEffect(() => {
chrome.runtime.onMessage.addListener((request) => {
if (iframeRef.current) {
switch (request.message) {
case LayoutEvents.HIDE:
iframeRef.current.style.display = "none";
break;
case LayoutEvents.RESIZE:
const styles = getIframeStyles(request.data.iframe);
Object.assign(iframeRef.current.style, styles);
break;
case LayoutEvents.SHOW:
iframeRef.current.style.display = "block";
break;
}
}
return true;
});
}, []);

return (
<>
{ReactDOM.createPortal(
<iframe
ref={iframeRef}
seamless={true}
src={`${import.meta.env.VITE_NEST_APP}/extension/main`}
style={{
backgroundColor: "transparent",
border: "none",
bottom: "10px",
boxShadow: "none",
colorScheme: "light",
display: "block",
height: "600px",
left: "auto",
position: "fixed",
right: "10px",
top: "auto",
width: "500px",
zIndex: 99998,
}}
/>,
document.body,
)}
</>
);
}

export default MainIframe;
Loading

0 comments on commit 81b2997

Please sign in to comment.