pull/1840/head
bunsenstraat 3 years ago
parent d70ddf7729
commit 6adfafc752
  1. 56
      apps/remix-ide/src/app-component.js
  2. 1
      apps/remix-ide/src/app.tsx
  3. 2
      apps/remix-ide/src/walkthroughService.js
  4. 5
      libs/remix-ui/app/src/lib/remix-app/context/context.tsx
  5. 43
      libs/remix-ui/app/src/lib/remix-app/modals/alert.tsx
  6. 55
      libs/remix-ui/app/src/lib/remix-app/modals/matomo.tsx
  7. 16
      libs/remix-ui/app/src/lib/remix-app/modals/splashscreen.tsx
  8. 66
      libs/remix-ui/app/src/lib/remix-app/remix-app.css
  9. 48
      libs/remix-ui/app/src/lib/remix-app/remix-app.tsx
  10. 4
      libs/remix-ui/app/src/lib/remix-app/style/remix-app.css

@ -11,6 +11,7 @@ import { HiddenPanel } from './app/components/hidden-panel'
import { VerticalIcons } from './app/components/vertical-icons'
import { LandingPage } from './app/ui/landing-page/landing-page'
import { MainPanel } from './app/components/main-panel'
import { FramingService } from './framingService'
import { WalkthroughService } from './walkthroughService'
@ -54,6 +55,7 @@ class AppComponent {
const self = this
self.appManager = new RemixAppManager({})
self._components = {}
self.registry = registry
// setup storage
const configStorage = new Storage('config-v0.8:')
@ -84,16 +86,32 @@ class AppComponent {
self.engine = new RemixEngine()
self.engine.register(appManager)
const queryParams = new QueryParams()
const params = queryParams.get()
self.startWalkthroughService = () => {
console.log('start walkthrough')
const walkthroughService = new WalkthroughService(localStorage)
if (!params.code && !params.url && !params.minimizeterminal && !params.gist && !params.minimizesidepanel) {
walkthroughService.start()
}
}
self.startWalkthroughService()
const hosts = ['127.0.0.1:8080', '192.168.0.101:8080', 'localhost:8080']
// workaround for Electron support
if (!isElectron() && !hosts.includes(window.location.host)) {
// Oops! Accidentally trigger refresh or bookmark.
window.onbeforeunload = function () {
return 'Are you sure you want to leave?'
}
}
// SERVICES
// ----------------- theme service ---------------------------------
const themeModule = new ThemeModule(registry)
registry.put({ api: themeModule, name: 'themeModule' })
themeModule.initTheme(() => {
setTimeout(() => {
// document.body.removeChild(self._view.splashScreen)
// self._view.el.style.visibility = 'visible'
}, 1500)
})
self.themeModule = new ThemeModule(registry)
registry.put({ api: self.themeModule, name: 'themeModule' })
// ----------------- editor service ----------------------------
const editor = new Editor() // wrapper around ace editor
registry.put({ api: editor, name: 'editor' })
@ -147,7 +165,7 @@ class AppComponent {
self.engine.register([
blockchain,
contentImport,
themeModule,
self.themeModule,
editor,
fileManager,
compilerMetadataGenerator,
@ -179,7 +197,7 @@ class AppComponent {
const pluginManagerComponent = new PluginManagerComponent(appManager, self.engine)
const filePanel = new FilePanel(appManager)
const landingPage = new LandingPage(appManager, self.menuicons, fileManager, filePanel, contentImport)
const settings = new SettingsTab(
self.settings = new SettingsTab(
registry.get('config').api,
editor,
appManager
@ -192,7 +210,7 @@ class AppComponent {
self.sidePanel,
filePanel,
pluginManagerComponent,
settings
self.settings
])
// CONTENT VIEWS & DEFAULT PLUGINS
@ -230,6 +248,8 @@ class AppComponent {
filePanel.hardhatHandle,
filePanel.slitherHandle
])
}
async activate () {
@ -259,15 +279,6 @@ class AppComponent {
await self.appManager.registerContextMenuItems()
})
const startWalkthroughService = () => {
const walkthroughService = new WalkthroughService(localStorage)
if (!params.code && !params.url && !params.minimizeterminal && !params.gist && !params.minimizesidepanel) {
walkthroughService.start()
}
}
startWalkthroughService()
await self.appManager.activatePlugin(['filePanel'])
// Set workspace after initial activation
self.appManager.on('editor', 'editorMounted', () => {
@ -301,6 +312,11 @@ class AppComponent {
})
// activate solidity plugin
self.appManager.activatePlugin(['solidity', 'udapp'])
// Load and start the service who manager layout and frame
const framingService = new FramingService(self.sidePanel, self.menuicons, self.mainview, this._components.resizeFeature)
if (params.embed) framingService.embed()
framingService.start(params)
}
}

@ -5,6 +5,7 @@ import AppComponent from './app-component'
const appComponent = new AppComponent()
appComponent.run()
function App () {
return <>
<RemixApp app={appComponent}></RemixApp>

@ -47,6 +47,8 @@ export class WalkthroughService {
}
}).start()
localStorage.setItem('hadTour_initial', true)
} else {
console.log('had walkthrough')
}
})
}

@ -0,0 +1,5 @@
import React from 'react'
const AppContext = React.createContext(null)
export default AppContext

@ -0,0 +1,43 @@
import React, { useEffect, useState } from 'react'
import { ModalDialog } from '@remix-ui/modal-dialog'
const AlertModal = () => {
const [visible, setVisible] = useState<boolean>(true)
const [content, setContent] = useState<string>('')
useEffect(() => {
// check the origin and warn message
if (window.location.hostname === 'yann300.github.io') {
setContent('This UNSTABLE ALPHA branch of Remix has been moved to http://ethereum.github.io/remix-live-alpha.')
} else if (window.location.hostname === 'remix-alpha.ethereum.org' ||
(window.location.hostname === 'ethereum.github.io' && window.location.pathname.indexOf('/remix-live-alpha') === 0)) {
setContent('Welcome to the Remix alpha instance. Please use it to try out latest features. But use preferably https://remix.ethereum.org for any production work.')
} else if (window.location.protocol.indexOf('http') === 0 &&
window.location.hostname !== 'remix.ethereum.org' &&
window.location.hostname !== 'localhost' &&
window.location.hostname !== '127.0.0.1') {
setContent(`The Remix IDE has moved to http://remix.ethereum.org.\n
This instance of Remix you are visiting WILL NOT BE UPDATED.\n
Please make a backup of your contracts and start using http://remix.ethereum.org`)
}
setVisible(content !== '')
}, [])
const closeModal = async () => {
setVisible(false)
}
const handleModalOkClick = async () => {
setVisible(false)
}
return (<ModalDialog
handleHide={closeModal}
id="appAlert"
hide={!visible}
title="Alert"
okLabel="Ok"
okFn={ handleModalOkClick }
cancelLabel=""
cancelFn={closeModal}>{content}</ModalDialog>)
}
export default AlertModal

@ -0,0 +1,55 @@
import React, { useContext, useEffect, useState } from 'react'
import { ModalDialog } from '@remix-ui/modal-dialog'
import AppContext from '../context/context'
const _paq = window._paq = window._paq || []
const MatomoDialog = (props) => {
const { settings, registry, startWalkthroughService } = useContext(AppContext)
const [visible, setVisible] = useState<boolean>(props.hide)
useEffect(() => {
const matomoDomains = {
'remix-alpha.ethereum.org': 27,
'remix-beta.ethereum.org': 25,
'remix.ethereum.org': 23,
localhost: 24
}
if (matomoDomains[window.location.hostname] && !registry.get('config').api.exists('settings/matomo-analytics')) {
setVisible(true)
} else {
setVisible(false)
}
}, [])
const declineModal = async () => {
settings.updateMatomoAnalyticsChoice(false)
_paq.push(['optUserOut'])
setVisible(false)
}
const hideModal = async () => {
setVisible(false)
}
const handleModalOkClick = async () => {
_paq.push(['forgetUserOptOut'])
// @TODO remove next line when https://github.com/matomo-org/matomo/commit/9e10a150585522ca30ecdd275007a882a70c6df5 is used
document.cookie = 'mtm_consent_removed=; expires=Thu, 01 Jan 1970 00:00:01 GMT;'
settings.updateMatomoAnalyticsChoice(true)
setVisible(false)
}
return (<ModalDialog
handleHide={hideModal}
id="matomoDialog"
hide={!visible}
title="Help us to improve Remix IDE"
okLabel="Accept"
okFn={ handleModalOkClick }
cancelLabel="Decline"
cancelFn={declineModal}>
<p>An Opt-in version of <a href="https://matomo.org" target="_blank" rel="noreferrer">Matomo</a>, an open source data analytics platform is being used to improve Remix IDE.</p>
<p>We realize that our users have sensitive information in their code and that their privacy - your privacy - must be protected.</p>
<p>All data collected through Matomo is stored on our own server - no data is ever given to third parties. Our analytics reports are public: <a href="https://matomo.ethereum.org/index.php?module=MultiSites&action=index&idSite=23&period=day&date=yesterday" target="_blank" rel="noreferrer">take a look</a>.</p>
<p>We do not collect nor store any personally identifiable information (PII).</p>
<p>For more info, see: <a href="https://medium.com/p/66ef69e14931/" target="_blank" rel="noreferrer">Matomo Analyitcs on Remix iDE</a>.</p>
<p>You can change your choice in the Settings panel anytime.</p>
</ModalDialog>)
}
export default MatomoDialog

@ -0,0 +1,16 @@
import React from 'react'
const RemixSplashScreen = (props) => {
return (<> <div style={{ display: props.hide ? 'none' : 'block' }} className='centered'>
<svg id="Ebene_2" data-name="Ebene 2" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 105 100">
<path d="M91.84,35a.09.09,0,0,1-.1-.07,41,41,0,0,0-79.48,0,.09.09,0,0,1-.1.07C9.45,35,1,35.35,1,42.53c0,8.56,1,16,6,20.32,2.16,1.85,5.81,2.3,9.27,2.22a44.4,44.4,0,0,0,6.45-.68.09.09,0,0,0,.06-.15A34.81,34.81,0,0,1,17,45c0-.1,0-.21,0-.31a35,35,0,0,1,70,0c0,.1,0,.21,0,.31a34.81,34.81,0,0,1-5.78,19.24.09.09,0,0,0,.06.15,44.4,44.4,0,0,0,6.45.68c3.46.08,7.11-.37,9.27-2.22,5-4.27,6-11.76,6-20.32C103,35.35,94.55,35,91.84,35Z"/>
<path d="M52,74,25.4,65.13a.1.1,0,0,0-.1.17L51.93,91.93a.1.1,0,0,0,.14,0L78.7,65.3a.1.1,0,0,0-.1-.17L52,74A.06.06,0,0,1,52,74Z"/>
<path d="M75.68,46.9,82,45a.09.09,0,0,0,.08-.09,29.91,29.91,0,0,0-.87-6.94.11.11,0,0,0-.09-.08l-6.43-.58a.1.1,0,0,1-.06-.18l4.78-4.18a.13.13,0,0,0,0-.12,30.19,30.19,0,0,0-3.65-6.07.09.09,0,0,0-.11,0l-5.91,2a.1.1,0,0,1-.12-.14L72.19,23a.11.11,0,0,0,0-.12,29.86,29.86,0,0,0-5.84-4.13.09.09,0,0,0-.11,0l-4.47,4.13a.1.1,0,0,1-.17-.07l.09-6a.1.1,0,0,0-.07-.1,30.54,30.54,0,0,0-7-1.47.1.1,0,0,0-.1.07l-2.38,5.54a.1.1,0,0,1-.18,0l-2.37-5.54a.11.11,0,0,0-.11-.06,30,30,0,0,0-7,1.48.12.12,0,0,0-.07.1l.08,6.05a.09.09,0,0,1-.16.07L37.8,18.76a.11.11,0,0,0-.12,0,29.75,29.75,0,0,0-5.83,4.13.11.11,0,0,0,0,.12l2.59,5.6a.11.11,0,0,1-.13.14l-5.9-2a.11.11,0,0,0-.12,0,30.23,30.23,0,0,0-3.62,6.08.11.11,0,0,0,0,.12l4.79,4.19a.1.1,0,0,1-.06.17L23,37.91a.1.1,0,0,0-.09.07A29.9,29.9,0,0,0,22,44.92a.1.1,0,0,0,.07.1L28.4,47a.1.1,0,0,1,0,.18l-5.84,3.26a.16.16,0,0,0,0,.11,30.17,30.17,0,0,0,2.1,6.76c.32.71.67,1.4,1,2.08a.1.1,0,0,0,.06,0L52,68.16H52l26.34-8.78a.1.1,0,0,0,.06-.05,30.48,30.48,0,0,0,3.11-8.88.1.1,0,0,0-.05-.11l-5.83-3.26A.1.1,0,0,1,75.68,46.9Z"/>
</svg>
<div className="info-secondary splash">
REMIX IDE
</div>
</div></>)
}
export default RemixSplashScreen

@ -1,66 +0,0 @@
html { box-sizing: border-box; }
*, *:before, *:after { box-sizing: inherit; }
body {
/* font: 14px/1.5 Lato, "Helvetica Neue", Helvetica, Arial, sans-serif; */
font-size : .8rem;
}
pre {
overflow-x: auto;
}
.remixIDE {
width : 100vw;
height : 100vh;
overflow : hidden;
flex-direction : row;
display : flex;
}
.mainpanel {
display : flex;
flex-direction : column;
overflow : hidden;
flex : 1;
min-width : 320px;
}
.iconpanel {
display : flex;
flex-direction : column;
overflow : hidden;
width : 50px;
user-select : none;
}
.sidepanel {
display : flex;
flex-direction : row-reverse;
width : 320px;
}
.highlightcode {
position : absolute;
z-index : 20;
background-color : var(--info);
}
.highlightcode_fullLine {
position : absolute;
z-index : 20;
background-color : var(--info);
opacity : 0.5;
}
.centered {
position : fixed;
top : 20%;
left : 45%;
width : 200px;
height : 200px;
}
.centered svg path {
fill: var(--secondary);
}
.centered svg polygon {
fill : var(--secondary);
}
.onboarding {
color : var(--text-info);
background-color : var(--info);
}
.matomoBtn {
width : 100px;
}

@ -1,13 +1,15 @@
import React, { useEffect, useRef, useState } from 'react'
import { ModalDialog } from '@remix-ui/modal-dialog'
import './remix-app.css'
import React, { useContext, useEffect, useRef, useState } from 'react'
import './style/remix-app.css'
import RemixSplashScreen from './modals/splashscreen'
import MatomoDialog from './modals/matomo'
import AlertModal from './modals/alert'
import AppContext from './context/context'
interface IRemixAppUi {
app: any
}
const RemixApp = (props: IRemixAppUi) => {
const [visible, setVisible] = useState<boolean>(false)
const [appReady, setAppReady] = useState<boolean>(false)
const sidePanelRef = useRef(null)
const mainPanelRef = useRef(null)
const iconPanelRef = useRef(null)
@ -35,9 +37,15 @@ const RemixApp = (props: IRemixAppUi) => {
hiddenPanelRef.current.appendChild(props.app.hiddenPanel.render())
}
}
async function activateApp () {
props.app.themeModule.initTheme(() => {
setAppReady(true)
props.app.activate()
})
}
if (props.app) {
console.log('app', props.app)
props.app.activate()
activateApp()
}
}, [])
@ -48,33 +56,19 @@ const RemixApp = (props: IRemixAppUi) => {
hiddenPanel: <div ref={hiddenPanelRef}></div>
}
const handleModalOkClick = async () => {
}
const closeModal = async () => {
}
return (
<>
<div className='remixIDE' hidden={false} data-id="remixIDE">
<AppContext.Provider value={{ settings: props.app.settings, registry: props.app.registry, startWalkthroughService: props.app.startWalkthroughService }}>
<RemixSplashScreen hide={appReady}></RemixSplashScreen>
<AlertModal></AlertModal>
<MatomoDialog hide={!appReady}></MatomoDialog>
<div className={`remixIDE ${appReady ? '' : 'd-none'}`} data-id="remixIDE">
{components.iconPanel}
{components.sidePanel}
{components.mainPanel}
</div>
<ModalDialog
handleHide={closeModal}
id="pluginManagerLocalPluginModalDialog"
hide={!visible}
title="Modal"
okLabel="OK"
okFn={ handleModalOkClick }
cancelLabel="Cancel"
cancelFn={closeModal}
>test</ModalDialog>
{components.hiddenPanel}
</>
</AppContext.Provider>
)
}

@ -68,7 +68,3 @@ pre {
.splash {
text-align: center;
}
.showApp {
display: none;
}
Loading…
Cancel
Save