From b888c2b894e42015213c15d0a21a83a2d5361d8a Mon Sep 17 00:00:00 2001 From: bunsenstraat Date: Tue, 13 Jun 2023 17:16:36 +0200 Subject: [PATCH] open folder --- apps/remixdesktop/src/main.ts | 5 +- apps/remixdesktop/src/plugins/configPlugin.ts | 58 ++ apps/remixdesktop/src/plugins/fsPlugin.ts | 14 +- apps/remixdesktop/src/utils/config.ts | 37 ++ .../workspace/src/lib/actions/index.ts | 6 +- .../workspace/src/lib/actions/workspace.ts | 4 + .../workspace/src/lib/contexts/index.ts | 1 + .../src/lib/providers/FileSystemProvider.tsx | 11 +- .../workspace/src/lib/remix-ui-workspace.tsx | 590 +++++++++--------- 9 files changed, 427 insertions(+), 299 deletions(-) create mode 100644 apps/remixdesktop/src/plugins/configPlugin.ts create mode 100644 apps/remixdesktop/src/utils/config.ts diff --git a/apps/remixdesktop/src/main.ts b/apps/remixdesktop/src/main.ts index 421de7eb7d..f174c50a44 100644 --- a/apps/remixdesktop/src/main.ts +++ b/apps/remixdesktop/src/main.ts @@ -13,6 +13,9 @@ if ( isPackaged = true; } +// get system home dir +const homeDir = app.getPath('userData') + export let mainWindow: BrowserWindow; export const createWindow = async (): Promise => { // Create the browser window. @@ -27,7 +30,7 @@ export const createWindow = async (): Promise => { // and load the index.html of the app. mainWindow.loadURL( process.env.NODE_ENV === 'production' || isPackaged? `file://${__dirname}/remix-ide/index.html` : - 'http://localhost:8080') + 'http://localhost:8080?opendir=' + homeDir) mainWindow.maximize(); diff --git a/apps/remixdesktop/src/plugins/configPlugin.ts b/apps/remixdesktop/src/plugins/configPlugin.ts new file mode 100644 index 0000000000..cc144f0230 --- /dev/null +++ b/apps/remixdesktop/src/plugins/configPlugin.ts @@ -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 { + const client = this.clients.find(c => c.webContentsId === webContentsId) + if (client) { + client.writeConfig(data) + } + } + + async readConfig(webContentsId: any): Promise { + 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 { + + } + + async readConfig(): Promise { + + } + +} \ No newline at end of file diff --git a/apps/remixdesktop/src/plugins/fsPlugin.ts b/apps/remixdesktop/src/plugins/fsPlugin.ts index 1ecbfbd32e..63b5153f5e 100644 --- a/apps/remixdesktop/src/plugins/fsPlugin.ts +++ b/apps/remixdesktop/src/plugins/fsPlugin.ts @@ -26,7 +26,7 @@ export class FSPlugin extends ElectronBasePlugin { openFolder(webContentsId: any): void { const client = this.clients.find(c => c.webContentsId === webContentsId) if (client) { - client.setWorkingDir() + client.openFolder() } } @@ -36,7 +36,7 @@ const clientProfile: Profile = { name: 'fs', displayName: '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 { @@ -145,9 +145,9 @@ class FSPluginClient extends ElectronBasePluginClient { if (this.watcher) this.watcher.close() } - async setWorkingDir(): Promise { + async openFolder(): Promise { const dirs = dialog.showOpenDialogSync(this.window, { - properties: ['openDirectory'] + properties: ['openDirectory', 'createDirectory', "showHiddenFiles"] }) if (dirs && dirs.length > 0) { this.workingDir = dirs[0] @@ -156,6 +156,12 @@ class FSPluginClient extends ElectronBasePluginClient { } + async setWorkingDir(path: string): Promise { + console.log('setWorkingDir', path) + this.workingDir = path + this.emit('workingDirChanged', path) + } + fixPath(path: string): string { if (path) { if (path.startsWith('/')) { diff --git a/apps/remixdesktop/src/utils/config.ts b/apps/remixdesktop/src/utils/config.ts new file mode 100644 index 0000000000..62e35d45df --- /dev/null +++ b/apps/remixdesktop/src/utils/config.ts @@ -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 +} \ No newline at end of file diff --git a/libs/remix-ui/workspace/src/lib/actions/index.ts b/libs/remix-ui/workspace/src/lib/actions/index.ts index 70af2f08db..a48524a10c 100644 --- a/libs/remix-ui/workspace/src/lib/actions/index.ts +++ b/libs/remix-ui/workspace/src/lib/actions/index.ts @@ -23,6 +23,7 @@ export type UrlParametersType = { code: string, url: string, address: string + opendir: string, } const basicWorkspaceInit = async (workspaces: { name: string; isGitRepo: boolean; }[], workspaceProvider) => { @@ -120,7 +121,10 @@ export const initWorkspace = (filePanelPlugin) => async (reducerDispatch: React. } else if (isElectron()) { console.log('isElectron initWorkspace') 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 }) dispatch(setCurrentWorkspace({ name: 'electron', isGitRepo: false })) diff --git a/libs/remix-ui/workspace/src/lib/actions/workspace.ts b/libs/remix-ui/workspace/src/lib/actions/workspace.ts index 439a127053..aa180f2e6c 100644 --- a/libs/remix-ui/workspace/src/lib/actions/workspace.ts +++ b/libs/remix-ui/workspace/src/lib/actions/workspace.ts @@ -747,6 +747,10 @@ export const checkoutRemoteBranch = async (branch: string, remote: string) => { } } +export const openElectronFolder = async () => { + await plugin.call('fs', 'openFolder') +} + export const hasLocalChanges = async () => { const filesStatus = await plugin.call('dGitProvider', 'status') const uncommittedFiles = getUncommittedFiles(filesStatus) diff --git a/libs/remix-ui/workspace/src/lib/contexts/index.ts b/libs/remix-ui/workspace/src/lib/contexts/index.ts index 3423323a90..b46b2c7d04 100644 --- a/libs/remix-ui/workspace/src/lib/contexts/index.ts +++ b/libs/remix-ui/workspace/src/lib/contexts/index.ts @@ -46,6 +46,7 @@ export const FileSystemContext = createContext<{ dispatchCreateTsSolGithubAction: () => Promise, dispatchCreateSlitherGithubAction: () => Promise dispatchCreateHelperScripts: (script: string) => Promise + dispatchOpenElectronFolder: () => Promise }>(null) \ No newline at end of file diff --git a/libs/remix-ui/workspace/src/lib/providers/FileSystemProvider.tsx b/libs/remix-ui/workspace/src/lib/providers/FileSystemProvider.tsx index 29399275e1..7c9cc07c4e 100644 --- a/libs/remix-ui/workspace/src/lib/providers/FileSystemProvider.tsx +++ b/libs/remix-ui/workspace/src/lib/providers/FileSystemProvider.tsx @@ -8,7 +8,7 @@ import { browserReducer, browserInitialState } from '../reducers/workspace' import { initWorkspace, fetchDirectory, removeInputField, deleteWorkspace, deleteAllWorkspaces, clearPopUp, publishToGist, createNewFile, setFocusElement, createNewFolder, deletePath, renamePath, downloadPath, copyFile, copyFolder, runScript, emitContextMenuEvent, handleClickFile, handleExpandPath, addInputField, createWorkspace, fetchWorkspaceDirectory, renameWorkspace, switchToWorkspace, uploadFile, uploadFolder, handleDownloadWorkspace, handleDownloadFiles, restoreBackupZip, cloneRepository, moveFile, moveFolder, - showAllBranches, switchBranch, createNewBranch, checkoutRemoteBranch, createSolidityGithubAction, createTsSolGithubAction, createSlitherGithubAction, createHelperScripts + showAllBranches, switchBranch, createNewBranch, checkoutRemoteBranch, createSolidityGithubAction, createTsSolGithubAction, createSlitherGithubAction, createHelperScripts, openElectronFolder } from '../actions' import { Modal, WorkspaceProps, WorkspaceTemplate } from '../types' // eslint-disable-next-line @typescript-eslint/no-unused-vars @@ -187,6 +187,12 @@ export const FileSystemProvider = (props: WorkspaceProps) => { await createHelperScripts(script) } + const dispatchOpenElectronFolder = async () => { + console.log('open electron folder') + await openElectronFolder() + } + + useEffect(() => { dispatchInitWorkspace() }, []) @@ -304,7 +310,8 @@ export const FileSystemProvider = (props: WorkspaceProps) => { dispatchCreateSolidityGithubAction, dispatchCreateTsSolGithubAction, dispatchCreateSlitherGithubAction, - dispatchCreateHelperScripts + dispatchCreateHelperScripts, + dispatchOpenElectronFolder } return ( diff --git a/libs/remix-ui/workspace/src/lib/remix-ui-workspace.tsx b/libs/remix-ui/workspace/src/lib/remix-ui-workspace.tsx index b7b88e2318..d11525c404 100644 --- a/libs/remix-ui/workspace/src/lib/remix-ui-workspace.tsx +++ b/libs/remix-ui/workspace/src/lib/remix-ui-workspace.tsx @@ -18,7 +18,7 @@ const _paq = window._paq = window._paq || [] const canUpload = window.File || window.FileReader || window.FileList || window.Blob -export function Workspace () { +export function Workspace() { const LOCALHOST = ' - connect to localhost - ' const NO_WORKSPACE = ' - none - ' const ELECTRON = 'electron' @@ -111,11 +111,10 @@ export function Workspace () { setCurrentWorkspace(global.fs.browser.currentWorkspace) global.dispatchFetchWorkspaceDirectory(ROOT_PATH) } - else - { + else { setCurrentWorkspace(NO_WORKSPACE) } - + } else if (global.fs.mode === 'localhost') { global.dispatchFetchWorkspaceDirectory(ROOT_PATH) setCurrentWorkspace(LOCALHOST) @@ -139,14 +138,14 @@ export function Workspace () { }, [currentWorkspace]) 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 = () => { - 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 = () => { - 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 = () => { @@ -241,7 +240,7 @@ export function Workspace () { try { await global.dispatchRenameWorkspace(currentWorkspace, workspaceName) } 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) } } @@ -250,7 +249,7 @@ export function Workspace () { try { await global.dispatchHandleDownloadWorkspace() } 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) } } @@ -270,13 +269,13 @@ export function Workspace () { // @ts-ignore: Object is possibly 'null'. pausable: pausableCheckboxRef.current.checked, // @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 { await global.dispatchCreateWorkspace(workspaceName, workspaceTemplateName, opts, initGitRepo) } 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) } } @@ -285,7 +284,7 @@ export function Workspace () { try { await global.dispatchDeleteWorkspace(global.fs.browser.currentWorkspace) } 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) } } @@ -294,7 +293,7 @@ export function Workspace () { try { await global.dispatchDeleteAllWorkspaces() } 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) } } @@ -308,7 +307,7 @@ export function Workspace () { await global.dispatchSwitchToWorkspace(name) global.dispatchHandleExpandPath([]) } 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) } } @@ -346,7 +345,7 @@ export function Workspace () { intl.formatMessage({ id: 'filePanel.workspace.clone' }), intl.formatMessage({ id: 'filePanel.workspace.cloneMessage' }), intl.formatMessage({ id: 'filePanel.ok' }), - () => {}, + () => { }, intl.formatMessage({ id: 'filePanel.cancel' }) ) } @@ -372,7 +371,7 @@ export function Workspace () { try { global.dispatchDownloadPath(path) } 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 () => { }) } } @@ -380,7 +379,7 @@ export function Workspace () { try { global.dispatchCopyFile(src, dest) } 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 () => { }) } } @@ -388,7 +387,7 @@ export function Workspace () { try { global.dispatchCopyFolder(src, dest) } 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 () => { }) } } @@ -460,15 +459,15 @@ export function Workspace () { 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) => { - 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) => { - 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[]) => { @@ -486,13 +485,17 @@ export function Workspace () { if (global.fs.readonly) return global.toast('cannot delete file. ' + name + ' is a read only explorer') 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) => { global.dispatchPublishToGist(path, type) } + const openFolderElectron = async () => { + global.dispatchOpenElectronFolder() + } + const editModeOn = (path: string, type: string, isNew = false) => { if (global.fs.readonly) return global.toast('Cannot write/modify file system in read only mode.') @@ -549,7 +552,7 @@ export function Workspace () { } } catch (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' })) } } @@ -558,66 +561,66 @@ export function Workspace () { await global.dispatchCreateNewBranch(branchFilter) _paq.push(['trackEvent', 'Workspace', 'GIT', 'switch_to_new_branch']) } 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 = () => { return ( <> - + -
- +
+
- - + +
- - + +
- - + +
- - + +
- - + +
- +
@@ -628,7 +631,7 @@ export function Workspace () { className="form-check-input custom-control-input" type="checkbox" disabled={!global.fs.gitConfig.username || !global.fs.gitConfig.email} - onChange={() => {}} + onChange={() => { }} />