From e17b25318ef802e48ece99b06de7136fd0eeedfa Mon Sep 17 00:00:00 2001 From: Michael Wallace Date: Wed, 20 Nov 2024 14:43:41 +1100 Subject: [PATCH 1/7] feat: experimental captcha support --- apps/extension/entrypoints/sandbox/index.html | 124 +++++++++++++++++- apps/extension/wxt.config.ts | 2 +- 2 files changed, 124 insertions(+), 2 deletions(-) diff --git a/apps/extension/entrypoints/sandbox/index.html b/apps/extension/entrypoints/sandbox/index.html index 80ba766..b660e1f 100644 --- a/apps/extension/entrypoints/sandbox/index.html +++ b/apps/extension/entrypoints/sandbox/index.html @@ -17,6 +17,11 @@ height: 100%; } + +
@@ -28,10 +33,97 @@ sandbox="allow-same-origin allow-scripts allow-forms allow-popups allow-popups-to-escape-sandbox allow-modals">
-
@@ -33,92 +28,6 @@ sandbox="allow-same-origin allow-scripts allow-forms allow-popups allow-popups-to-escape-sandbox allow-modals">
+ + diff --git a/apps/extension/entrypoints/options/options.js b/apps/extension/entrypoints/options/options.js new file mode 100644 index 0000000..e1c579e --- /dev/null +++ b/apps/extension/entrypoints/options/options.js @@ -0,0 +1,30 @@ +// Saves options to chrome.storage +const saveOptions = () => { + const use_popup_window = document.getElementById('use_popup_window').checked; + + chrome.storage.sync.set( + { use_popup_window }, + () => { + // Update status to let user know options were saved. + const status = document.getElementById('status'); + status.textContent = 'Options saved.'; + setTimeout(() => { + status.textContent = ''; + }, 750); + } + ); +}; + +// Restores select box and checkbox state using the preferences +// stored in chrome.storage. +const restoreOptions = () => { + chrome.storage.sync.get( + { use_popup_window: false }, + (items) => { + document.getElementById('use_popup_window').checked = items.use_popup_window; + } + ); +}; + +document.addEventListener('DOMContentLoaded', restoreOptions); +document.getElementById('save').addEventListener('click', saveOptions); diff --git a/apps/extension/entrypoints/twitter-observer.content/twitter-observer.tsx b/apps/extension/entrypoints/twitter-observer.content/twitter-observer.tsx index 625200f..a052d69 100644 --- a/apps/extension/entrypoints/twitter-observer.content/twitter-observer.tsx +++ b/apps/extension/entrypoints/twitter-observer.content/twitter-observer.tsx @@ -4,6 +4,7 @@ import "@repo/tlinks/index.css" import { useEffect, useState } from "react" import "~/assets/style.css" import {AbstractActionComponent, TokenscriptCardMetadata} from "@repo/tlinks"; +import {openTsPopupWindow} from "@/lib/open-ts-popup-window"; export const TwitterObserver = () => { const [dAppUrl, setDAppUrl] = useState("") @@ -18,11 +19,19 @@ export const TwitterObserver = () => { connect: () => chrome.runtime.sendMessage({ type: "connect" }), getConnectedAccount: () => chrome.runtime.sendMessage({ type: "getConnectedAccount" }), - interceptHandlePost: (component: AbstractActionComponent) => { + interceptHandlePost: async (component: AbstractActionComponent) => { if (isTokenScriptViewerUrl(component.href)) { - setTsMetadata(component.tsMetadata as TokenscriptCardMetadata) - setDAppUrl(component.href) - iframePopupRef.current?.setOpen(true) + + const options = await chrome.storage.sync.get({ use_popup_window: false }); + + if (options.use_popup_window){ + openTsPopupWindow(component.href, component.tsMetadata); + } else { + setTsMetadata(component.tsMetadata as TokenscriptCardMetadata) + setDAppUrl(component.href) + iframePopupRef.current?.setOpen(true) + } + return true } else { return false diff --git a/apps/extension/lib/handle-tlink-api.ts b/apps/extension/lib/handle-tlink-api.ts index 3052483..6014d7e 100644 --- a/apps/extension/lib/handle-tlink-api.ts +++ b/apps/extension/lib/handle-tlink-api.ts @@ -60,7 +60,7 @@ async function handleTlinkApiViaTSViewerWindow(method: string, payload: any){ }); } -function popupCenter(url: string, title: string, w: number, h: number) { +export function popupCenter(url: string, title: string, w: number, h: number) { const left = (screen.width/2)-(w/2); const top = (screen.height/2)-(h/2); return window.open(url, title, 'toolbar=no, location=no, directories=no, status=no, menubar=no, scrollbars=no, resizable=yes, copyhistory=no, width='+w+', height='+h+', top='+top+', left='+left); diff --git a/apps/extension/lib/open-ts-popup-window.ts b/apps/extension/lib/open-ts-popup-window.ts new file mode 100644 index 0000000..9d19add --- /dev/null +++ b/apps/extension/lib/open-ts-popup-window.ts @@ -0,0 +1,72 @@ +import {handleTlinkApiRequest, popupCenter} from "@/lib/handle-tlink-api.ts"; +import {TokenscriptCardMetadata} from "@repo/tlinks/src"; + +export function openTsPopupWindow(dAppUrl: string, tsMetadata: TokenscriptCardMetadata){ + + let popup; + + const handleMessage = async (event: MessageEvent) => { + + // We only proxy messages that originate from the child iframe + if (!popup || event.source !== popup) { + return + } + + console.log("Processing message from popup", event, popup); + + if (event.data?.type === "TLINK_API_REQUEST") { + popup.postMessage( + { + type: "TLINK_API_RESPONSE", + source: "TLINK_API_RESPONSE", + data: { + uid: event.data.data.uid, + method: event.data.data.method, + response: await handleTlinkApiRequest( + event.data.data.method, + event.data.data.payload + ) + } + }, + "*" + ) + } + + if (event.data?.jsonrpc) { + const resp = await chrome.runtime.sendMessage({ + type: "rpc", + data: event.data + }) + + sendResponse(event.data, resp) + } + + function sendResponse( + messageData: MessageEvent["data"], + response: any | null + ) { + const data = messageData + + if (response?.error) { + data.error = response.error + } else { + data.result = response.result + } + + popup!!.postMessage( + data, + "*" + ) + } + } + + const width = tsMetadata.fullScreen ? Math.round(screen.width * 0.9) : 550; + const height = tsMetadata.fullScreen ? Math.round(screen.height * 0.9) : 800; + + popup = popupCenter(dAppUrl, "", width, height); + + window.addEventListener("message", handleMessage); + + if (!popup) + throw new Error("Failed to open the popup window"); +} \ No newline at end of file diff --git a/packages/tlinks/src/api/ActionConfig.ts b/packages/tlinks/src/api/ActionConfig.ts index 3955e65..c761952 100644 --- a/packages/tlinks/src/api/ActionConfig.ts +++ b/packages/tlinks/src/api/ActionConfig.ts @@ -39,7 +39,7 @@ export interface ActionAdapter { | { signature: string } | { error: string | { code: number; message: string } } >; - interceptHandlePost?: (href: AbstractActionComponent) => boolean; + interceptHandlePost?: (href: AbstractActionComponent) => boolean|Promise; tsIframeRenderer?: (props: { websiteUrl: string }) => JSX.Element | null; } @@ -74,7 +74,7 @@ export class ActionConfig implements ActionAdapter { } } - interceptHandlePost(component: AbstractActionComponent) { + async interceptHandlePost(component: AbstractActionComponent) { return this.adapter.interceptHandlePost?.(component) || false; }