Skip to content

Commit 209dac4

Browse files
authored
Merge pull request #46 from dapplets/dap-4805
2 parents 03d9c2e + 91a6154 commit 209dac4

File tree

12 files changed

+199
-1
lines changed

12 files changed

+199
-1
lines changed

apps/extension/manifest.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,11 @@
1111
"type": "module"
1212
},
1313
"minimum_chrome_version": "95",
14+
"action": {
15+
"default_icon": {
16+
"128": "icons/icon128.png"
17+
}
18+
},
1419
"icons": {
1520
"128": "icons/icon128.png"
1621
},

apps/extension/src/background/index.ts

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,3 +294,38 @@ browser.runtime.onInstalled.addListener(async () => {
294294

295295
browser.tabs.onActivated.addListener(({ tabId }) => mutationLinkListener(tabId))
296296
browser.tabs.onUpdated.addListener((tabId) => mutationLinkListener(tabId))
297+
298+
const overlayPopupOpen = async (tab: browser.Tabs.Tab) => {
299+
if (!tab.id) return
300+
await browser.tabs.sendMessage(tab.id, { type: 'TOGGLE_OVERLAY' })
301+
}
302+
303+
const updateAction = async (tabId: number) => {
304+
const tab = await browser.tabs.get(tabId)
305+
306+
// A normal site where the extension can work
307+
if (tab.id && (tab?.url?.startsWith('https://') || tab?.url?.startsWith('http://'))) {
308+
// The script may not be injected if the extension was just installed
309+
const isContentScriptInjected = await browser.tabs
310+
.sendMessage(tab.id, { type: 'PING' }) // The CS must reply 'PONG'
311+
.then(() => true)
312+
.catch(() => false)
313+
314+
if (isContentScriptInjected) {
315+
await browser.action.setPopup({ tabId, popup: '' })
316+
browser.action.onClicked.addListener(overlayPopupOpen)
317+
} else {
318+
const popupUrl = browser.runtime.getURL('popup.html?page=no-cs-injected')
319+
await browser.action.setPopup({ tabId, popup: popupUrl })
320+
browser.action.onClicked.removeListener(overlayPopupOpen)
321+
}
322+
} else {
323+
// If it's a system tab where the extension doesn't work
324+
const popupUrl = browser.runtime.getURL('popup.html?page=unsupported-page')
325+
await browser.action.setPopup({ tabId, popup: popupUrl })
326+
browser.action.onClicked.removeListener(overlayPopupOpen)
327+
}
328+
}
329+
330+
browser.tabs.onActivated.addListener(({ tabId }) => updateAction(tabId))
331+
browser.tabs.onUpdated.addListener((tabId) => updateAction(tabId))

apps/extension/src/contentscript/index.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,9 @@ async function main() {
9797
} else if (message.type === 'OPEN_NEW_MUTATION_POPUP') {
9898
// ToDo: eventEmitter is intended for near-wallet-selector
9999
eventEmitter.emit('openMutationPopup')
100+
} else if (message.type === 'TOGGLE_OVERLAY') {
101+
// ToDo: eventEmitter is intended for near-wallet-selector
102+
eventEmitter.emit('toggleOverlay')
100103
}
101104
})
102105

apps/extension/src/contentscript/multitable-panel/multitable-panel.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,7 @@ export const MultitablePanel: FC<MultitablePanelProps> = ({ eventEmitter }) => {
175175
<MutableOverlayContainer
176176
notchRef={notchRef}
177177
networkId={config.networkId as NearNetworkId}
178+
eventEmitter={eventEmitter}
178179
setOpen={setIsDropdownVisible}
179180
open={isDropdownVisible}
180181
handleMutateButtonClick={handleMutateButtonClick}

apps/extension/src/contentscript/multitable-panel/mutable-overlay-container.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { EventEmitter as NEventEmitter } from 'events'
12
import { useMutableWeb, useMutationApp } from '@mweb/engine'
23
import { AppInstanceWithSettings } from '@mweb/backend'
34
import { AppSwitcher, MiniOverlay } from '@mweb/shared-components'
@@ -18,12 +19,14 @@ function MutableOverlayContainer({
1819
setOpen,
1920
open,
2021
handleMutateButtonClick,
22+
eventEmitter,
2123
}: {
2224
notchRef: React.RefObject<HTMLDivElement>
2325
networkId: NearNetworkId
2426
setOpen: React.Dispatch<React.SetStateAction<boolean>>
2527
open: boolean
2628
handleMutateButtonClick: () => void
29+
eventEmitter: NEventEmitter
2730
}) {
2831
const { selectedMutation, mutationApps } = useMutableWeb()
2932
const trackingRefs = new Set<React.RefObject<HTMLDivElement>>()
@@ -38,6 +41,7 @@ function MutableOverlayContainer({
3841
connectWallet={Background.connectWallet}
3942
disconnectWallet={Background.disconnectWallet}
4043
trackingRefs={trackingRefs}
44+
eventEmitter={eventEmitter}
4145
handleMutateButtonClick={handleMutateButtonClick}
4246
>
4347
<>

apps/extension/src/popup/App.tsx

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import React from 'react'
2+
import { InfoIcon } from './components/InfoIcon'
3+
4+
export const App: React.FC = () => {
5+
const page = new URLSearchParams(window.location.search).get('page')
6+
7+
switch (page) {
8+
case 'unsupported-page':
9+
return (
10+
<>
11+
<header>
12+
<InfoIcon />
13+
Unsupported page
14+
</header>
15+
<div>You are on an unsupported page</div>
16+
<div>
17+
Mutable Web Extension works on pages with context, for example on{' '}
18+
<a target="_blank" href="https://twitter.com/" rel="noreferrer">
19+
twitter.com
20+
</a>
21+
</div>
22+
</>
23+
)
24+
case 'no-cs-injected':
25+
return (
26+
<>
27+
<header>
28+
<InfoIcon />
29+
Reload page
30+
</header>
31+
<div>
32+
You have installed a new version of the Mutable Web extension. To start working with it,
33+
you need to reload the page
34+
</div>
35+
</>
36+
)
37+
default:
38+
return null
39+
}
40+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import React from 'react'
2+
3+
export const InfoIcon: React.FC = () => (
4+
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20" fill="none">
5+
<g clipPath="url(#clip0_8_7)">
6+
<path
7+
d="M9.99996 18.3333C14.6023 18.3333 18.3333 14.6024 18.3333 10C18.3333 5.39762 14.6023 1.66666 9.99996 1.66666C5.39759 1.66666 1.66663 5.39762 1.66663 10C1.66663 14.6024 5.39759 18.3333 9.99996 18.3333Z"
8+
stroke="#5AB5E8"
9+
strokeWidth="2"
10+
strokeLinecap="round"
11+
strokeLinejoin="round"
12+
/>
13+
<path
14+
d="M10 13.3333V10"
15+
stroke="#5AB5E8"
16+
strokeWidth="2"
17+
strokeLinecap="round"
18+
strokeLinejoin="round"
19+
/>
20+
<path
21+
d="M10 6.66666H10.0083"
22+
stroke="#5AB5E8"
23+
strokeWidth="2"
24+
strokeLinecap="round"
25+
strokeLinejoin="round"
26+
/>
27+
</g>
28+
<defs>
29+
<clipPath id="clip0_8_7">
30+
<rect width="20" height="20" fill="white" />
31+
</clipPath>
32+
</defs>
33+
</svg>
34+
)

apps/extension/src/popup/index.css

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
2+
body {
3+
display: flex;
4+
flex-direction: column;
5+
6+
width: 305px;
7+
height: 80px;
8+
padding: 6px;
9+
}
10+
11+
header {
12+
display: flex;
13+
align-items: center;
14+
15+
margin-bottom: 6px;
16+
17+
18+
font-size: 14px;
19+
font-weight: 400;
20+
line-height: 149%;
21+
color: #5AB5E8;
22+
}
23+
24+
svg {
25+
margin-right: 5px;
26+
}
27+
28+
div{
29+
font-size: 12px;
30+
font-weight: 400;
31+
font-style: normal;
32+
line-height: 149%;
33+
color: #747376;
34+
}
35+
36+
a{
37+
font-size: 12px;
38+
font-weight: 400;
39+
font-style: normal;
40+
line-height: 149%;
41+
color: #588ca3;
42+
text-decoration-line: underline;
43+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<html>
2+
<body>
3+
<div id="app"></div>
4+
</body>
5+
<script src="./popup.js"></script>
6+
</html>

apps/extension/src/popup/index.tsx

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import * as React from 'react'
2+
import * as ReactDOM from 'react-dom'
3+
4+
import { App } from './App'
5+
import './index.css'
6+
7+
const container = document.getElementById('app')
8+
9+
ReactDOM.render(<App />, container)

0 commit comments

Comments
 (0)