Merge branch 'master' of https://github.com/ethereum/remix-project
commit
4d3dd97c80
@ -0,0 +1,190 @@ |
||||
import React from 'react' // eslint-disable-line
|
||||
import { ViewPlugin } from '@remixproject/engine-web' |
||||
import { PluginViewWrapper } from '@remix-ui/helper' |
||||
import { RemixUIGridView } from '@remix-ui/remix-ui-grid-view' |
||||
import { RemixUIGridSection } from '@remix-ui/remix-ui-grid-section' |
||||
import { RemixUIGridCell } from '@remix-ui/remix-ui-grid-cell' |
||||
import './style/environment-explorer.css' |
||||
import type { Provider } from '../../blockchain/blockchain' |
||||
|
||||
import * as packageJson from '../../../../../package.json' |
||||
|
||||
const _paq = (window._paq = window._paq || []) |
||||
|
||||
const profile = { |
||||
name: 'environmentExplorer', |
||||
displayName: 'Environment Explorer', |
||||
icon: 'assets/img/EnvironmentExplorerLogo.webp', |
||||
description: 'Explore providers and customize web3 provider list', |
||||
location: 'mainPanel', |
||||
documentation: 'https://remix-ide.readthedocs.io/en/latest/run.html', |
||||
version: packageJson.version, |
||||
maintainedBy: 'Remix', |
||||
permission: true, |
||||
events: [], |
||||
methods: [] |
||||
} |
||||
|
||||
type ProvidersSection = `Injected` | 'Remix VMs' | 'Externals' |
||||
|
||||
export class EnvironmentExplorer extends ViewPlugin { |
||||
providers: { [key in ProvidersSection]: Provider[] } |
||||
providersFlat: { [key: string]: Provider } |
||||
pinnedProviders: string[] |
||||
dispatch: React.Dispatch<any> = () => {} |
||||
|
||||
constructor() { |
||||
super(profile) |
||||
this.providersFlat = {} |
||||
this.providers = { |
||||
'Injected': [], |
||||
'Remix VMs': [], |
||||
'Externals': [] |
||||
} |
||||
} |
||||
|
||||
async onActivation(): Promise<void> { |
||||
this.providersFlat = await this.call('blockchain', 'getAllProviders') |
||||
this.pinnedProviders = await this.call('blockchain', 'getPinnedProviders') |
||||
this.renderComponent() |
||||
} |
||||
|
||||
addProvider (provider: Provider) { |
||||
if (provider.isInjected) { |
||||
this.providers['Injected'].push(provider) |
||||
} else if (provider.isVM) { |
||||
this.providers['Remix VMs'].push(provider) |
||||
} else { |
||||
this.providers['Externals'].push(provider) |
||||
} |
||||
} |
||||
|
||||
setDispatch(dispatch: React.Dispatch<any>): void { |
||||
this.dispatch = dispatch |
||||
this.renderComponent() |
||||
} |
||||
render() { |
||||
return ( |
||||
<div className="bg-dark" id="environmentExplorer"> |
||||
<PluginViewWrapper plugin={this} /> |
||||
</div> |
||||
) |
||||
} |
||||
|
||||
renderComponent() { |
||||
this.dispatch({ |
||||
...this |
||||
}) |
||||
} |
||||
|
||||
updateComponent(state: any) { |
||||
this.providers = { |
||||
'Injected': [], |
||||
'Remix VMs': [], |
||||
'Externals': [] |
||||
} |
||||
console.log(this.providersFlat) |
||||
for (const [key, provider] of Object.entries(this.providersFlat)) { |
||||
this.addProvider(provider) |
||||
} |
||||
return ( |
||||
<RemixUIGridView |
||||
plugin={this} |
||||
styleList={""} |
||||
logo={profile.icon} |
||||
enableFilter={true} |
||||
showUntagged={true} |
||||
showPin={true} |
||||
title={profile.description} |
||||
description="Choose how you would like to interact with a chain." |
||||
> |
||||
<RemixUIGridSection |
||||
plugin={this} |
||||
title='Injected' |
||||
hScrollable={true} |
||||
> |
||||
{this.providers['Injected'].map(provider => { |
||||
return <RemixUIGridCell |
||||
plugin={this} |
||||
title={provider.name} |
||||
classList='EECellStyle' |
||||
pinned={this.pinnedProviders.includes(provider.name)} |
||||
pinStateCallback={async (pinned: boolean) => { |
||||
if (pinned) { |
||||
this.emit('providerPinned', provider.name, provider) |
||||
return true |
||||
} |
||||
const providerName = await this.call('blockchain', 'getProvider') |
||||
if (providerName !== provider.name) { |
||||
this.emit('providerUnpinned', provider.name, provider) |
||||
return true |
||||
} else { |
||||
this.call('notification', 'toast', 'Cannot unpin the current selected provider') |
||||
return false |
||||
} |
||||
}} |
||||
> |
||||
<div>{provider.name}</div> |
||||
</RemixUIGridCell> |
||||
})} |
||||
</RemixUIGridSection> |
||||
<RemixUIGridSection |
||||
plugin={this} |
||||
title='Remix VMs' |
||||
hScrollable= {true} |
||||
>{this.providers['Remix VMs'].map(provider => { |
||||
return <RemixUIGridCell |
||||
plugin={this} |
||||
title={provider.name} |
||||
classList='EECellStyle' |
||||
pinned={this.pinnedProviders.includes(provider.name)} |
||||
pinStateCallback={async (pinned: boolean) => { |
||||
if (pinned) { |
||||
this.emit('providerPinned', provider.name, provider) |
||||
return true |
||||
} |
||||
const providerName = await this.call('blockchain', 'getProvider') |
||||
if (providerName !== provider.name) { |
||||
this.emit('providerUnpinned', provider.name, provider) |
||||
return true |
||||
} else { |
||||
this.call('notification', 'toast', 'Cannot unpin the current selected provider') |
||||
return false |
||||
} |
||||
}} |
||||
> |
||||
<div>{provider.name}</div> |
||||
</RemixUIGridCell> |
||||
})}</RemixUIGridSection> |
||||
<RemixUIGridSection |
||||
plugin={this} |
||||
title='Externals' |
||||
hScrollable= {true} |
||||
>{this.providers['Externals'].map(provider => { |
||||
return <RemixUIGridCell |
||||
plugin={this} |
||||
title={provider.name} |
||||
classList='EECellStyle' |
||||
pinned={this.pinnedProviders.includes(provider.name)} |
||||
pinStateCallback={async (pinned: boolean) => { |
||||
if (pinned) { |
||||
this.emit('providerPinned', provider.name, provider) |
||||
return true |
||||
} |
||||
const providerName = await this.call('blockchain', 'getProvider') |
||||
if (providerName !== provider.name) { |
||||
this.emit('providerUnpinned', provider.name, provider) |
||||
return true |
||||
} else { |
||||
this.call('notification', 'toast', 'Cannot unpin the current selected provider') |
||||
return false |
||||
} |
||||
}} |
||||
> |
||||
<div>{provider.name}</div> |
||||
</RemixUIGridCell> |
||||
})}</RemixUIGridSection> |
||||
</RemixUIGridView> |
||||
) |
||||
} |
||||
} |
@ -0,0 +1,6 @@ |
||||
.EECellStyle { |
||||
min-height: 4rem; |
||||
max-width: 10rem; |
||||
min-width: 9rem; |
||||
max-height: 5rem; |
||||
} |
After Width: | Height: | Size: 9.9 KiB |
@ -0,0 +1,13 @@ |
||||
import { IFilePanel } from '@remixproject/plugin-api' |
||||
import { StatusEvents } from '@remixproject/plugin-utils' |
||||
|
||||
export interface ILayoutApi { |
||||
events:{ |
||||
} & StatusEvents |
||||
methods: { |
||||
maximisePinnedPanel: () => void |
||||
maximiseSidePanel: () => void |
||||
resetPinnedPanel: () => void |
||||
resetSidePanel: () => void |
||||
} |
||||
} |
@ -0,0 +1,11 @@ |
||||
import { IFilePanel } from '@remixproject/plugin-api' |
||||
import { StatusEvents } from '@remixproject/plugin-utils' |
||||
|
||||
export interface IPinnedPanelApi { |
||||
events:{ |
||||
|
||||
} & StatusEvents |
||||
methods: { |
||||
currentFocus(): Promise<string> |
||||
} |
||||
} |
@ -0,0 +1,11 @@ |
||||
import { IFilePanel } from '@remixproject/plugin-api' |
||||
import { StatusEvents } from '@remixproject/plugin-utils' |
||||
|
||||
export interface ISidePanelApi { |
||||
events:{ |
||||
focusChanged: (name: string) => void; |
||||
} & StatusEvents |
||||
methods: { |
||||
|
||||
} |
||||
} |
@ -0,0 +1,17 @@ |
||||
import React, { createContext } from 'react' |
||||
import { defaultStatusBarContext, StatusBarContextType, StatusBarInterface } from '../lib/types' |
||||
|
||||
export const StatusBarContext = createContext<StatusBarContextType>(defaultStatusBarContext) |
||||
|
||||
export function StatusBarContextProvider ({ children }) { |
||||
const statusBarProviderValues = { |
||||
test: true |
||||
} |
||||
return ( |
||||
<> |
||||
<StatusBarContext.Provider value={statusBarProviderValues}> |
||||
{children} |
||||
</StatusBarContext.Provider> |
||||
</> |
||||
) |
||||
} |
@ -0,0 +1,35 @@ |
||||
import { CustomTooltip } from '@remix-ui/helper' |
||||
import axios from 'axios' |
||||
import React, { useEffect, useState } from 'react' |
||||
|
||||
export default function DidYouKnow () { |
||||
const [tip, setTip] = useState<string>('') |
||||
useEffect(() => { |
||||
const abortController = new AbortController() |
||||
const signal = abortController.signal |
||||
async function showRemixTips() { |
||||
const response = await axios.get('https://raw.githubusercontent.com/remix-project-org/remix-dynamics/main/ide/tips.json', { signal }) |
||||
if (signal.aborted) return |
||||
const tips = response.data |
||||
const index = Math.floor(Math.random() * (tips.length - 1)) |
||||
setTip(tips[index]) |
||||
} |
||||
try { |
||||
showRemixTips() |
||||
} catch (e) { |
||||
console.log(e) |
||||
} |
||||
return () => { |
||||
abortController.abort() |
||||
} |
||||
}, []) |
||||
return ( |
||||
<CustomTooltip tooltipText={'Did you know'}> |
||||
<div className="remixui_statusbar_didyouknow text-white small d-flex align-items-center"> |
||||
<span className="pr-2 text-success fa-solid fa-lightbulb"></span> |
||||
<div className="mr-2">Did you know?</div> |
||||
{ tip && tip.length > 0 ? <div>{tip}</div> : null } |
||||
</div> |
||||
</CustomTooltip> |
||||
) |
||||
} |
Loading…
Reference in new issue