Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/send bug report popup #27

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 2 additions & 22 deletions extension/src/content/RPCs/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { copyToClipboard } from "./copyToClipboard"
import { getElementScreenCapture } from "./elementScreenCapture"
import ripple from "./ripple"
import { fetchData } from "./fetchData"
import { initWindowListener, RPCPayload } from './initListeners'
import { initBgRpc, initWindowListener, RPCPayload } from './initListeners'
import { attachMutationListener, detachMutationListener, initMutationObserver } from "./mutationObserver"
import { respondToOtherTab, forwardToTab, getPendingMessage } from "./crossInstanceComms"
import { configs } from "../../constants"
Expand Down Expand Up @@ -44,26 +44,6 @@ type RPC = typeof rpc

export const initRPC = () => {
initWindowListener<RPC>(rpc)
// Function to handle messages from the background script
chrome.runtime.onMessage.addListener((event, sender, sendResponse) => {
const payload: RPCPayload = event
if (!payload || !(payload.fn in rpc)) {
const error = 'Invalid payload'
sendResponse({ error });
return true;
}
if (sender.id == chrome.runtime.id) {
try {
Promise.resolve(rpc[payload.fn](payload.args, sender)).then((response) => {
sendResponse({ response });
}).catch(error => {
sendResponse({ error });
})
} catch (error) {
sendResponse({ error });
}
}
return true
});
initBgRpc<RPC>(rpc)
initMutationObserver()
}
38 changes: 31 additions & 7 deletions extension/src/content/RPCs/initListeners.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { configs } from "../../constants"

export type RPCPayload = {
fn: string
args: any[]
id: number
timeout: number
fn: string
args: any[]
id: number
timeout: number
}

export type RPCError = {
Expand All @@ -26,9 +26,9 @@ export type RPCErrorResponse = {
type: 'error'
}

export const initWindowListener = <T extends RPCs> (rpc: T) => {
export const initWindowListener = <T extends RPCs>(rpc: T) => {
const TRUSTED_ORIGINS = [configs.WEB_URL]
window.addEventListener('message', function(event) {
window.addEventListener('message', function (event) {
const payload: RPCPayload = event.data
if (!TRUSTED_ORIGINS.includes(event.origin) || !payload || !(payload.fn in rpc)) {
return false;
Expand Down Expand Up @@ -63,7 +63,7 @@ export const initWindowListener = <T extends RPCs> (rpc: T) => {
});
}).catch(rawError => {
const error: RPCError = {
message: rawError?.message?? 'An error occurred',
message: rawError?.message ?? 'An error occurred',
}
try {
error.error = JSON.parse(JSON.stringify(rawError))
Expand All @@ -80,4 +80,28 @@ export const initWindowListener = <T extends RPCs> (rpc: T) => {
})
return true
});
}

export const initBgRpc = <T extends RPCs>(rpc: T) => {
// Function to handle messages from the background script
chrome.runtime.onMessage.addListener((event, sender, sendResponse) => {
const payload: RPCPayload = event
if (!payload || !(payload.fn in rpc)) {
const error = 'Invalid payload'
sendResponse({ error });
return true;
}
if (sender.id == chrome.runtime.id) {
try {
Promise.resolve(rpc[payload.fn](payload.args, sender)).then((response) => {
sendResponse({ response });
}).catch(error => {
sendResponse({ error });
})
} catch (error) {
sendResponse({ error });
}
}
return true
});
}
2 changes: 1 addition & 1 deletion extension/src/content/debug.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import userEvent, { PointerEventsCheckLevel } from '@testing-library/user-event';
import { fireEvent } from '@testing-library/dom';
window.userEvent = userEvent
window.fireEvent = fireEvent
window.fireEvent = fireEvent
17 changes: 17 additions & 0 deletions extension/src/content/diagnostics.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { initBgRpc } from 'extension'

const getPageSource = (selector: any): string => {
if (selector) {
selector = document.querySelector(selector);
if (!selector) return "ERROR: querySelector failed to find node"
} else {
selector = document.documentElement;
}
return selector.outerHTML;
}


export const rpc = {
getPageSource,
}
initBgRpc(rpc)
14 changes: 12 additions & 2 deletions extension/src/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
"http://*/*",
"https://*/*"
],
"js": ["contentScript.bundle.js"],
"js": ["contentScript.bundle.js", "diagnostics.bundle.js"],
"css": [],
"run_at": "document_start"
}
Expand All @@ -30,7 +30,17 @@
],
"web_accessible_resources": [
{
"resources": ["content.styles.css", "icon-128.png", "icon-34.png", "*.svg", "metabase.bundle.js", "jupyter.bundle.js", "posthog.bundle.js", "debug.bundle.js"],
"resources": [
"content.styles.css",
"icon-128.png",
"icon-34.png",
"*.svg",
"metabase.bundle.js",
"jupyter.bundle.js",
"posthog.bundle.js",
"debug.bundle.js",
"diagnostics.bundle.js"
],
"matches": ["<all_urls>"]
}
],
Expand Down
2 changes: 1 addition & 1 deletion extension/src/package.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
export { resolveSelector } from './helpers/pageParse/resolveSelectors'
export { initWindowListener } from './content/RPCs/initListeners'
export { initWindowListener, initBgRpc } from './content/RPCs/initListeners'
36 changes: 22 additions & 14 deletions extension/src/popup/Popup.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React, { useEffect } from 'react';
import { Box, Button, Text, ChakraProvider, Image, HStack, IconButton } from '@chakra-ui/react'
import { Box, Button, Text, ChakraProvider, Image, HStack, IconButton, Link } from '@chakra-ui/react'
import { BsTerminalFill, BsTools } from "react-icons/bs";
import { TbWorldShare } from "react-icons/tb";
import { get } from 'lodash'
Expand All @@ -8,27 +8,35 @@ const playgroundLink = 'https://minusx.ai/playground'
const requestToolLink = 'https://minusx.ai/tool-request'
const websiteLink = 'https://minusx.ai'

const getSource = () => {
return chrome.tabs.query({ active: true, currentWindow: true }).then(function (tabs) {
var activeTab = tabs[0];
var activeTabId = activeTab.id;
if (!activeTabId) return "ERROR: no active tab found"
console.log("tab id" , activeTabId)
return chrome.tabs.sendMessage(activeTabId, {fn: 'getPageSource', args: ['html']})
.then(results => {
console.log(results)
return results.response
}).catch(err => {
console.log(err)
})
})
}
export const Popup: React.FC = () => {
const defaultPopupText = `We currently support MinusX on any Jupyter (Lab, Notebook, Lite, etc), or Metabase (SQL Query page) instance. You can test-drive it in a playground we've created for you, or request support for your favourite analytics apps!`
const [popupText, setPopupText] = React.useState<string>(defaultPopupText);
useEffect(() => {
chrome.storage.local.get().then((localConfigs) => {
const popupText = get(localConfigs, "configs.popup_text")
if (popupText) {
setPopupText(popupText)
} else {
setPopupText(defaultPopupText)
}
})
})
return (
<ChakraProvider>
<Box width="400px" p={5}>
<HStack justifyContent={"space-between"}>
<Image width={"150px"} src={chrome.runtime.getURL('logo.svg')} />
<IconButton aria-label="Website" icon={<TbWorldShare />} onClick={() => window.open(websiteLink, '_blank')} isRound={true}/>
</HStack>
<Text bg={'gray.50'} borderRadius={5} p={5} mt={2} fontSize="sm">{popupText}</Text>
<Text bg={'gray.50'} borderRadius={5} p={5} mt={2} fontSize="sm">
Supported tools: Jupyter (Lab, Notebook, Lite, etc), Metabase (SQL Query page), Posthog (HogQL page).
<br/>
Don't see MinusX on your app? Send a <Link href="https://minusx.ai/privacy-simplified"
color="blue" onClick={() => getSource().then(src => alert(src))}>bug report</Link>.
</Text>
<HStack justifyContent={"space-between"}>
<Button mt={2} onClick={() => window.open(playgroundLink, '_blank')} aria-label="Go to Playground" leftIcon={<BsTerminalFill/>} colorScheme='blue' variant='solid'>Go to Playground</Button>
<Button mt={3} onClick={() => window.open(requestToolLink, '_blank')} aria-label="Request Tool" leftIcon={<BsTools/>} colorScheme='gray' variant='solid'>App Support</Button>
Expand Down
2 changes: 2 additions & 0 deletions extension/webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ var options = {
popup: path.join(__dirname, 'src', 'popup', 'index.tsx'),
contentScript: path.join(__dirname, 'src', 'content', 'index.ts'),
debug: path.join(__dirname, 'src', 'content', 'debug.ts'),
// diagnostics file for bug reporting
diagnostics: path.join(__dirname, 'src', 'content', 'diagnostics.ts'),
// @ppsreejith: We can generate this in the future, for now adding manually
// Same in manifest.json file
metabase: path.join(__dirname, '..', 'apps', 'src', 'metabase', 'inject.ts'),
Expand Down