parent
22c5351b96
commit
c4f12804bb
@ -0,0 +1,161 @@ |
||||
/* eslint-disable @typescript-eslint/no-unused-vars */ |
||||
import React, { useState, useRef, useReducer } from 'react' |
||||
import { ModalDialog } from '@remix-ui/modal-dialog' // eslint-disable-line
|
||||
import { Toaster } from '@remix-ui/toaster' // eslint-disable-line
|
||||
|
||||
interface HomeTabFileProps { |
||||
plugin: any |
||||
} |
||||
|
||||
const loadingInitialState = { |
||||
tooltip: '', |
||||
showModalDialog: false, |
||||
importSource: '' |
||||
} |
||||
|
||||
const loadingReducer = (state = loadingInitialState, action) => { |
||||
return { ...state, tooltip: action.tooltip, showModalDialog: false, importSource: '' } |
||||
} |
||||
|
||||
function HomeTabFile ({plugin}: HomeTabFileProps) { |
||||
const [state, setState] = useState<{ |
||||
searchInput: string, |
||||
showModalDialog: boolean, |
||||
modalInfo: { title: string, loadItem: string, examples: Array<string> }, |
||||
importSource: string, |
||||
toasterMsg: string |
||||
}>({ |
||||
searchInput: '', |
||||
showModalDialog: false, |
||||
modalInfo: { title: '', loadItem: '', examples: [] }, |
||||
importSource: '', |
||||
toasterMsg: '' |
||||
}) |
||||
|
||||
const [, dispatch] = useReducer(loadingReducer, loadingInitialState) |
||||
|
||||
const inputValue = useRef(null) |
||||
|
||||
const processLoading = () => { |
||||
const contentImport = plugin.contentImport |
||||
const workspace = plugin.fileManager.getProvider('workspace') |
||||
contentImport.import( |
||||
state.importSource, |
||||
(loadingMsg) => dispatch({ tooltip: loadingMsg }), |
||||
async (error, content, cleanUrl, type, url) => { |
||||
if (error) { |
||||
toast(error.message || error) |
||||
} else { |
||||
try { |
||||
if (await workspace.exists(type + '/' + cleanUrl)) toast('File already exists in workspace') |
||||
else { |
||||
workspace.addExternal(cleanUrl, content, url) |
||||
plugin.call('menuicons', 'select', 'filePanel') |
||||
}
|
||||
} catch (e) { |
||||
toast(e.message) |
||||
} |
||||
} |
||||
} |
||||
) |
||||
setState(prevState => { |
||||
return { ...prevState, showModalDialog: false, importSource: '' } |
||||
}) |
||||
} |
||||
|
||||
const toast = (message: string) => { |
||||
setState(prevState => { |
||||
return { ...prevState, toasterMsg: message } |
||||
}) |
||||
} |
||||
|
||||
const createNewFile = async () => { |
||||
plugin.verticalIcons.select('filePanel') |
||||
await plugin.call('filePanel', 'createNewFile') |
||||
} |
||||
|
||||
const uploadFile = async (target) => { |
||||
await plugin.call('filePanel', 'uploadFile', target) |
||||
} |
||||
|
||||
const connectToLocalhost = () => { |
||||
plugin.appManager.activatePlugin('remixd') |
||||
} |
||||
const importFromGist = () => { |
||||
plugin.call('gistHandler', 'load', '') |
||||
plugin.verticalIcons.select('filePanel') |
||||
} |
||||
|
||||
const showFullMessage = (title: string, loadItem: string, examples: Array<string>) => { |
||||
setState(prevState => { |
||||
return { ...prevState, showModalDialog: true, modalInfo: { title: title, loadItem: loadItem, examples: examples } } |
||||
}) |
||||
} |
||||
|
||||
const hideFullMessage = () => { //eslint-disable-line
|
||||
setState(prevState => { |
||||
return { ...prevState, showModalDialog: false, importSource: '' } |
||||
}) |
||||
} |
||||
|
||||
const examples = state.modalInfo.examples.map((urlEl, key) => (<div key={key} className="p-1 user-select-auto"><a>{urlEl}</a></div>)) |
||||
|
||||
return ( |
||||
<> |
||||
<ModalDialog |
||||
id='homeTab' |
||||
title={ 'Import from ' + state.modalInfo.title } |
||||
okLabel='Import' |
||||
hide={ !state.showModalDialog } |
||||
handleHide={ () => hideFullMessage() } |
||||
okFn={ () => processLoading() } |
||||
> |
||||
<div className="p-2 user-select-auto"> |
||||
{ state.modalInfo.loadItem !== '' && <span>Enter the { state.modalInfo.loadItem } you would like to load.</span> } |
||||
{ state.modalInfo.examples.length !== 0 && |
||||
<> |
||||
<div>e.g</div> |
||||
<div> |
||||
{ examples } |
||||
</div> |
||||
</> } |
||||
<input |
||||
ref={inputValue} |
||||
type='text' |
||||
name='prompt_text' |
||||
id='inputPrompt_text' |
||||
className="w-100 mt-1 form-control" |
||||
data-id="homeTabModalDialogCustomPromptText" |
||||
value={state.importSource} |
||||
onInput={(e) => { |
||||
setState(prevState => { |
||||
return { ...prevState, importSource: inputValue.current.value } |
||||
}) |
||||
}} |
||||
/> |
||||
</div> |
||||
</ModalDialog> |
||||
<Toaster message={state.toasterMsg} /> |
||||
<div className="justify-content-start p-2 border-bottom d-flex flex-column" id="hTFileSection"> |
||||
<label>Files</label> |
||||
<button className="btn p-2 border my-1" style={{width: 'fit-content'}} onClick={() => createNewFile()}>New File</button> |
||||
<label className="btn p-2 border my-1" style={{width: 'fit-content'}} htmlFor="openFileInput">Open File</label> |
||||
<input title="open file" type="file" id="openFileInput" onChange={(event) => { |
||||
event.stopPropagation() |
||||
plugin.verticalIcons.select('filePanel') |
||||
uploadFile(event.target) |
||||
}} multiple /> |
||||
<button className="btn p-2 border my-1" style={{width: 'fit-content'}} onClick={() => connectToLocalhost()}>Connect for Localhost</button> |
||||
<label className="pt-2">Load From</label> |
||||
<div className="d-flex"> |
||||
<button className="btn p-2 border mr-2" data-id="landingPageImportFromGitHubButton" onClick={() => showFullMessage('GitHub', 'github URL', ['https://github.com/0xcert/ethereum-erc721/src/contracts/tokens/nf-token-metadata.sol', 'https://github.com/OpenZeppelin/openzeppelin-solidity/blob/67bca857eedf99bf44a4b6a0fc5b5ed553135316/contracts/access/Roles.sol'])}>GitHub</button> |
||||
<button className="btn p-2 border mr-2" data-id="landingPalandingPageImportFromGistButtongeImportFromGistButton" onClick={() => importFromGist()}>Gist</button> |
||||
<button className="btn p-2 border mr-2" onClick={() => showFullMessage('Ipfs', 'ipfs URL', ['ipfs://<ipfs-hash>'])}>IPFS</button>
|
||||
<button className="btn p-2 border" onClick={() => showFullMessage('Https', 'http/https raw content', ['https://raw.githubusercontent.com/OpenZeppelin/openzeppelin-contracts/master/contracts/token/ERC20/ERC20.sol'])}>HTTPS</button> |
||||
</div> |
||||
</div> |
||||
</> |
||||
) |
||||
} |
||||
|
||||
export default HomeTabFile |
@ -0,0 +1,56 @@ |
||||
/* eslint-disable @typescript-eslint/no-unused-vars */ |
||||
import React, { useEffect, useState, useContext } from 'react' |
||||
import { ThemeContext } from '../themeContext' |
||||
|
||||
enum VisibleTutorial { |
||||
Basics, |
||||
Intermediate, |
||||
Advanced |
||||
} |
||||
|
||||
function HomeTabLearn () { |
||||
const [state, setState] = useState<{ |
||||
visibleTutorial: VisibleTutorial |
||||
}>({ |
||||
visibleTutorial: VisibleTutorial.Basics |
||||
}) |
||||
|
||||
const themeFilter = useContext(ThemeContext) |
||||
|
||||
const openLink = () => { |
||||
window.open("https://remix-ide.readthedocs.io/en/latest/search.html?q=learneth&check_keywords=yes&area=default", '_blank') |
||||
} |
||||
|
||||
return ( |
||||
<div className="d-flex px-2 pb-2 pt-2 d-flex flex-column" id="hTLearnSection"> |
||||
<div className="d-flex justify-content-between"> |
||||
<label className="pt-2 align-self-center m-0">Learn</label> |
||||
<button |
||||
onClick={ ()=> openLink()} |
||||
className="h-100 px-2 pt-0 btn" |
||||
> |
||||
<img className="align-self-center" src="assets/img/learnEthLogo.webp" alt="" style={ { filter: themeFilter.filter, width: "1rem", height: "1ren" } } /> |
||||
</button> |
||||
</div> |
||||
<div className="d-flex flex-column"> |
||||
<button className="btn border" onClick={() => setState((prevState) => {return { ...prevState, visibleTutorial: VisibleTutorial.Basics }})}> |
||||
{(state.visibleTutorial === VisibleTutorial.Basics) && <div className="text-left"> |
||||
Introduction to Remix's interface and concepts used in Ethereum, as well as the basics of Solidity. |
||||
</div>} |
||||
<label className="pb-1 float-left" style={{fontSize: "1rem"}}>Remix Basics</label> |
||||
</button> |
||||
<button className="btn border " onClick={() => setState((prevState) => {return { ...prevState, visibleTutorial: VisibleTutorial.Intermediate }})}> |
||||
{(state.visibleTutorial === VisibleTutorial.Intermediate) && <div className="text-left">Using the web3.js to interact with a contract. Using Recorder tool.</div>} |
||||
<label className="pb-1 float-left" style={{fontSize: "1rem"}}>Remix Intermediate</label> |
||||
</button> |
||||
<button className="btn border" onClick={() => setState((prevState) => {return { ...prevState, visibleTutorial: VisibleTutorial.Advanced }})}> |
||||
{(state.visibleTutorial === VisibleTutorial.Advanced) && <div className="text-left">Learn the Proxy Pattern and working with Libraries in Remix. Learn to use the Debugger</div>} |
||||
<label className="pb-1 float-left" style={{fontSize: "1rem"}}>Remix Advanced</label> |
||||
</button> |
||||
</div> |
||||
<br/> |
||||
</div> |
||||
) |
||||
} |
||||
|
||||
export default HomeTabLearn |
@ -0,0 +1,101 @@ |
||||
/* eslint-disable @typescript-eslint/no-unused-vars */ |
||||
import React, { useEffect, useState, useRef } from 'react' |
||||
|
||||
function HomeTabTitle () { |
||||
const [state, setState] = useState<{ |
||||
searchInput: string |
||||
}>({ |
||||
searchInput: '' |
||||
}) |
||||
useEffect(() => { |
||||
|
||||
document.addEventListener("keyup", (e) => handleSearchKeyDown(e)) |
||||
|
||||
return () => { |
||||
document.removeEventListener("keyup", handleSearchKeyDown) |
||||
} |
||||
}, []) |
||||
|
||||
const searchInputRef = useRef(null) |
||||
const remiAudioEl = useRef(null) |
||||
|
||||
const playRemi = async () => { |
||||
remiAudioEl.current.play() |
||||
} |
||||
const handleSearchKeyDown = (e: KeyboardEvent) => { |
||||
if (e.target !== searchInputRef.current) return |
||||
if (e.key === "Enter") { |
||||
openLink() |
||||
setState(prevState => { |
||||
return { ...prevState, searchInput: '' } |
||||
}) |
||||
searchInputRef.current.value = "" |
||||
} |
||||
} |
||||
|
||||
const openLink = (url = "") => { |
||||
if (url === "") { |
||||
window.open("https://remix-ide.readthedocs.io/en/latest/search.html?q=" + state.searchInput + "&check_keywords=yes&area=default", '_blank') |
||||
} else { |
||||
window.open(url, '_blank') |
||||
} |
||||
} |
||||
|
||||
return ( |
||||
<div className="px-2 pb-2 pt-2 d-flex flex-column border-bottom" id="hTTitleSection"> |
||||
<div className="mr-4 d-flex"> |
||||
<img className="align-self-end remixui_home_logoImg" src="assets/img/guitarRemiCroped.webp" onClick={ () => playRemi() } alt=""></img> |
||||
<audio |
||||
id="remiAudio" |
||||
muted={false} |
||||
src="assets/audio/remiGuitar-single-power-chord-A-minor.wav" |
||||
ref={remiAudioEl} |
||||
></audio> |
||||
</div> |
||||
<div className="d-flex justify-content-between"> |
||||
<span className="h-80" style={ { fontSize: 'xx-large', fontFamily: "Noah" } }>Remix</span> |
||||
<span> |
||||
<button |
||||
onClick={ ()=> openLink("https://www.youtube.com/channel/UCjTUPyFEr2xDGN6Cg8nKDaA")} |
||||
className="h-100 btn fab fa-youtube"> |
||||
</button> |
||||
<button |
||||
onClick={ ()=> openLink("https://twitter.com/EthereumRemix")} |
||||
className="h-100 pl-2 btn fab fa-twitter"> |
||||
</button> |
||||
</span> |
||||
</div> |
||||
<b className="pb-1 text-dark" style={{fontStyle: 'italic'}}>The Native IDE for Solidity Development.</b> |
||||
<div className="pb-1" id="hTGeneralLinks"> |
||||
<a className="remixui_home_text" target="__blank" href="https://remix-ide.readthedocs.io/en/latest">Learn more</a> |
||||
<a className="pl-2 remixui_home_text" target="__blank" href="https://remix-ide.readthedocs.io/en/latest">Documentation</a> |
||||
<a className="pl-2 remixui_home_text" target="__blank" href="https://remix-ide.readthedocs.io/en/latest">more</a> |
||||
<a className="pl-2 remixui_home_text" target="__blank" href="https://remix-ide.readthedocs.io/en/latest">more</a> |
||||
</div> |
||||
<div className="d-flex pb-1 align-items-center"> |
||||
<input |
||||
ref={searchInputRef} |
||||
onChange={(event) => { |
||||
setState(prevState => { |
||||
return { ...prevState, searchInput: event.target.value.trim() } |
||||
}) |
||||
}} |
||||
type="text" |
||||
className="border form-control border-right-0" |
||||
id="searchInput" |
||||
placeholder="Search Documentation" |
||||
data-id="terminalInputSearch" |
||||
/> |
||||
<button |
||||
className="form-control border d-flex align-items-center p-2 justify-content-center fas fa-search bg-light" |
||||
onClick={ (e) => openLink() } |
||||
disabled={state.searchInput === ""} |
||||
style={{width: "3rem"}} |
||||
> |
||||
</button> |
||||
</div> |
||||
</div> |
||||
) |
||||
} |
||||
|
||||
export default HomeTabTitle |
Loading…
Reference in new issue