open folder

rdesktop^2
bunsenstraat 1 year ago
parent 274a3c7cbd
commit b8ed5556cb
  1. 5
      apps/remixdesktop/src/main.ts
  2. 58
      apps/remixdesktop/src/plugins/configPlugin.ts
  3. 14
      apps/remixdesktop/src/plugins/fsPlugin.ts
  4. 37
      apps/remixdesktop/src/utils/config.ts
  5. 6
      libs/remix-ui/workspace/src/lib/actions/index.ts
  6. 4
      libs/remix-ui/workspace/src/lib/actions/workspace.ts
  7. 1
      libs/remix-ui/workspace/src/lib/contexts/index.ts
  8. 11
      libs/remix-ui/workspace/src/lib/providers/FileSystemProvider.tsx
  9. 586
      libs/remix-ui/workspace/src/lib/remix-ui-workspace.tsx

@ -13,6 +13,9 @@ if (
isPackaged = true; isPackaged = true;
} }
// get system home dir
const homeDir = app.getPath('userData')
export let mainWindow: BrowserWindow; export let mainWindow: BrowserWindow;
export const createWindow = async (): Promise<void> => { export const createWindow = async (): Promise<void> => {
// Create the browser window. // Create the browser window.
@ -27,7 +30,7 @@ export const createWindow = async (): Promise<void> => {
// and load the index.html of the app. // and load the index.html of the app.
mainWindow.loadURL( mainWindow.loadURL(
process.env.NODE_ENV === 'production' || isPackaged? `file://${__dirname}/remix-ide/index.html` : process.env.NODE_ENV === 'production' || isPackaged? `file://${__dirname}/remix-ide/index.html` :
'http://localhost:8080') 'http://localhost:8080?opendir=' + homeDir)
mainWindow.maximize(); mainWindow.maximize();

@ -0,0 +1,58 @@
import { ElectronBasePlugin, ElectronBasePluginClient } from "@remixproject/plugin-electron"
import { Profile } from "@remixproject/plugin-utils";
const profile: Profile = {
displayName: 'electronconfig',
name: 'electronconfig',
description: 'Electron Config'
}
export class ConfigPlugin extends ElectronBasePlugin {
clients: ConfigPluginClient[] = []
constructor() {
super(profile, clientProfile, ConfigPluginClient)
this.methods = [...super.methods, 'writeConfig', 'readConfig']
}
async writeConfig(webContentsId: any, data: any): Promise<void> {
const client = this.clients.find(c => c.webContentsId === webContentsId)
if (client) {
client.writeConfig(data)
}
}
async readConfig(webContentsId: any): Promise<any> {
const client = this.clients.find(c => c.webContentsId === webContentsId)
if (client) {
return client.readConfig()
}
}
}
const clientProfile: Profile = {
name: 'electronconfig',
displayName: 'electronconfig',
description: 'Electron Config',
methods: ['writeConfig', 'readConfig']
}
class ConfigPluginClient extends ElectronBasePluginClient {
constructor(webContentsId: number, profile: Profile) {
super(webContentsId, profile)
this.onload(() => {
//console.log('config client onload')
})
}
async writeConfig(data: any): Promise<void> {
}
async readConfig(): Promise<any> {
}
}

@ -26,7 +26,7 @@ export class FSPlugin extends ElectronBasePlugin {
openFolder(webContentsId: any): void { openFolder(webContentsId: any): void {
const client = this.clients.find(c => c.webContentsId === webContentsId) const client = this.clients.find(c => c.webContentsId === webContentsId)
if (client) { if (client) {
client.setWorkingDir() client.openFolder()
} }
} }
@ -36,7 +36,7 @@ const clientProfile: Profile = {
name: 'fs', name: 'fs',
displayName: 'fs', displayName: 'fs',
description: 'fs', description: 'fs',
methods: ['readdir', 'readFile', 'writeFile', 'mkdir', 'rmdir', 'unlink', 'rename', 'stat', 'lstat', 'exists', 'currentPath', 'watch', 'closeWatch', 'setWorkingDir'] methods: ['readdir', 'readFile', 'writeFile', 'mkdir', 'rmdir', 'unlink', 'rename', 'stat', 'lstat', 'exists', 'currentPath', 'watch', 'closeWatch', 'setWorkingDir', 'openFolder']
} }
class FSPluginClient extends ElectronBasePluginClient { class FSPluginClient extends ElectronBasePluginClient {
@ -145,9 +145,9 @@ class FSPluginClient extends ElectronBasePluginClient {
if (this.watcher) this.watcher.close() if (this.watcher) this.watcher.close()
} }
async setWorkingDir(): Promise<void> { async openFolder(): Promise<void> {
const dirs = dialog.showOpenDialogSync(this.window, { const dirs = dialog.showOpenDialogSync(this.window, {
properties: ['openDirectory'] properties: ['openDirectory', 'createDirectory', "showHiddenFiles"]
}) })
if (dirs && dirs.length > 0) { if (dirs && dirs.length > 0) {
this.workingDir = dirs[0] this.workingDir = dirs[0]
@ -156,6 +156,12 @@ class FSPluginClient extends ElectronBasePluginClient {
} }
async setWorkingDir(path: string): Promise<void> {
console.log('setWorkingDir', path)
this.workingDir = path
this.emit('workingDirChanged', path)
}
fixPath(path: string): string { fixPath(path: string): string {
if (path) { if (path) {
if (path.startsWith('/')) { if (path.startsWith('/')) {

@ -0,0 +1,37 @@
import fs from 'fs'
import os from 'os'
import path from 'path'
const cacheDir = path.join(os.homedir(), '.cache_remix_ide')
try {
if (!fs.existsSync(cacheDir)) {
fs.mkdirSync(cacheDir)
}
if(!fs.existsSync(cacheDir + '/remixdesktop.json')) {
fs.writeFileSync(cacheDir + '/remixdesktop.json', JSON.stringify({}))
}
} catch (e) {
}
export const writeConfig = (data: any) => {
const cache = readConfig()
try {
fs.writeFileSync(cacheDir + '/remixdesktop.json', JSON.stringify({ ...cache, ...data }))
} catch (e) {
console.error('Can\'t write config file', e)
}
}
export const readConfig = () => {
if (fs.existsSync(cacheDir + '/remixdesktop.json')) {
try {
// read the cache file
const cache = fs.readFileSync(cacheDir + '/remixdesktop.json')
const data = JSON.parse(cache.toString())
return data
} catch (e) {
console.error('Can\'t read config file', e)
}
}
return undefined
}

@ -23,6 +23,7 @@ export type UrlParametersType = {
code: string, code: string,
url: string, url: string,
address: string address: string
opendir: string,
} }
const basicWorkspaceInit = async (workspaces: { name: string; isGitRepo: boolean; }[], workspaceProvider) => { const basicWorkspaceInit = async (workspaces: { name: string; isGitRepo: boolean; }[], workspaceProvider) => {
@ -120,7 +121,10 @@ export const initWorkspace = (filePanelPlugin) => async (reducerDispatch: React.
} else if (isElectron()) { } else if (isElectron()) {
console.log('isElectron initWorkspace') console.log('isElectron initWorkspace')
plugin.call('notification', 'toast', `connecting to electron...`) plugin.call('notification', 'toast', `connecting to electron...`)
if(params.opendir){
plugin.call('notification', 'toast', `opening ${params.opendir}...`)
plugin.call('fs', 'setWorkingDir', params.opendir)
}
plugin.setWorkspace({ name: 'electron', isLocalhost: false }) plugin.setWorkspace({ name: 'electron', isLocalhost: false })
dispatch(setCurrentWorkspace({ name: 'electron', isGitRepo: false })) dispatch(setCurrentWorkspace({ name: 'electron', isGitRepo: false }))

@ -735,6 +735,10 @@ export const checkoutRemoteBranch = async (branch: string, remote: string) => {
} }
} }
export const openElectronFolder = async () => {
await plugin.call('fs', 'openFolder')
}
export const hasLocalChanges = async () => { export const hasLocalChanges = async () => {
const filesStatus = await plugin.call('dGitProvider', 'status') const filesStatus = await plugin.call('dGitProvider', 'status')
const uncommittedFiles = getUncommittedFiles(filesStatus) const uncommittedFiles = getUncommittedFiles(filesStatus)

@ -45,6 +45,7 @@ export const FileSystemContext = createContext<{
dispatchCreateSolidityGithubAction: () => Promise<void>, dispatchCreateSolidityGithubAction: () => Promise<void>,
dispatchCreateTsSolGithubAction: () => Promise<void>, dispatchCreateTsSolGithubAction: () => Promise<void>,
dispatchCreateSlitherGithubAction: () => Promise<void> dispatchCreateSlitherGithubAction: () => Promise<void>
dispatchOpenElectronFolder: () => Promise<void>
}>(null) }>(null)

@ -8,7 +8,7 @@ import { browserReducer, browserInitialState } from '../reducers/workspace'
import { initWorkspace, fetchDirectory, removeInputField, deleteWorkspace, deleteAllWorkspaces, clearPopUp, publishToGist, createNewFile, setFocusElement, createNewFolder, import { initWorkspace, fetchDirectory, removeInputField, deleteWorkspace, deleteAllWorkspaces, clearPopUp, publishToGist, createNewFile, setFocusElement, createNewFolder,
deletePath, renamePath, downloadPath, copyFile, copyFolder, runScript, emitContextMenuEvent, handleClickFile, handleExpandPath, addInputField, createWorkspace, deletePath, renamePath, downloadPath, copyFile, copyFolder, runScript, emitContextMenuEvent, handleClickFile, handleExpandPath, addInputField, createWorkspace,
fetchWorkspaceDirectory, renameWorkspace, switchToWorkspace, uploadFile, uploadFolder, handleDownloadWorkspace, handleDownloadFiles, restoreBackupZip, cloneRepository, moveFile, moveFolder, fetchWorkspaceDirectory, renameWorkspace, switchToWorkspace, uploadFile, uploadFolder, handleDownloadWorkspace, handleDownloadFiles, restoreBackupZip, cloneRepository, moveFile, moveFolder,
showAllBranches, switchBranch, createNewBranch, checkoutRemoteBranch, createSolidityGithubAction, createTsSolGithubAction, createSlitherGithubAction showAllBranches, switchBranch, createNewBranch, checkoutRemoteBranch, createSolidityGithubAction, createTsSolGithubAction, createSlitherGithubAction, openElectronFolder
} from '../actions' } from '../actions'
import { Modal, WorkspaceProps, WorkspaceTemplate } from '../types' import { Modal, WorkspaceProps, WorkspaceTemplate } from '../types'
// eslint-disable-next-line @typescript-eslint/no-unused-vars // eslint-disable-next-line @typescript-eslint/no-unused-vars
@ -183,6 +183,12 @@ export const FileSystemProvider = (props: WorkspaceProps) => {
await createSlitherGithubAction() await createSlitherGithubAction()
} }
const dispatchOpenElectronFolder = async () => {
console.log('open electron folder')
await openElectronFolder()
}
useEffect(() => { useEffect(() => {
dispatchInitWorkspace() dispatchInitWorkspace()
}, []) }, [])
@ -299,7 +305,8 @@ export const FileSystemProvider = (props: WorkspaceProps) => {
dispatchCheckoutRemoteBranch, dispatchCheckoutRemoteBranch,
dispatchCreateSolidityGithubAction, dispatchCreateSolidityGithubAction,
dispatchCreateTsSolGithubAction, dispatchCreateTsSolGithubAction,
dispatchCreateSlitherGithubAction dispatchCreateSlitherGithubAction,
dispatchOpenElectronFolder
} }
return ( return (
<FileSystemContext.Provider value={value}> <FileSystemContext.Provider value={value}>

@ -18,7 +18,7 @@ const _paq = window._paq = window._paq || []
const canUpload = window.File || window.FileReader || window.FileList || window.Blob const canUpload = window.File || window.FileReader || window.FileList || window.Blob
export function Workspace () { export function Workspace() {
const LOCALHOST = ' - connect to localhost - ' const LOCALHOST = ' - connect to localhost - '
const NO_WORKSPACE = ' - none - ' const NO_WORKSPACE = ' - none - '
const ELECTRON = 'electron' const ELECTRON = 'electron'
@ -109,8 +109,7 @@ export function Workspace () {
setCurrentWorkspace(global.fs.browser.currentWorkspace) setCurrentWorkspace(global.fs.browser.currentWorkspace)
global.dispatchFetchWorkspaceDirectory(ROOT_PATH) global.dispatchFetchWorkspaceDirectory(ROOT_PATH)
} }
else else {
{
setCurrentWorkspace(NO_WORKSPACE) setCurrentWorkspace(NO_WORKSPACE)
} }
@ -137,14 +136,14 @@ export function Workspace () {
}, [currentWorkspace]) }, [currentWorkspace])
const renameCurrentWorkspace = () => { const renameCurrentWorkspace = () => {
global.modal(intl.formatMessage({ id: 'filePanel.workspace.rename' }), renameModalMessage(), intl.formatMessage({ id: 'filePanel.ok' }), onFinishRenameWorkspace, intl.formatMessage({ id: 'filePanel.cancel' })) global.modal(intl.formatMessage({ id: 'filePanel.workspace.rename' }), renameModalMessage(), intl.formatMessage({ id: 'filePanel.ok' }), onFinishRenameWorkspace, intl.formatMessage({ id: 'filePanel.cancel' }))
} }
const downloadCurrentWorkspace = () => { const downloadCurrentWorkspace = () => {
global.modal(intl.formatMessage({ id: 'filePanel.workspace.download' }), intl.formatMessage({ id: 'filePanel.workspace.downloadConfirm' }), intl.formatMessage({ id: 'filePanel.ok' }), onFinishDownloadWorkspace, intl.formatMessage({ id: 'filePanel.cancel' })) global.modal(intl.formatMessage({ id: 'filePanel.workspace.download' }), intl.formatMessage({ id: 'filePanel.workspace.downloadConfirm' }), intl.formatMessage({ id: 'filePanel.ok' }), onFinishDownloadWorkspace, intl.formatMessage({ id: 'filePanel.cancel' }))
} }
const createWorkspace = () => { const createWorkspace = () => {
global.modal(intl.formatMessage({ id: 'filePanel.workspace.create' }), createModalMessage(), intl.formatMessage({ id: 'filePanel.ok' }), onFinishCreateWorkspace, intl.formatMessage({ id: 'filePanel.cancel' })) global.modal(intl.formatMessage({ id: 'filePanel.workspace.create' }), createModalMessage(), intl.formatMessage({ id: 'filePanel.ok' }), onFinishCreateWorkspace, intl.formatMessage({ id: 'filePanel.cancel' }))
} }
const deleteCurrentWorkspace = () => { const deleteCurrentWorkspace = () => {
@ -235,7 +234,7 @@ export function Workspace () {
try { try {
await global.dispatchRenameWorkspace(currentWorkspace, workspaceName) await global.dispatchRenameWorkspace(currentWorkspace, workspaceName)
} catch (e) { } catch (e) {
global.modal(intl.formatMessage({ id: 'filePanel.workspace.rename' }), e.message, intl.formatMessage({ id: 'filePanel.ok' }), () => {}, intl.formatMessage({ id: 'filePanel.cancel' })) global.modal(intl.formatMessage({ id: 'filePanel.workspace.rename' }), e.message, intl.formatMessage({ id: 'filePanel.ok' }), () => { }, intl.formatMessage({ id: 'filePanel.cancel' }))
console.error(e) console.error(e)
} }
} }
@ -244,7 +243,7 @@ export function Workspace () {
try { try {
await global.dispatchHandleDownloadWorkspace() await global.dispatchHandleDownloadWorkspace()
} catch (e) { } catch (e) {
global.modal(intl.formatMessage({ id: 'filePanel.workspace.download' }), e.message, intl.formatMessage({ id: 'filePanel.ok' }), () => {}, intl.formatMessage({ id: 'filePanel.cancel' })) global.modal(intl.formatMessage({ id: 'filePanel.workspace.download' }), e.message, intl.formatMessage({ id: 'filePanel.ok' }), () => { }, intl.formatMessage({ id: 'filePanel.cancel' }))
console.error(e) console.error(e)
} }
} }
@ -264,13 +263,13 @@ export function Workspace () {
// @ts-ignore: Object is possibly 'null'. // @ts-ignore: Object is possibly 'null'.
pausable: pausableCheckboxRef.current.checked, pausable: pausableCheckboxRef.current.checked,
// @ts-ignore: Object is possibly 'null'. // @ts-ignore: Object is possibly 'null'.
upgradeable: transparentRadioRef.current.checked ? transparentRadioRef.current.value : ( uupsRadioRef.current.checked ? uupsRadioRef.current.value : false ) upgradeable: transparentRadioRef.current.checked ? transparentRadioRef.current.value : (uupsRadioRef.current.checked ? uupsRadioRef.current.value : false)
} }
try { try {
await global.dispatchCreateWorkspace(workspaceName, workspaceTemplateName, opts, initGitRepo) await global.dispatchCreateWorkspace(workspaceName, workspaceTemplateName, opts, initGitRepo)
} catch (e) { } catch (e) {
global.modal(intl.formatMessage({ id: 'filePanel.workspace.create' }), e.message, intl.formatMessage({ id: 'filePanel.ok' }), () => {}, intl.formatMessage({ id: 'filePanel.cancel' })) global.modal(intl.formatMessage({ id: 'filePanel.workspace.create' }), e.message, intl.formatMessage({ id: 'filePanel.ok' }), () => { }, intl.formatMessage({ id: 'filePanel.cancel' }))
console.error(e) console.error(e)
} }
} }
@ -279,7 +278,7 @@ export function Workspace () {
try { try {
await global.dispatchDeleteWorkspace(global.fs.browser.currentWorkspace) await global.dispatchDeleteWorkspace(global.fs.browser.currentWorkspace)
} catch (e) { } catch (e) {
global.modal(intl.formatMessage({ id: 'filePanel.workspace.delete' }), e.message, intl.formatMessage({ id: 'filePanel.ok' }), () => {}, intl.formatMessage({ id: 'filePanel.cancel' })) global.modal(intl.formatMessage({ id: 'filePanel.workspace.delete' }), e.message, intl.formatMessage({ id: 'filePanel.ok' }), () => { }, intl.formatMessage({ id: 'filePanel.cancel' }))
console.error(e) console.error(e)
} }
} }
@ -288,7 +287,7 @@ export function Workspace () {
try { try {
await global.dispatchDeleteAllWorkspaces() await global.dispatchDeleteAllWorkspaces()
} catch (e) { } catch (e) {
global.modal(intl.formatMessage({ id: 'filePanel.workspace.deleteAll' }), e.message, intl.formatMessage({ id: 'filePanel.ok' }), () => {}, intl.formatMessage({ id: 'filePanel.cancel' })) global.modal(intl.formatMessage({ id: 'filePanel.workspace.deleteAll' }), e.message, intl.formatMessage({ id: 'filePanel.ok' }), () => { }, intl.formatMessage({ id: 'filePanel.cancel' }))
console.error(e) console.error(e)
} }
} }
@ -302,7 +301,7 @@ export function Workspace () {
await global.dispatchSwitchToWorkspace(name) await global.dispatchSwitchToWorkspace(name)
global.dispatchHandleExpandPath([]) global.dispatchHandleExpandPath([])
} catch (e) { } catch (e) {
global.modal(intl.formatMessage({ id: 'filePanel.workspace.switch' }), e.message, intl.formatMessage({ id: 'filePanel.ok' }), () => {}, intl.formatMessage({ id: 'filePanel.cancel' })) global.modal(intl.formatMessage({ id: 'filePanel.workspace.switch' }), e.message, intl.formatMessage({ id: 'filePanel.ok' }), () => { }, intl.formatMessage({ id: 'filePanel.cancel' }))
console.error(e) console.error(e)
} }
} }
@ -340,7 +339,7 @@ export function Workspace () {
intl.formatMessage({ id: 'filePanel.workspace.clone' }), intl.formatMessage({ id: 'filePanel.workspace.clone' }),
intl.formatMessage({ id: 'filePanel.workspace.cloneMessage' }), intl.formatMessage({ id: 'filePanel.workspace.cloneMessage' }),
intl.formatMessage({ id: 'filePanel.ok' }), intl.formatMessage({ id: 'filePanel.ok' }),
() => {}, () => { },
intl.formatMessage({ id: 'filePanel.cancel' }) intl.formatMessage({ id: 'filePanel.cancel' })
) )
} }
@ -366,7 +365,7 @@ export function Workspace () {
try { try {
global.dispatchDownloadPath(path) global.dispatchDownloadPath(path)
} catch (error) { } catch (error) {
global.modal('Download Failed', 'Unexpected error while downloading: ' + typeof error === 'string' ? error : error.message, 'Close', async () => {}) global.modal('Download Failed', 'Unexpected error while downloading: ' + typeof error === 'string' ? error : error.message, 'Close', async () => { })
} }
} }
@ -374,7 +373,7 @@ export function Workspace () {
try { try {
global.dispatchCopyFile(src, dest) global.dispatchCopyFile(src, dest)
} catch (error) { } catch (error) {
global.modal('Copy File Failed', 'Unexpected error while copying file: ' + src, 'Close', async () => {}) global.modal('Copy File Failed', 'Unexpected error while copying file: ' + src, 'Close', async () => { })
} }
} }
@ -382,7 +381,7 @@ export function Workspace () {
try { try {
global.dispatchCopyFolder(src, dest) global.dispatchCopyFolder(src, dest)
} catch (error) { } catch (error) {
global.modal('Copy Folder Failed', 'Unexpected error while copying folder: ' + src, 'Close', async () => {}) global.modal('Copy Folder Failed', 'Unexpected error while copying folder: ' + src, 'Close', async () => { })
} }
} }
@ -454,15 +453,15 @@ export function Workspace () {
const pushChangesToGist = (path?: string, type?: string) => { const pushChangesToGist = (path?: string, type?: string) => {
global.modal('Create a public gist', 'Are you sure you want to push changes to remote gist file on github.com?', 'OK', () => toGist(path, type), 'Cancel', () => {}) global.modal('Create a public gist', 'Are you sure you want to push changes to remote gist file on github.com?', 'OK', () => toGist(path, type), 'Cancel', () => { })
} }
const publishFolderToGist = (path?: string, type?: string) => { const publishFolderToGist = (path?: string, type?: string) => {
global.modal('Create a public gist', `Are you sure you want to anonymously publish all your files in the ${path} folder as a public gist on github.com?`, 'OK', () => toGist(path, type), 'Cancel', () => {}) global.modal('Create a public gist', `Are you sure you want to anonymously publish all your files in the ${path} folder as a public gist on github.com?`, 'OK', () => toGist(path, type), 'Cancel', () => { })
} }
const publishFileToGist = (path?: string, type?: string) => { const publishFileToGist = (path?: string, type?: string) => {
global.modal('Create a public gist', `Are you sure you want to anonymously publish ${path} file as a public gist on github.com?`, 'OK', () => toGist(path, type), 'Cancel', () => {}) global.modal('Create a public gist', `Are you sure you want to anonymously publish ${path} file as a public gist on github.com?`, 'OK', () => toGist(path, type), 'Cancel', () => { })
} }
const deleteMessage = (path: string[]) => { const deleteMessage = (path: string[]) => {
@ -480,13 +479,17 @@ export function Workspace () {
if (global.fs.readonly) return global.toast('cannot delete file. ' + name + ' is a read only explorer') if (global.fs.readonly) return global.toast('cannot delete file. ' + name + ' is a read only explorer')
if (!Array.isArray(path)) path = [path] if (!Array.isArray(path)) path = [path]
global.modal(`Delete ${path.length > 1 ? 'items' : 'item'}`, deleteMessage(path), 'OK', () => { global.dispatchDeletePath(path) }, 'Cancel', () => {}) global.modal(`Delete ${path.length > 1 ? 'items' : 'item'}`, deleteMessage(path), 'OK', () => { global.dispatchDeletePath(path) }, 'Cancel', () => { })
} }
const toGist = (path?: string, type?: string) => { const toGist = (path?: string, type?: string) => {
global.dispatchPublishToGist(path, type) global.dispatchPublishToGist(path, type)
} }
const openFolderElectron = async () => {
global.dispatchOpenElectronFolder()
}
const editModeOn = (path: string, type: string, isNew = false) => { const editModeOn = (path: string, type: string, isNew = false) => {
if (global.fs.readonly) return global.toast('Cannot write/modify file system in read only mode.') if (global.fs.readonly) return global.toast('Cannot write/modify file system in read only mode.')
@ -543,7 +546,7 @@ export function Workspace () {
} }
} catch (e) { } catch (e) {
console.error(e) console.error(e)
global.modal(intl.formatMessage({ id: 'filePanel.checkoutGitBranch' }), e.message, intl.formatMessage({ id: 'filePanel.ok' }), () => {}, intl.formatMessage({ id: 'filePanel.cancel' })) global.modal(intl.formatMessage({ id: 'filePanel.checkoutGitBranch' }), e.message, intl.formatMessage({ id: 'filePanel.ok' }), () => { }, intl.formatMessage({ id: 'filePanel.cancel' }))
} }
} }
@ -552,66 +555,66 @@ export function Workspace () {
await global.dispatchCreateNewBranch(branchFilter) await global.dispatchCreateNewBranch(branchFilter)
_paq.push(['trackEvent', 'Workspace', 'GIT', 'switch_to_new_branch']) _paq.push(['trackEvent', 'Workspace', 'GIT', 'switch_to_new_branch'])
} catch (e) { } catch (e) {
global.modal(intl.formatMessage({ id: 'filePanel.checkoutGitBranch' }), e.message, intl.formatMessage({ id: 'filePanel.ok' }), () => {}, intl.formatMessage({ id: 'filePanel.cancel' })) global.modal(intl.formatMessage({ id: 'filePanel.checkoutGitBranch' }), e.message, intl.formatMessage({ id: 'filePanel.ok' }), () => { }, intl.formatMessage({ id: 'filePanel.cancel' }))
} }
} }
const createModalMessage = () => { const createModalMessage = () => {
return ( return (
<> <>
<label id="selectWsTemplate" className="form-check-label" style={{fontWeight: "bolder"}}><FormattedMessage id='filePanel.workspace.chooseTemplate' /></label> <label id="selectWsTemplate" className="form-check-label" style={{ fontWeight: "bolder" }}><FormattedMessage id='filePanel.workspace.chooseTemplate' /></label>
<select name="wstemplate" className="mb-3 form-control custom-select" id="wstemplate" defaultValue='remixDefault' ref={workspaceCreateTemplateInput} onChange={updateWsName}> <select name="wstemplate" className="mb-3 form-control custom-select" id="wstemplate" defaultValue='remixDefault' ref={workspaceCreateTemplateInput} onChange={updateWsName}>
<optgroup style={{fontSize: "medium"}} label="General"> <optgroup style={{ fontSize: "medium" }} label="General">
<option style={{fontSize: "small"}} value='remixDefault'>Basic</option> <option style={{ fontSize: "small" }} value='remixDefault'>Basic</option>
<option style={{fontSize: "small"}} value='blank'>Blank</option> <option style={{ fontSize: "small" }} value='blank'>Blank</option>
</optgroup> </optgroup>
<optgroup style={{fontSize: "medium"}} label="OpenZeppelin"> <optgroup style={{ fontSize: "medium" }} label="OpenZeppelin">
<option style={{fontSize: "small"}} value='ozerc20'>ERC20</option> <option style={{ fontSize: "small" }} value='ozerc20'>ERC20</option>
<option style={{fontSize: "small"}} value='ozerc721'>ERC721</option> <option style={{ fontSize: "small" }} value='ozerc721'>ERC721</option>
<option style={{fontSize: "small"}} value='ozerc1155'>ERC1155</option> <option style={{ fontSize: "small" }} value='ozerc1155'>ERC1155</option>
</optgroup> </optgroup>
<optgroup style={{fontSize: "medium"}} label="0xProject"> <optgroup style={{ fontSize: "medium" }} label="0xProject">
<option style={{fontSize: "small"}} value='zeroxErc20'>ERC20</option> <option style={{ fontSize: "small" }} value='zeroxErc20'>ERC20</option>
</optgroup> </optgroup>
<optgroup style={{fontSize: "medium"}} label="GnosisSafe"> <optgroup style={{ fontSize: "medium" }} label="GnosisSafe">
<option style={{fontSize: "small"}} value='gnosisSafeMultisig'>MultiSig Wallet</option> <option style={{ fontSize: "small" }} value='gnosisSafeMultisig'>MultiSig Wallet</option>
</optgroup> </optgroup>
</select> </select>
<div id="ozcustomization" data-id="ozCustomization" ref={displayOzCustomRef} style={{display: 'none'}} className="mb-2"> <div id="ozcustomization" data-id="ozCustomization" ref={displayOzCustomRef} style={{ display: 'none' }} className="mb-2">
<label className="form-check-label d-block mb-2" style={{fontWeight: "bolder"}}><FormattedMessage id='filePanel.customizeTemplate' /></label> <label className="form-check-label d-block mb-2" style={{ fontWeight: "bolder" }}><FormattedMessage id='filePanel.customizeTemplate' /></label>
<label id="wsName" className="form-check-label d-block mb-1"><FormattedMessage id='filePanel.features' /></label> <label id="wsName" className="form-check-label d-block mb-1"><FormattedMessage id='filePanel.features' /></label>
<div className="mb-2"> <div className="mb-2">
<div className="d-flex ml-2 custom-control custom-checkbox"> <div className="d-flex ml-2 custom-control custom-checkbox">
<input className="custom-control-input" type="checkbox" name="feature" value="mintable" id="mintable" ref={mintableCheckboxRef} /> <input className="custom-control-input" type="checkbox" name="feature" value="mintable" id="mintable" ref={mintableCheckboxRef} />
<label className="form-check-label custom-control-label" htmlFor="mintable" data-id="featureTypeMintable" >Mintable</label> <label className="form-check-label custom-control-label" htmlFor="mintable" data-id="featureTypeMintable" >Mintable</label>
</div> </div>
<div className="d-flex ml-2 custom-control custom-checkbox"> <div className="d-flex ml-2 custom-control custom-checkbox">
<input className="custom-control-input" type="checkbox" name="feature" value="burnable" id="burnable" ref={burnableCheckboxRef} /> <input className="custom-control-input" type="checkbox" name="feature" value="burnable" id="burnable" ref={burnableCheckboxRef} />
<label className="form-check-label custom-control-label" htmlFor="burnable" data-id="featureTypeBurnable" >Burnable</label> <label className="form-check-label custom-control-label" htmlFor="burnable" data-id="featureTypeBurnable" >Burnable</label>
</div> </div>
<div className="d-flex ml-2 custom-control custom-checkbox"> <div className="d-flex ml-2 custom-control custom-checkbox">
<input className="custom-control-input" type="checkbox" name="feature" value="pausable" id="pausable" ref={pausableCheckboxRef} /> <input className="custom-control-input" type="checkbox" name="feature" value="pausable" id="pausable" ref={pausableCheckboxRef} />
<label className="form-check-label custom-control-label" htmlFor="pausable" data-id="featureTypePausable" >Pausable</label> <label className="form-check-label custom-control-label" htmlFor="pausable" data-id="featureTypePausable" >Pausable</label>
</div> </div>
</div> </div>
<label id="wsName" className="form-check-label d-block mb-1"><FormattedMessage id='filePanel.upgradeability' /></label> <label id="wsName" className="form-check-label d-block mb-1"><FormattedMessage id='filePanel.upgradeability' /></label>
<div> <div>
<div className="d-flex ml-2 custom-control custom-radio"> <div className="d-flex ml-2 custom-control custom-radio">
<input className="custom-control-input" type="radio" name="upgradeability" value="transparent" id="transparent" ref={transparentRadioRef} /> <input className="custom-control-input" type="radio" name="upgradeability" value="transparent" id="transparent" ref={transparentRadioRef} />
<label className="form-check-label custom-control-label" htmlFor="transparent" data-id="upgradeTypeTransparent" >Transparent</label> <label className="form-check-label custom-control-label" htmlFor="transparent" data-id="upgradeTypeTransparent" >Transparent</label>
</div> </div>
<div className="d-flex ml-2 custom-control custom-radio"> <div className="d-flex ml-2 custom-control custom-radio">
<input className="custom-control-input" type="radio" name="upgradeability" value="uups" id="uups" ref={uupsRadioRef} /> <input className="custom-control-input" type="radio" name="upgradeability" value="uups" id="uups" ref={uupsRadioRef} />
<label className="form-check-label custom-control-label" htmlFor="uups" data-id="upgradeTypeUups" >UUPS</label> <label className="form-check-label custom-control-label" htmlFor="uups" data-id="upgradeTypeUups" >UUPS</label>
</div> </div>
</div> </div>
</div> </div>
<label id="wsName" className="form-check-label" style={{fontWeight: "bolder"}} ><FormattedMessage id='filePanel.workspaceName' /></label> <label id="wsName" className="form-check-label" style={{ fontWeight: "bolder" }} ><FormattedMessage id='filePanel.workspaceName' /></label>
<input type="text" data-id="modalDialogCustomPromptTextCreate" defaultValue={global.plugin.getAvailableWorkspaceName(TEMPLATE_NAMES['remixDefault'])} ref={workspaceCreateInput} className="form-control" /> <input type="text" data-id="modalDialogCustomPromptTextCreate" defaultValue={global.plugin.getAvailableWorkspaceName(TEMPLATE_NAMES['remixDefault'])} ref={workspaceCreateInput} className="form-control" />
<div className="d-flex py-2 align-items-center custom-control custom-checkbox"> <div className="d-flex py-2 align-items-center custom-control custom-checkbox">
@ -622,7 +625,7 @@ export function Workspace () {
className="form-check-input custom-control-input" className="form-check-input custom-control-input"
type="checkbox" type="checkbox"
disabled={!global.fs.gitConfig.username || !global.fs.gitConfig.email} disabled={!global.fs.gitConfig.username || !global.fs.gitConfig.email}
onChange={() => {}} onChange={() => { }}
/> />
<label <label
htmlFor="initGitRepository" htmlFor="initGitRepository"
@ -635,8 +638,8 @@ export function Workspace () {
</div> </div>
{!global.fs.gitConfig.username || !global.fs.gitConfig.email ? {!global.fs.gitConfig.username || !global.fs.gitConfig.email ?
( (
<div className='text-warning'><FormattedMessage id='filePanel.initGitRepositoryWarning' /></div>) <div className='text-warning'><FormattedMessage id='filePanel.initGitRepositoryWarning' /></div>)
:<></> : <></>
} }
</> </>
@ -646,7 +649,7 @@ export function Workspace () {
const renameModalMessage = () => { const renameModalMessage = () => {
return ( return (
<> <>
<input type="text" data-id="modalDialogCustomPromptTextRename" defaultValue={ currentWorkspace } ref={workspaceRenameInput} className="form-control" /> <input type="text" data-id="modalDialogCustomPromptTextRename" defaultValue={currentWorkspace} ref={workspaceRenameInput} className="form-control" />
</> </>
) )
} }
@ -671,22 +674,22 @@ export function Workspace () {
return ( return (
<div className='d-flex flex-column justify-content-between h-100'> <div className='d-flex flex-column justify-content-between h-100'>
<div className='remixui_container overflow-auto' style={{ maxHeight: selectedWorkspace && selectedWorkspace.isGitRepo ? '95%' : '100%' }} onContextMenu={(e)=>{ <div className='remixui_container overflow-auto' style={{ maxHeight: selectedWorkspace && selectedWorkspace.isGitRepo ? '95%' : '100%' }} onContextMenu={(e) => {
e.preventDefault() e.preventDefault()
handleContextMenu(e.pageX, e.pageY, ROOT_PATH, "workspace", 'workspace') handleContextMenu(e.pageX, e.pageY, ROOT_PATH, "workspace", 'workspace')
} }
}> }>
<div className='d-flex flex-column w-100 remixui_fileexplorer' data-id="remixUIWorkspaceExplorer" onClick={resetFocus}> <div className='d-flex flex-column w-100 remixui_fileexplorer' data-id="remixUIWorkspaceExplorer" onClick={resetFocus}>
<div> <div>
<header> <header>
<div className="mx-2 mb-2 d-flex flex-column"> <div className="mx-2 mb-2 d-flex flex-column">
<div className="d-flex justify-content-between"> <div className="d-flex justify-content-between">
{!isElectron() ? {!isElectron() ?
<span className="d-flex align-items-end"> <span className="d-flex align-items-end">
<label className="pl-1 form-check-label" htmlFor="workspacesSelect" style={{wordBreak: 'keep-all'}}> <label className="pl-1 form-check-label" htmlFor="workspacesSelect" style={{ wordBreak: 'keep-all' }}>
<FormattedMessage id='filePanel.workspace' /> <FormattedMessage id='filePanel.workspace' />
</label> </label>
</span>: null} </span> : null}
{currentWorkspace !== LOCALHOST && !isElectron() ? (<span className="remixui_menu remixui_topmenu d-flex justify-content-between align-items-end w-75"> {currentWorkspace !== LOCALHOST && !isElectron() ? (<span className="remixui_menu remixui_topmenu d-flex justify-content-between align-items-end w-75">
<CustomTooltip <CustomTooltip
placement="top" placement="top"
@ -705,7 +708,7 @@ export function Workspace () {
}} }}
style={{ fontSize: 'medium' }} style={{ fontSize: 'medium' }}
className='far fa-plus remixui_menuicon d-flex align-self-end' className='far fa-plus remixui_menuicon d-flex align-self-end'
> >
</span> </span>
</CustomTooltip> </CustomTooltip>
<Dropdown id="workspacesMenuDropdown" data-id="workspacesMenuDropdown" onToggle={() => hideIconsMenu(!showIconsMenu)} show={showIconsMenu}> <Dropdown id="workspacesMenuDropdown" data-id="workspacesMenuDropdown" onToggle={() => hideIconsMenu(!showIconsMenu)} show={showIconsMenu}>
@ -731,262 +734,267 @@ export function Workspace () {
addSlitherGithubAction={addSlitherGithubAction} addSlitherGithubAction={addSlitherGithubAction}
addTsSolTestGithubAction={addTsSolTestGithubAction} addTsSolTestGithubAction={addTsSolTestGithubAction}
showIconsMenu={showIconsMenu} showIconsMenu={showIconsMenu}
hideWorkspaceOptions={ currentWorkspace === LOCALHOST } hideWorkspaceOptions={currentWorkspace === LOCALHOST}
hideLocalhostOptions={ currentWorkspace === NO_WORKSPACE } hideLocalhostOptions={currentWorkspace === NO_WORKSPACE}
/> />
</Dropdown.Menu> </Dropdown.Menu>
</Dropdown> </Dropdown>
</span>) : null} </span>) : null}
</div> </div>
{!isElectron() ? ( {!isElectron() ? (
<Dropdown id="workspacesSelect" data-id="workspacesSelect" onToggle={toggleDropdown} show={showDropdown}> <Dropdown id="workspacesSelect" data-id="workspacesSelect" onToggle={toggleDropdown} show={showDropdown}>
<Dropdown.Toggle <Dropdown.Toggle
as={CustomToggle} as={CustomToggle}
id="dropdown-custom-components" id="dropdown-custom-components"
className="btn btn-light btn-block w-100 d-inline-block border border-dark form-control mt-1" className="btn btn-light btn-block w-100 d-inline-block border border-dark form-control mt-1"
icon={selectedWorkspace && selectedWorkspace.isGitRepo && !(currentWorkspace === LOCALHOST) ? 'far fa-code-branch' : null} icon={selectedWorkspace && selectedWorkspace.isGitRepo && !(currentWorkspace === LOCALHOST) ? 'far fa-code-branch' : null}
>
{ selectedWorkspace ? selectedWorkspace.name : currentWorkspace === LOCALHOST ? formatNameForReadonly("localhost") : NO_WORKSPACE }
</Dropdown.Toggle>
<Dropdown.Menu as={CustomMenu} className='w-100 custom-dropdown-items' data-id="custom-dropdown-items">
<Dropdown.Item
onClick={() => {
createWorkspace()
}}
> >
{selectedWorkspace ? selectedWorkspace.name : currentWorkspace === LOCALHOST ? formatNameForReadonly("localhost") : NO_WORKSPACE}
</Dropdown.Toggle>
<Dropdown.Menu as={CustomMenu} className='w-100 custom-dropdown-items' data-id="custom-dropdown-items">
<Dropdown.Item
onClick={() => {
createWorkspace()
}}
>
{
<span className="pl-3"> - create a new workspace - </span>
}
</Dropdown.Item>
<Dropdown.Item onClick={() => { switchWorkspace(LOCALHOST) }}>{currentWorkspace === LOCALHOST ? <span>&#10003; localhost </span> : <span className="pl-3"> {LOCALHOST} </span>}</Dropdown.Item>
<Dropdown.Item onClick={() => { switchWorkspace(ELECTRON) }}>{currentWorkspace === ELECTRON ? <span>&#10003; electron </span> : <span className="pl-3"> {ELECTRON} </span>}</Dropdown.Item>
{ {
<span className="pl-3"> - create a new workspace - </span> global.fs.browser.workspaces.map(({ name, isGitRepo }, index) => (
} <Dropdown.Item
</Dropdown.Item> key={index}
<Dropdown.Item onClick={() => { switchWorkspace(LOCALHOST) }}>{currentWorkspace === LOCALHOST ? <span>&#10003; localhost </span> : <span className="pl-3"> { LOCALHOST } </span>}</Dropdown.Item> onClick={() => {
<Dropdown.Item onClick={() => { switchWorkspace(ELECTRON) }}>{currentWorkspace === ELECTRON ? <span>&#10003; electron </span> : <span className="pl-3"> { ELECTRON } </span>}</Dropdown.Item> switchWorkspace(name)
{ }}
global.fs.browser.workspaces.map(({ name, isGitRepo }, index) => ( data-id={`dropdown-item-${name}`}
<Dropdown.Item >
key={index} {isGitRepo ?
onClick={() => { <div className='d-flex justify-content-between'>
switchWorkspace(name) <span>{currentWorkspace === name ? <span>&#10003; {name} </span> : <span className="pl-3">{name}</span>}</span>
}} <i className='fas fa-code-branch pt-1'></i>
data-id={`dropdown-item-${name}`} </div> :
> <span>{currentWorkspace === name ? <span>&#10003; {name} </span> : <span className="pl-3">{name}</span>}</span>
{ isGitRepo ? }
<div className='d-flex justify-content-between'>
<span>{ currentWorkspace === name ? <span>&#10003; { name } </span> : <span className="pl-3">{ name }</span> }</span>
<i className='fas fa-code-branch pt-1'></i>
</div> :
<span>{ currentWorkspace === name ? <span>&#10003; { name } </span> : <span className="pl-3">{ name }</span> }</span>
}
</Dropdown.Item> </Dropdown.Item>
)) ))
} }
{ ((global.fs.browser.workspaces.length <= 0) || currentWorkspace === NO_WORKSPACE) && <Dropdown.Item onClick={() => { switchWorkspace(NO_WORKSPACE) }}>{ <span className="pl-3">NO_WORKSPACE</span> }</Dropdown.Item> } {((global.fs.browser.workspaces.length <= 0) || currentWorkspace === NO_WORKSPACE) && <Dropdown.Item onClick={() => { switchWorkspace(NO_WORKSPACE) }}>{<span className="pl-3">NO_WORKSPACE</span>}</Dropdown.Item>}
</Dropdown.Menu> </Dropdown.Menu>
</Dropdown> </Dropdown>
) : null} ) : null}
</div> </div>
</header> </header>
</div> </div>
<div className='h-100 remixui_fileExplorerTree' onFocus={() => { toggleDropdown(false) }}> {isElectron() && global.fs.browser.isSuccessfulDirectory ? null :
<div onClick={openFolderElectron} className='btn btn-primary'>Open Folder</div>
}
<div className='h-100 remixui_fileExplorerTree' onFocus={() => { toggleDropdown(false) }}>
<div className='h-100'> <div className='h-100'>
{ (global.fs.browser.isRequestingWorkspace || global.fs.browser.isRequestingCloning) && <div className="text-center py-5"><i className="fas fa-spinner fa-pulse fa-2x"></i></div>} {(global.fs.browser.isRequestingWorkspace || global.fs.browser.isRequestingCloning) && <div className="text-center py-5"><i className="fas fa-spinner fa-pulse fa-2x"></i></div>}
{ !(global.fs.browser.isRequestingWorkspace || global.fs.browser.isRequestingCloning) && {!(global.fs.browser.isRequestingWorkspace || global.fs.browser.isRequestingCloning) &&
(global.fs.mode === 'browser') && (currentWorkspace !== NO_WORKSPACE) && (global.fs.mode === 'browser') && (currentWorkspace !== NO_WORKSPACE) &&
<div className='h-100 remixui_treeview' data-id='filePanelFileExplorerTree'> <div className='h-100 remixui_treeview' data-id='filePanelFileExplorerTree'>
<FileExplorer <FileExplorer
fileState={global.fs.browser.fileState} fileState={global.fs.browser.fileState}
name={currentWorkspace} name={currentWorkspace}
menuItems={['createNewFile', 'createNewFolder', 'publishToGist', canUpload ? 'uploadFile' : '', canUpload ? 'uploadFolder' : '']} menuItems={['createNewFile', 'createNewFolder', 'publishToGist', canUpload ? 'uploadFile' : '', canUpload ? 'uploadFolder' : '']}
contextMenuItems={global.fs.browser.contextMenu.registeredMenuItems} contextMenuItems={global.fs.browser.contextMenu.registeredMenuItems}
removedContextMenuItems={global.fs.browser.contextMenu.removedMenuItems} removedContextMenuItems={global.fs.browser.contextMenu.removedMenuItems}
files={global.fs.browser.files} files={global.fs.browser.files}
workspaceState={state} workspaceState={state}
expandPath={global.fs.browser.expandPath} expandPath={global.fs.browser.expandPath}
focusEdit={global.fs.focusEdit} focusEdit={global.fs.focusEdit}
focusElement={global.fs.focusElement} focusElement={global.fs.focusElement}
hideIconsMenu={hideIconsMenu} hideIconsMenu={hideIconsMenu}
showIconsMenu={showIconsMenu} showIconsMenu={showIconsMenu}
dispatchCreateNewFile={global.dispatchCreateNewFile} dispatchCreateNewFile={global.dispatchCreateNewFile}
modal={global.modal} modal={global.modal}
dispatchCreateNewFolder={global.dispatchCreateNewFolder} dispatchCreateNewFolder={global.dispatchCreateNewFolder}
readonly={global.fs.readonly} readonly={global.fs.readonly}
toast={global.toast} toast={global.toast}
dispatchDeletePath={global.dispatchDeletePath} dispatchDeletePath={global.dispatchDeletePath}
dispatchRenamePath={global.dispatchRenamePath} dispatchRenamePath={global.dispatchRenamePath}
dispatchDownloadPath={global.dispatchDownloadPath} dispatchDownloadPath={global.dispatchDownloadPath}
dispatchUploadFile={global.dispatchUploadFile} dispatchUploadFile={global.dispatchUploadFile}
dispatchUploadFolder={global.dispatchUploadFolder} dispatchUploadFolder={global.dispatchUploadFolder}
dispatchCopyFile={global.dispatchCopyFile} dispatchCopyFile={global.dispatchCopyFile}
dispatchCopyFolder={global.dispatchCopyFolder} dispatchCopyFolder={global.dispatchCopyFolder}
dispatchPublishToGist={global.dispatchPublishToGist} dispatchPublishToGist={global.dispatchPublishToGist}
dispatchRunScript={global.dispatchRunScript} dispatchRunScript={global.dispatchRunScript}
dispatchEmitContextMenuEvent={global.dispatchEmitContextMenuEvent} dispatchEmitContextMenuEvent={global.dispatchEmitContextMenuEvent}
dispatchHandleClickFile={global.dispatchHandleClickFile} dispatchHandleClickFile={global.dispatchHandleClickFile}
dispatchSetFocusElement={global.dispatchSetFocusElement} dispatchSetFocusElement={global.dispatchSetFocusElement}
dispatchFetchDirectory={global.dispatchFetchDirectory} dispatchFetchDirectory={global.dispatchFetchDirectory}
dispatchRemoveInputField={global.dispatchRemoveInputField} dispatchRemoveInputField={global.dispatchRemoveInputField}
dispatchAddInputField={global.dispatchAddInputField} dispatchAddInputField={global.dispatchAddInputField}
dispatchHandleExpandPath={global.dispatchHandleExpandPath} dispatchHandleExpandPath={global.dispatchHandleExpandPath}
dispatchMoveFile={global.dispatchMoveFile} dispatchMoveFile={global.dispatchMoveFile}
dispatchMoveFolder={global.dispatchMoveFolder} dispatchMoveFolder={global.dispatchMoveFolder}
handleCopyClick={handleCopyClick} handleCopyClick={handleCopyClick}
handlePasteClick={handlePasteClick} handlePasteClick={handlePasteClick}
addMenuItems={addMenuItems} addMenuItems={addMenuItems}
removeMenuItems={removeMenuItems} removeMenuItems={removeMenuItems}
handleContextMenu={handleContextMenu} handleContextMenu={handleContextMenu}
uploadFile={uploadFile} uploadFile={uploadFile}
uploadFolder={uploadFolder} uploadFolder={uploadFolder}
getFocusedFolder={getFocusedFolder} getFocusedFolder={getFocusedFolder}
toGist={toGist} toGist={toGist}
editModeOn={editModeOn} editModeOn={editModeOn}
handleNewFileInput={handleNewFileInput} handleNewFileInput={handleNewFileInput}
handleNewFolderInput={handleNewFolderInput} handleNewFolderInput={handleNewFolderInput}
/> />
</div> </div>
} }
{ global.fs.localhost.isRequestingLocalhost && <div className="text-center py-5"><i className="fas fa-spinner fa-pulse fa-2x"></i></div> }
{ (global.fs.mode === 'localhost' && global.fs.localhost.isSuccessfulLocalhost) && {global.fs.localhost.isRequestingLocalhost && <div className="text-center py-5"><i className="fas fa-spinner fa-pulse fa-2x"></i></div>}
<div className='h-100 filesystemexplorer remixui_treeview'> {(global.fs.mode === 'localhost' && global.fs.localhost.isSuccessfulLocalhost) &&
<FileExplorer <div className='h-100 filesystemexplorer remixui_treeview'>
name='localhost' <FileExplorer
menuItems={['createNewFile', 'createNewFolder']} name='localhost'
contextMenuItems={global.fs.localhost.contextMenu.registeredMenuItems} menuItems={['createNewFile', 'createNewFolder']}
removedContextMenuItems={global.fs.localhost.contextMenu.removedMenuItems} contextMenuItems={global.fs.localhost.contextMenu.registeredMenuItems}
files={global.fs.localhost.files} removedContextMenuItems={global.fs.localhost.contextMenu.removedMenuItems}
fileState={[]} files={global.fs.localhost.files}
workspaceState={state} fileState={[]}
expandPath={global.fs.localhost.expandPath} workspaceState={state}
focusEdit={global.fs.focusEdit} expandPath={global.fs.localhost.expandPath}
focusElement={global.fs.focusElement} focusEdit={global.fs.focusEdit}
hideIconsMenu={hideIconsMenu} focusElement={global.fs.focusElement}
showIconsMenu={showIconsMenu} hideIconsMenu={hideIconsMenu}
dispatchCreateNewFile={global.dispatchCreateNewFile} showIconsMenu={showIconsMenu}
modal={global.modal} dispatchCreateNewFile={global.dispatchCreateNewFile}
dispatchCreateNewFolder={global.dispatchCreateNewFolder} modal={global.modal}
readonly={global.fs.readonly} dispatchCreateNewFolder={global.dispatchCreateNewFolder}
toast={global.toast} readonly={global.fs.readonly}
dispatchDeletePath={global.dispatchDeletePath} toast={global.toast}
dispatchRenamePath={global.dispatchRenamePath} dispatchDeletePath={global.dispatchDeletePath}
dispatchDownloadPath={global.dispatchDownloadPath} dispatchRenamePath={global.dispatchRenamePath}
dispatchUploadFile={global.dispatchUploadFile} dispatchDownloadPath={global.dispatchDownloadPath}
dispatchUploadFolder={global.dispatchUploadFolder} dispatchUploadFile={global.dispatchUploadFile}
dispatchCopyFile={global.dispatchCopyFile} dispatchUploadFolder={global.dispatchUploadFolder}
dispatchCopyFolder={global.dispatchCopyFolder} dispatchCopyFile={global.dispatchCopyFile}
dispatchPublishToGist={global.dispatchPublishToGist} dispatchCopyFolder={global.dispatchCopyFolder}
dispatchRunScript={global.dispatchRunScript} dispatchPublishToGist={global.dispatchPublishToGist}
dispatchEmitContextMenuEvent={global.dispatchEmitContextMenuEvent} dispatchRunScript={global.dispatchRunScript}
dispatchHandleClickFile={global.dispatchHandleClickFile} dispatchEmitContextMenuEvent={global.dispatchEmitContextMenuEvent}
dispatchSetFocusElement={global.dispatchSetFocusElement} dispatchHandleClickFile={global.dispatchHandleClickFile}
dispatchFetchDirectory={global.dispatchFetchDirectory} dispatchSetFocusElement={global.dispatchSetFocusElement}
dispatchRemoveInputField={global.dispatchRemoveInputField} dispatchFetchDirectory={global.dispatchFetchDirectory}
dispatchAddInputField={global.dispatchAddInputField} dispatchRemoveInputField={global.dispatchRemoveInputField}
dispatchHandleExpandPath={global.dispatchHandleExpandPath} dispatchAddInputField={global.dispatchAddInputField}
dispatchMoveFile={global.dispatchMoveFile} dispatchHandleExpandPath={global.dispatchHandleExpandPath}
dispatchMoveFolder={global.dispatchMoveFolder} dispatchMoveFile={global.dispatchMoveFile}
handleCopyClick={handleCopyClick} dispatchMoveFolder={global.dispatchMoveFolder}
handlePasteClick={handlePasteClick} handleCopyClick={handleCopyClick}
addMenuItems={addMenuItems} handlePasteClick={handlePasteClick}
removeMenuItems={removeMenuItems} addMenuItems={addMenuItems}
handleContextMenu={handleContextMenu} removeMenuItems={removeMenuItems}
uploadFile={uploadFile} handleContextMenu={handleContextMenu}
uploadFolder={uploadFolder} uploadFile={uploadFile}
getFocusedFolder={getFocusedFolder} uploadFolder={uploadFolder}
toGist={toGist} getFocusedFolder={getFocusedFolder}
editModeOn={editModeOn} toGist={toGist}
handleNewFileInput={handleNewFileInput} editModeOn={editModeOn}
handleNewFolderInput={handleNewFolderInput} handleNewFileInput={handleNewFileInput}
/> handleNewFolderInput={handleNewFolderInput}
</div> />
} </div>
}
</div> </div>
</div> </div>
</div> </div>
</div>
{ </div>
selectedWorkspace && {
<div className={`bg-light border-top ${selectedWorkspace.isGitRepo && currentBranch ? 'd-block' : 'd-none'}`} data-id="workspaceGitPanel"> selectedWorkspace &&
<div className='d-flex justify-space-between p-1'> <div className={`bg-light border-top ${selectedWorkspace.isGitRepo && currentBranch ? 'd-block' : 'd-none'}`} data-id="workspaceGitPanel">
<div className="mr-auto text-uppercase text-dark pt-2 pl-2">GIT</div> <div className='d-flex justify-space-between p-1'>
<div className="pt-1 mr-1" data-id="workspaceGitBranchesDropdown"> <div className="mr-auto text-uppercase text-dark pt-2 pl-2">GIT</div>
<Dropdown style={{ height: 30, minWidth: 80 }} onToggle={toggleBranches} show={showBranches} drop={'up'}> <div className="pt-1 mr-1" data-id="workspaceGitBranchesDropdown">
<Dropdown.Toggle as={CustomToggle} id="dropdown-custom-components" className="btn btn-light btn-block w-100 d-inline-block border border-dark form-control h-100 p-0 pl-2 pr-2 text-dark" icon={null}> <Dropdown style={{ height: 30, minWidth: 80 }} onToggle={toggleBranches} show={showBranches} drop={'up'}>
{ global.fs.browser.isRequestingCloning ? <i className="fad fa-spinner fa-spin"></i> : currentBranch || '-none-' } <Dropdown.Toggle as={CustomToggle} id="dropdown-custom-components" className="btn btn-light btn-block w-100 d-inline-block border border-dark form-control h-100 p-0 pl-2 pr-2 text-dark" icon={null}>
</Dropdown.Toggle> {global.fs.browser.isRequestingCloning ? <i className="fad fa-spinner fa-spin"></i> : currentBranch || '-none-'}
</Dropdown.Toggle>
<Dropdown.Menu as={CustomMenu} className='custom-dropdown-items branches-dropdown'>
<div data-id="custom-dropdown-menu"> <Dropdown.Menu as={CustomMenu} className='custom-dropdown-items branches-dropdown'>
<div className='d-flex text-dark' style={{ fontSize: 14, fontWeight: 'bold' }}> <div data-id="custom-dropdown-menu">
<span className='mt-2 ml-2 mr-auto'><FormattedMessage id='filePanel.switchBranches' /></span> <div className='d-flex text-dark' style={{ fontSize: 14, fontWeight: 'bold' }}>
<div className='pt-2 pr-2' onClick={() => { toggleBranches(false) }}><i className='fa fa-close'></i> <span className='mt-2 ml-2 mr-auto'><FormattedMessage id='filePanel.switchBranches' /></span>
</div> <div className='pt-2 pr-2' onClick={() => { toggleBranches(false) }}><i className='fa fa-close'></i>
</div>
<div className='border-top py-2'>
<input
className='form-control border checkout-input bg-light'
placeholder={intl.formatMessage({ id: 'filePanel.findOrCreateABranch' })}
style={{ minWidth: 225 }}
onChange={handleBranchFilterChange}
data-id='workspaceGitInput'
/>
</div> </div>
<div className='border-top' style={{ maxHeight: 120, overflowY: 'scroll' }} data-id="custom-dropdown-items"> </div>
{ <div className='border-top py-2'>
filteredBranches.length > 0 ? filteredBranches.map((branch, index) => { <input
return ( className='form-control border checkout-input bg-light'
<Dropdown.Item key={index} onClick={() => { switchToBranch(branch) }} title={branch.remote ? 'Checkout new branch from remote branch' : 'Checkout to local branch'}> placeholder={intl.formatMessage({ id: 'filePanel.findOrCreateABranch' })}
<div data-id={`workspaceGit-${ branch.remote ? `${branch.remote}/${branch.name}` : branch.name }`}> style={{ minWidth: 225 }}
{ onChange={handleBranchFilterChange}
(currentBranch === branch.name) && !branch.remote ? data-id='workspaceGitInput'
<span>&#10003; <i className='far fa-code-branch'></i><span className='pl-1'>{ branch.name }</span></span> : />
<span className='pl-3'><i className={`far ${ branch.remote ? 'fa-cloud' : 'fa-code-branch'}`}></i><span className='pl-1'>{ branch.remote ? `${branch.remote}/${branch.name}` : branch.name }</span></span> </div>
} <div className='border-top' style={{ maxHeight: 120, overflowY: 'scroll' }} data-id="custom-dropdown-items">
</div> {
</Dropdown.Item> filteredBranches.length > 0 ? filteredBranches.map((branch, index) => {
) return (
}) : <Dropdown.Item key={index} onClick={() => { switchToBranch(branch) }} title={branch.remote ? 'Checkout new branch from remote branch' : 'Checkout to local branch'}>
<div data-id={`workspaceGit-${branch.remote ? `${branch.remote}/${branch.name}` : branch.name}`}>
{
(currentBranch === branch.name) && !branch.remote ?
<span>&#10003; <i className='far fa-code-branch'></i><span className='pl-1'>{branch.name}</span></span> :
<span className='pl-3'><i className={`far ${branch.remote ? 'fa-cloud' : 'fa-code-branch'}`}></i><span className='pl-1'>{branch.remote ? `${branch.remote}/${branch.name}` : branch.name}</span></span>
}
</div>
</Dropdown.Item>
)
}) :
<Dropdown.Item onClick={switchToNewBranch}> <Dropdown.Item onClick={switchToNewBranch}>
<div className="pl-1 pr-1" data-id="workspaceGitCreateNewBranch"> <div className="pl-1 pr-1" data-id="workspaceGitCreateNewBranch">
<i className="fas fa-code-branch pr-2"></i><span><FormattedMessage id='filePanel.createBranch' />: { branchFilter } from '{currentBranch}'</span> <i className="fas fa-code-branch pr-2"></i><span><FormattedMessage id='filePanel.createBranch' />: {branchFilter} from '{currentBranch}'</span>
</div> </div>
</Dropdown.Item> </Dropdown.Item>
}
</div>
{
(selectedWorkspace.branches || []).length > 4 && <div className='text-center border-top pt-2'><label style={{ fontSize: 12, cursor: 'pointer' }} onClick={showAllBranches}><FormattedMessage id='filePanel.viewAllBranches' /></label></div>
} }
</div> </div>
</Dropdown.Menu> {
</Dropdown> (selectedWorkspace.branches || []).length > 4 && <div className='text-center border-top pt-2'><label style={{ fontSize: 12, cursor: 'pointer' }} onClick={showAllBranches}><FormattedMessage id='filePanel.viewAllBranches' /></label></div>
</div> }
</div>
</Dropdown.Menu>
</Dropdown>
</div> </div>
</div> </div>
} </div>
{state.showContextMenu && <FileExplorerContextMenu }
actions={global.fs.focusElement.length > 1 ? state.actions.filter(item => item.multiselect) : state.actions.filter(item => !item.multiselect)} {state.showContextMenu && <FileExplorerContextMenu
hideContextMenu={hideContextMenu} actions={global.fs.focusElement.length > 1 ? state.actions.filter(item => item.multiselect) : state.actions.filter(item => !item.multiselect)}
createNewFile={handleNewFileInput} hideContextMenu={hideContextMenu}
createNewFolder={handleNewFolderInput} createNewFile={handleNewFileInput}
deletePath={deletePath} createNewFolder={handleNewFolderInput}
renamePath={editModeOn} deletePath={deletePath}
runScript={runScript} renamePath={editModeOn}
copy={handleCopyClick} runScript={runScript}
paste={handlePasteClick} copy={handleCopyClick}
copyFileName={handleCopyFileNameClick} paste={handlePasteClick}
copyPath={handleCopyFilePathClick} copyFileName={handleCopyFileNameClick}
emit={emitContextMenuEvent} copyPath={handleCopyFilePathClick}
pageX={state.focusContext.x} emit={emitContextMenuEvent}
pageY={state.focusContext.y} pageX={state.focusContext.x}
path={state.focusContext.element} pageY={state.focusContext.y}
type={state.focusContext.type} path={state.focusContext.element}
focus={global.fs.focusElement} type={state.focusContext.type}
pushChangesToGist={pushChangesToGist} focus={global.fs.focusElement}
publishFolderToGist={publishFolderToGist} pushChangesToGist={pushChangesToGist}
publishFileToGist={publishFileToGist} publishFolderToGist={publishFolderToGist}
uploadFile={uploadFile} publishFileToGist={publishFileToGist}
downloadPath={downloadPath} uploadFile={uploadFile}
downloadPath={downloadPath}
/>
} />
}
</div> </div>
) )
} }

Loading…
Cancel
Save