Skip to content

Commit

Permalink
Merge pull request #58 from gnosis/connections-redesign
Browse files Browse the repository at this point in the history
Connections drawer
  • Loading branch information
samepant authored Mar 14, 2023
2 parents 31045cd + efeaa97 commit 88b7c44
Show file tree
Hide file tree
Showing 45 changed files with 1,771 additions and 288 deletions.
27 changes: 16 additions & 11 deletions e2e-tests/tests/initialLaunch.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,12 @@ describe('initial launch', () => {

it('should show the connections list if multiple connections are stored but the selected one is not ready', async () => {
const page = await launch('gnosis')
const $doc = await getDocument(page)

await queries.findByText($doc, 'Connections')
await queries.findByText($doc, 'Gnosis DAO on GC')
await page.waitForSelector('#drawer-root')
const $drawer = await page.$('#drawer-root')

await queries.findByText($drawer, 'Pilot Connections')
await queries.findByText($drawer, 'Gnosis DAO on GC')

await page.close()
await wallet.cancel() // cancel the pending connection request
Expand All @@ -31,17 +33,20 @@ describe('initial launch', () => {
await wallet.disconnect()

const page = await launch('jan')
const $doc = await getDocument(page)

await page.waitForSelector('#drawer-root')
const $drawer = await page.$('#drawer-root')
const $app = await page.$('#root')

// approve the connection request triggered on page load and go back to Pilot page
await metamask.approve()
await page.bringToFront()

// we will see the Connections page now
await queries.findByText($doc, 'Connections')
await queries.findByText($drawer, 'Pilot Connections')

// the jan item has a status of "connected to a different chain"
const $item = await queries.findByText($doc, 'Jan Test DAO')
const $item = await queries.findByText($drawer, 'Jan Test DAO')
const $status = await around($item).getByRole('status')
const status = await $status.evaluate((el) => el.textContent)
expect(status).toBe('Pilot wallet is connected to a different chain')
Expand All @@ -59,8 +64,8 @@ describe('initial launch', () => {
)
await page.bringToFront()

await queries.findByPlaceholderText($doc, 'Type a url')
await queries.findByText($doc, 'Jan Test DAO')
await queries.findByPlaceholderText($app, 'Type a url')
await queries.findByText($app, 'Jan Test DAO')

await page.close()
})
Expand All @@ -70,10 +75,10 @@ describe('initial launch', () => {
await wallet.connectToPilot()

const page = await launch('jan')
const $app = await page.$('#root')

const $doc = await getDocument(page)
await queries.findByPlaceholderText($doc, 'Type a url')
await queries.findByText($doc, 'Jan Test DAO')
await queries.findByPlaceholderText($app, 'Type a url')
await queries.findByText($app, 'Jan Test DAO')
await page.close()
})
})
4 changes: 4 additions & 0 deletions extension/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -76,5 +76,9 @@
"typechain": "^8.0.0",
"typescript": "^4.9.4",
"typescript-plugin-css-modules": "^3.4.0"
},
"dependencies": {
"moment": "^2.29.4",
"react-moment": "^1.1.3"
}
}
88 changes: 51 additions & 37 deletions extension/src/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,69 +7,77 @@ import 'react-toastify/dist/ReactToastify.css'
import './global.css'

import Browser from './browser'
import { prependHttp } from './browser/UrlInput'
import ConnectionsDrawer from './browser/ConnectionsDrawer'
import ProvideProvider from './browser/ProvideProvider'
import { ProvideState } from './browser/state'
import ZodiacToastContainer from './components/Toast'
import { pushLocation } from './location'
import { ProvideMetaMask } from './providers'
import { useMatchSettingsRoute, usePushSettingsRoute } from './routing'
import Settings, { ProvideConnections, useConnection } from './settings'
import { useConnections } from './settings/connectionHooks'
import { ProvideMetaMask, ProvideTenderly } from './providers'
import { useMatchConnectionsRoute, usePushConnectionsRoute } from './routing'
import { ProvideConnections, useConnection } from './settings'
import {
useConnections,
useUpdateLastUsedConnection,
} from './settings/connectionHooks'
import { validateAddress } from './utils'

const Routes: React.FC = () => {
const settingsRouteMatch = useMatchSettingsRoute()
const pushSettingsRoute = usePushSettingsRoute()
const connectionsRouteMatch = useMatchConnectionsRoute()
const pushConnectionsRoute = usePushConnectionsRoute()
const { connection, connected } = useConnection()

const isSettingsRoute = !!settingsRouteMatch
const settingsRequired =
const isConnectionsRoute = connectionsRouteMatch.isMatch
const connectionChangeRequired =
!validateAddress(connection.avatarAddress) ||
!validateAddress(connection.pilotAddress)

const [connections] = useConnections()
const connectionToEdit =
connections.length === 1 ? connections[0].id : undefined

const waitForWallet = !isSettingsRoute && !settingsRequired && !connected
const waitForWallet =
!isConnectionsRoute && !connectionChangeRequired && !connected

// redirect to settings page if more settings are required
useUpdateLastUsedConnection()

// open connections drawer if a valid connection is not available
useEffect(() => {
if (!isSettingsRoute && settingsRequired) {
pushSettingsRoute(connectionToEdit)
if (!isConnectionsRoute && connectionChangeRequired) {
pushConnectionsRoute(connectionToEdit)
}
}, [isSettingsRoute, pushSettingsRoute, connectionToEdit, settingsRequired])
}, [
isConnectionsRoute,
pushConnectionsRoute,
connectionToEdit,
connectionChangeRequired,
])

// redirect to settings page if wallet is not connected, but only after a small delay to give the wallet time to connect when initially loading the page
// open connections drawer if wallet is not connected, but only after a small delay to give the wallet time to connect when initially loading the page
useEffect(() => {
let timeout: number
if (waitForWallet) {
timeout = window.setTimeout(() => {
pushSettingsRoute()
pushConnectionsRoute()
}, 200)
}
return () => {
window.clearTimeout(timeout)
}
}, [waitForWallet, pushSettingsRoute])
}, [waitForWallet, pushConnectionsRoute])

if (!isSettingsRoute && settingsRequired) return null
if (!isSettingsRoute && waitForWallet) return null
if (!isConnectionsRoute && connectionChangeRequired) return null
if (!isConnectionsRoute && waitForWallet) return null

if (isSettingsRoute) {
return (
<Settings
url={settingsRouteMatch.url}
editConnectionId={settingsRouteMatch.editConnectionId}
onLaunch={launch}
return (
<>
<ConnectionsDrawer
isOpen={connectionChangeRequired || isConnectionsRoute}
editConnectionId={connectionsRouteMatch.editConnectionId}
onClose={() => pushLocation(connectionsRouteMatch.url)}
/>
)
}

return <Browser />
}

function launch(url: string) {
pushLocation(prependHttp(url))
<Browser />
</>
)
}

const rootEl = document.getElementById('root')
Expand All @@ -78,11 +86,17 @@ const root = createRoot(rootEl)

root.render(
<React.StrictMode>
<ProvideMetaMask>
<ProvideState>
<ProvideConnections>
<Routes />
<ZodiacToastContainer />
<ProvideMetaMask>
<ProvideTenderly>
<ProvideProvider simulate>
<Routes />
<ZodiacToastContainer />
</ProvideProvider>
</ProvideTenderly>
</ProvideMetaMask>
</ProvideConnections>
</ProvideMetaMask>
</ProvideState>
</React.StrictMode>
)
32 changes: 29 additions & 3 deletions extension/src/bridge/host.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Eip1193Provider } from '../types'
import { Connection, Eip1193Provider } from '../types'

interface Request {
method: string
Expand All @@ -7,16 +7,30 @@ interface Request {

export default class BridgeHost {
private provider: Eip1193Provider
private connection: Connection
private source: WindowProxy | undefined

constructor(provider: Eip1193Provider) {
constructor(provider: Eip1193Provider, connection: Connection) {
this.provider = provider
this.connection = connection
}

setProvider(provider: Eip1193Provider) {
this.provider = provider
}

setConnection(connection: Connection) {
if (connection.avatarAddress !== this.connection.avatarAddress) {
this.emitBridgeEvent('accountsChanged', [[connection.avatarAddress]])
}

if (connection.chainId !== this.connection.chainId) {
this.emitBridgeEvent('chainChanged', [connection.chainId])
}

this.connection = connection
}

initBridge(event: MessageEvent<any>) {
if (!event.source) throw new Error('Unable to get message source')
if (
Expand All @@ -28,6 +42,19 @@ export default class BridgeHost {
this.source = event.source
}

private emitBridgeEvent(event: string, args: any[]) {
if (!this.source) throw new Error('source must be set')

this.source.postMessage(
{
zodiacPilotBridgeEvent: true,
event,
args,
},
'*'
)
}

private async handleRequest(request: Request, messageId: number) {
console.debug('REQ', messageId, request)
if (!this.source) throw new Error('source must be set')
Expand All @@ -54,7 +81,6 @@ export default class BridgeHost {
handleMessage(ev: MessageEvent<any>) {
const {
zodiacPilotBridgeInit,

zodiacPilotBridgeRequest,
messageId,
request,
Expand Down
10 changes: 10 additions & 0 deletions extension/src/bridge/iframe.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,16 @@ export default class BridgeIframe extends EventEmitter {
chainId,
})
})

const handleBridgeEvent = (ev: MessageEvent) => {
const { zodiacPilotBridgeEvent, event, args } = ev.data
if (!zodiacPilotBridgeEvent) {
return
}
this.emit(event, ...args)
}

window.addEventListener('message', handleBridgeEvent)
}

request(request: JsonRpcRequest): Promise<any> {
Expand Down
21 changes: 21 additions & 0 deletions extension/src/browser/ConnectionsDrawer/ConnectIcon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import React from 'react'
import { IconType } from 'react-icons/lib'

const ConnectIcon: IconType = ({ size, color, title, role }) => (
<svg
width={size}
height={size}
viewBox="0 0 24 24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
role={role}
>
{title && <title>{title}</title>}
<path
d="M18.0385 6.964C18.3368 7.35609 18.5657 7.79649 18.715 8.266V8.2645C19.0634 9.3134 19.0235 10.4526 18.6025 11.4745C18.37 12.0355 18.0385 12.532 17.608 12.9625L15.28 15.28L14.3569 14.3567L15.2658 13.4103L16.675 12.0295C16.9784 11.7274 17.2185 11.3679 17.3815 10.972H17.383C17.5535 10.5714 17.6405 10.1403 17.6387 9.70492C17.6369 9.26956 17.5463 8.83915 17.3725 8.44C17.2015 8.044 16.9645 7.6975 16.6645 7.405C16.3705 7.1035 16.0255 6.868 15.6295 6.697C15.2301 6.52295 14.7995 6.43224 14.3638 6.43043C13.9282 6.42863 13.4968 6.51576 13.096 6.6865C12.7005 6.85009 12.29 7.14228 11.9885 7.44601L9.712 9.71211L8.7895 8.788L11.107 6.4615C11.5316 6.03428 12.0369 5.69572 12.5935 5.4655C13.6154 5.04436 14.7546 5.00443 15.8035 5.353C16.273 5.50299 16.7134 5.7323 17.1055 6.031L19.1455 4L20.0695 4.924L18.0385 6.964ZM9.712 9.71211L10.6395 10.6384L10.633 10.6451L13.423 13.4336L13.4284 13.428L14.3569 14.3567L14.356 14.3576L15.28 15.28L12.9625 17.6081C12.5305 18.0386 12.0325 18.3701 11.4655 18.6026C10.9045 18.8351 10.3195 18.9506 9.7105 18.9506C9.2125 18.9506 8.7265 18.8756 8.2555 18.7256C7.7905 18.5681 7.36 18.3386 6.9625 18.0386L4.9225 20.0681L4 19.1456L6.031 17.1056C5.7295 16.7081 5.5 16.2776 5.3425 15.8126C5.1925 15.3416 5.1175 14.8556 5.1175 14.3576C5.11647 13.7557 5.23528 13.1596 5.467 12.6041C5.69447 12.0433 6.03271 11.5341 6.4615 11.1071L8.788 8.78961L9.712 9.71211ZM9.712 17.6381C10.1412 17.6397 10.5664 17.5561 10.963 17.3921C11.3617 17.2246 11.7239 16.9811 12.0295 16.6751L13.4245 15.2801L8.7895 10.6451L7.3945 12.0401C7.08793 12.3429 6.84486 12.7039 6.6795 13.1018C6.51415 13.4997 6.42984 13.9267 6.4315 14.3576C6.42895 14.7974 6.5157 15.2332 6.6865 15.6386C6.85242 16.0272 7.08891 16.3817 7.384 16.6841C7.68625 16.9798 8.04075 17.2168 8.4295 17.3831C8.833 17.5526 9.2605 17.6381 9.712 17.6381Z"
fill={color}
/>
</svg>
)

export default ConnectIcon
Loading

0 comments on commit 88b7c44

Please sign in to comment.