From 8adb7b28ef89196cd3240fa902e40ca5b1b5bd34 Mon Sep 17 00:00:00 2001 From: Prince Anuragi Date: Mon, 6 Nov 2023 22:22:33 +0530 Subject: [PATCH 1/3] fix: refactor the compilation component --- .../features/Compilation/CompilationCard.tsx | 141 +++++++ plugin/src/features/Compilation/index.tsx | 357 +----------------- plugin/src/hooks/useRemixClient.ts | 294 +++++++++++---- plugin/src/utils/initial_scarb_codes.ts | 2 +- 4 files changed, 378 insertions(+), 416 deletions(-) create mode 100644 plugin/src/features/Compilation/CompilationCard.tsx diff --git a/plugin/src/features/Compilation/CompilationCard.tsx b/plugin/src/features/Compilation/CompilationCard.tsx new file mode 100644 index 00000000..63790b11 --- /dev/null +++ b/plugin/src/features/Compilation/CompilationCard.tsx @@ -0,0 +1,141 @@ +import React from 'react' +import { useAtomValue, useSetAtom } from 'jotai' +import { BsChevronDown } from 'react-icons/bs' +import { compilationAtom, activeTomlPathAtom, statusAtom } from '../../atoms/compilation' +import Container from '../../components/ui_components/Container' +import useRemixClient from '../../hooks/useRemixClient' +import { isEmpty } from '../../utils/misc' + +import * as D from '../../components/ui_components/Dropdown' + +const CompilationCard: React.FC<{ + validation: boolean + isLoading: boolean + onClick: () => unknown + compileScarb: (workspacePath: string, scarbPath: string) => Promise + currentWorkspacePath: string +}> = ( + { + validation, + isLoading, + onClick, + compileScarb, + currentWorkspacePath + } +): React.ReactElement => { + const { remixClient } = useRemixClient() + + const { + activeTomlPath, + tomlPaths, + isCompiling, + currentFilename + } = useAtomValue(compilationAtom) + + const setActiveTomlPath = useSetAtom(activeTomlPathAtom) + + const isCurrentFileName = isEmpty(currentFilename) + + return ( + + {activeTomlPath !== undefined && tomlPaths?.length > 0 && ( +
+ + + + +
+ + +
+
+ + + {tomlPaths.map((tomlPath, i) => { + return ( + { + setActiveTomlPath(tomlPath) + }} + > + {tomlPath} + + ) + })} + + +
+
Or compile a single file:
+
+ )} + +
+ ) +} + +export default CompilationCard diff --git a/plugin/src/features/Compilation/index.tsx b/plugin/src/features/Compilation/index.tsx index b32df3da..8fcbc145 100644 --- a/plugin/src/features/Compilation/index.tsx +++ b/plugin/src/features/Compilation/index.tsx @@ -3,17 +3,13 @@ import { apiUrl } from '../../utils/network' import { artifactFilename, artifactFolder, - getFileExtension, - getFileNameFromPath + getFileExtension } from '../../utils/utils' import './styles.css' import { hash } from 'starknet' -import Container from '../../components/ui_components/Container' import storage from '../../utils/storage' import { ethers } from 'ethers' import { type AccordianTabs } from '../Plugin' -import * as D from '../../components/ui_components/Dropdown' -import { BsChevronDown } from 'react-icons/bs' import { type Contract } from '../../utils/types/contracts' import { asyncFetch } from '../../utils/async_fetch' import { useAtom, useAtomValue, useSetAtom } from 'jotai' @@ -21,9 +17,10 @@ import { useAtom, useAtomValue, useSetAtom } from 'jotai' // Imported Atoms import cairoVersionAtom from '../../atoms/cairoVersion' import { compiledContractsAtom, selectedCompiledContract } from '../../atoms/compiledContracts' -import { activeTomlPathAtom, compilationAtom, currentFilenameAtom, hashDirAtom, isCompilingAtom, isValidCairoAtom, noFileSelectedAtom, statusAtom, tomlPathsAtom } from '../../atoms/compilation' +import { activeTomlPathAtom, compilationAtom, hashDirAtom, isCompilingAtom, statusAtom } from '../../atoms/compilation' import useRemixClient from '../../hooks/useRemixClient' import { isEmpty } from '../../utils/misc' +import CompilationCard from './CompilationCard' interface FileContentMap { file_name: string @@ -36,134 +33,11 @@ interface ScarbCompileResponse { file_content_map_array: FileContentMap[] } -const CompilationCard: React.FC<{ - validation: boolean - isLoading: boolean - onClick: () => unknown - compileScarb: (workspacePath: string, scarbPath: string) => Promise - currentWorkspacePath: string -}> = ( - { - validation, - isLoading, - onClick, - compileScarb, - currentWorkspacePath - } -): React.ReactElement => { - const { remixClient } = useRemixClient() - - const { - activeTomlPath, - tomlPaths, - isCompiling, - currentFilename - } = useAtomValue(compilationAtom) - - const setActiveTomlPath = useSetAtom(activeTomlPathAtom) - - const isCurrentFileName = isEmpty(currentFilename) - - return ( - - {activeTomlPath !== undefined && tomlPaths?.length > 0 && ( -
- - - - -
- - -
-
- - - {tomlPaths.map((tomlPath, i) => { - return ( - { - setActiveTomlPath(tomlPath) - }} - > - {tomlPath} - - ) - })} - - -
-
Or compile a single file:
-
- )} - -
- ) +interface CompileResponse { + status: string + message: string + file_content: string + cairo_version: string } interface CompilationProps { @@ -171,7 +45,7 @@ interface CompilationProps { } const Compilation: React.FC = ({ setAccordian }) => { - const { remixClient } = useRemixClient() + const { remixClient, currentFilePath, currWorkspacePath } = useRemixClient() const cairoVersion = useAtomValue(cairoVersionAtom) const [contracts, setContracts] = useAtom(compiledContractsAtom) @@ -189,15 +63,9 @@ const Compilation: React.FC = ({ setAccordian }) => { const setStatus = useSetAtom(statusAtom) const setHashDir = useSetAtom(hashDirAtom) - const setNoFileSelected = useSetAtom(noFileSelectedAtom) - const setIsValidCairo = useSetAtom(isValidCairoAtom) const setIsCompiling = useSetAtom(isCompilingAtom) - const setCurrentFilename = useSetAtom(currentFilenameAtom) - const setTomlPaths = useSetAtom(tomlPathsAtom) const setActiveTomlPath = useSetAtom(activeTomlPathAtom) - const [currWorkspacePath, setCurrWorkspacePath] = React.useState('') - useEffect(() => { // read hashDir from localStorage const hashDir = storage.get('hashDir') @@ -213,12 +81,6 @@ const Compilation: React.FC = ({ setAccordian }) => { } }, [hashDir]) - useEffect(() => { - remixClient.on('fileManager', 'noFileSelected', () => { - setNoFileSelected(true) - }) - }, [remixClient]) - useEffect(() => { // eslint-disable-next-line @typescript-eslint/no-misused-promises setTimeout(async () => { @@ -227,67 +89,6 @@ const Compilation: React.FC = ({ setAccordian }) => { throw new Error('No file selected') } - // get current file - const currentFile = await remixClient.call( - 'fileManager', - 'getCurrentFile' - ) - if (currentFile.length > 0) { - const filename = getFileNameFromPath(currentFile) - const currentFileExtension = getFileExtension(filename) - setIsValidCairo(currentFileExtension === 'cairo') - setCurrentFilename(filename) - - remixClient.emit('statusChanged', { - key: 'succeed', - type: 'info', - title: 'Current file: ' + currentFilename - }) - } - } catch (e) { - remixClient.emit('statusChanged', { - key: 'failed', - type: 'info', - title: 'Please open a cairo file to compile' - }) - console.log('error: ', e) - } - }, 500) - }, [remixClient, currentFilename, noFileSelected]) - - useEffect(() => { - // eslint-disable-next-line @typescript-eslint/no-misused-promises - setTimeout(async () => { - remixClient.on( - 'fileManager', - 'currentFileChanged', - (currentFileChanged: any) => { - const filename = getFileNameFromPath(currentFileChanged) - const currentFileExtension = getFileExtension(filename) - setIsValidCairo(currentFileExtension === 'cairo') - setCurrentFilename(filename) - remixClient.emit('statusChanged', { - key: 'succeed', - type: 'info', - title: 'Current file: ' + currentFilename - }) - setNoFileSelected(false) - } - ) - }, 500) - }, [remixClient, currentFilename]) - - useEffect(() => { - // eslint-disable-next-line @typescript-eslint/no-misused-promises - setTimeout(async () => { - try { - if (noFileSelected) { - throw new Error('No file selected') - } - const currentFilePath = await remixClient.call( - 'fileManager', - 'getCurrentFile' - ) if (!currentFilePath.endsWith('.cairo')) { throw new Error('Not a valid cairo file') } @@ -315,144 +116,10 @@ const Compilation: React.FC = ({ setAccordian }) => { }, 100) }, [currentFilename, remixClient]) - async function getTomlPaths ( - workspacePath: string, - currPath: string - ): Promise { - const resTomlPaths: string[] = [] - - try { - const allFiles = await remixClient.fileManager.readdir( - workspacePath + '/' + currPath - ) - // get keys of allFiles object - const allFilesKeys: string[] = Object.keys(allFiles) - // const get all values of allFiles object - const allFilesValues = Object.values(allFiles) - - for (let i = 0; i < allFilesKeys.length; i++) { - if (allFilesKeys[i].endsWith('Scarb.toml')) { - resTomlPaths.push(currPath) - } - - if (Object.values(allFilesValues[i])[0] as unknown as boolean) { - const recTomlPaths = await getTomlPaths( - workspacePath, - allFilesKeys[i] - ) - resTomlPaths.push(...recTomlPaths) - } - } - } catch (e) { - console.log('error: ', e) - } - return resTomlPaths - } - - useEffect(() => { - // eslint-disable-next-line @typescript-eslint/no-misused-promises - setTimeout(async () => { - // get current workspace path - try { - const currWorkspace = await remixClient.filePanel.getCurrentWorkspace() - setCurrWorkspacePath(currWorkspace.absolutePath) - } catch (e) { - console.log('error: ', e) - } - }) - }) - - useEffect(() => { - // eslint-disable-next-line @typescript-eslint/no-misused-promises - setTimeout(async () => { - // get current workspace path - try { - if (currWorkspacePath === '') return - const allTomlPaths = await getTomlPaths(currWorkspacePath, '') - - setTomlPaths(allTomlPaths) - if (activeTomlPath === '' || activeTomlPath === undefined) { setActiveTomlPath(tomlPaths[0]) } - } catch (e) { - console.log('error: ', e) - } - }, 100) - }, [currWorkspacePath]) - useEffect(() => { if (activeTomlPath === '' || activeTomlPath === undefined) { setActiveTomlPath(tomlPaths[0]) } }, [tomlPaths]) - useEffect(() => { - // eslint-disable-next-line @typescript-eslint/no-misused-promises - setTimeout(async () => { - remixClient.on('fileManager', 'fileAdded', (_: any) => { - // eslint-disable-next-line @typescript-eslint/no-misused-promises - setTimeout(async () => { - // get current workspace path - try { - const allTomlPaths = await getTomlPaths(currWorkspacePath, '') - - setTomlPaths(allTomlPaths) - } catch (e) { - console.log('error: ', e) - } - }, 100) - }) - remixClient.on('fileManager', 'folderAdded', (_: any) => { - // eslint-disable-next-line @typescript-eslint/no-misused-promises - setTimeout(async () => { - // get current workspace path - try { - const allTomlPaths = await getTomlPaths(currWorkspacePath, '') - - setTomlPaths(allTomlPaths) - } catch (e) { - console.log('error: ', e) - } - }, 100) - }) - remixClient.on('fileManager', 'fileRemoved', (_: any) => { - // eslint-disable-next-line @typescript-eslint/no-misused-promises - setTimeout(async () => { - // get current workspace path - try { - const allTomlPaths = await getTomlPaths(currWorkspacePath, '') - - setTomlPaths(allTomlPaths) - } catch (e) { - console.log('error: ', e) - } - }, 100) - }) - remixClient.on('filePanel', 'workspaceCreated', (_: any) => { - // eslint-disable-next-line @typescript-eslint/no-misused-promises - setTimeout(async () => { - // get current workspace path - try { - const allTomlPaths = await getTomlPaths(currWorkspacePath, '') - - setTomlPaths(allTomlPaths) - } catch (e) { - console.log('error: ', e) - } - }, 100) - }) - remixClient.on('filePanel', 'workspaceRenamed', (_: any) => { - // eslint-disable-next-line @typescript-eslint/no-misused-promises - setTimeout(async () => { - // get current workspace path - try { - const allTomlPaths = await getTomlPaths(currWorkspacePath, '') - - setTomlPaths(allTomlPaths) - } catch (e) { - console.log('error: ', e) - } - }, 100) - }) - }, 500) - }, [remixClient]) - const compilations = [ { validation: isValidCairo, @@ -576,11 +243,11 @@ const Compilation: React.FC = ({ setAccordian }) => { ) // get Json body from response - const casm = JSON.parse(compileToCasmResponse) + const casm: CompileResponse = JSON.parse(compileToCasmResponse) if (casm.status !== 'Success') { - await remixClient.terminal.log(casm.message) + await remixClient.terminal.log(casm.message as unknown as any) - const lastLine = casm.message.trim().split('\n').pop().trim() + const lastLine = casm.message.trim().split('\n').pop()?.trim() remixClient.emit('statusChanged', { key: 'failed', diff --git a/plugin/src/hooks/useRemixClient.ts b/plugin/src/hooks/useRemixClient.ts index f9260c9d..86440e92 100644 --- a/plugin/src/hooks/useRemixClient.ts +++ b/plugin/src/hooks/useRemixClient.ts @@ -1,91 +1,245 @@ import { PluginClient } from '@remixproject/plugin' import { createClient } from '@remixproject/plugin-webview' -import { useEffect } from 'react' +import { useEffect, useState } from 'react' import { fetchGitHubFilesRecursively } from '../utils/initial_scarb_codes' import { pluginLoaded as atomPluginLoaded } from '../atoms/remixClient' -import { useAtom } from 'jotai' +import { type SetStateAction, useAtom, useSetAtom } from 'jotai' +import { getFileNameFromPath, getFileExtension } from '../utils/utils' +import { currentFilenameAtom, isValidCairoAtom, noFileSelectedAtom, tomlPathsAtom } from '../atoms/compilation' const remixClient = createClient(new PluginClient()) +const createExampleWorkspace = async (client: typeof remixClient): Promise => { + await client.filePanel.createWorkspace( + 'cairo_scarb_sample', + true + ) + try { + await client.fileManager.mkdir('hello_world') + } catch (e) { + console.log(e) + } + const exampleRepo = await fetchGitHubFilesRecursively( + 'software-mansion/scarb', + 'examples/starknet_multiple_contracts' + ) + + try { + for (const file of exampleRepo) { + const filePath = file?.path + .replace('examples/starknet_multiple_contracts/', '') + .replace('examples/starknet_multiple_contracts', '') ?? '' + + let fileContent: string = file?.content ?? '' + + if (file != null && file.fileName === 'Scarb.toml') { + fileContent = fileContent.concat('\ncasm = true') + await client.fileManager.writeFile( + `hello_world/${filePath}/${file.fileName}`, + fileContent + ) + } + } + } catch (e) { + if (e instanceof Error) { + await client.call('notification' as any, 'alert', { + id: 'starknetRemixPluginAlert', + title: 'Please check the write file permission', + message: e.message + '\n' + 'Did you provide the write file permission?' + }) + } + console.log(e) + } +} + +const checkWorkspaceAndPopulateExample = async (client: typeof remixClient): Promise => { + const workspaces = await client.filePanel.getWorkspaces() + + const workspaceLets: Array<{ name: string, isGitRepo: boolean }> = + JSON.parse(JSON.stringify(workspaces)) + + if ( + !workspaceLets.some( + (workspaceLet) => workspaceLet.name === 'cairo_scarb_sample' + ) + ) { + createExampleWorkspace(client).catch(e => { console.error(e) }) + } +} + +const getTomlPaths = async ( + workspacePath: string, + currPath: string, + client: typeof remixClient +): Promise => { + const resTomlPaths: string[] = [] + + try { + const allFiles = await client.fileManager.readdir( + workspacePath + '/' + currPath + ) + // get keys of allFiles object + const allFilesKeys: string[] = Object.keys(allFiles) + // const get all values of allFiles object + const allFilesValues = Object.values(allFiles) + + for (let i = 0; i < allFilesKeys.length; i++) { + if (allFilesKeys[i].endsWith('Scarb.toml')) { + resTomlPaths.push(currPath) + } + + if (Object.values(allFilesValues[i])[0] as unknown as boolean) { + const recTomlPaths = await getTomlPaths( + workspacePath, + allFilesKeys[i], + client + ) + resTomlPaths.push(...recTomlPaths) + } + } + } catch (e) { + console.log('error: ', e) + } + return resTomlPaths +} + +const getAndSetTomlPaths = async ( + client: typeof remixClient, + currentWorkspacePath: string, + setTomlPaths: (arg: SetStateAction) => void): Promise => { + try { + const allTomlPaths = await getTomlPaths(currentWorkspacePath, '', client) + setTomlPaths(allTomlPaths) + } catch (e) { + console.log('error: ', e) + } +} + const useRemixClient = (): { remixClient: typeof remixClient isPluginLoaded: boolean + currentFilePath: string + currWorkspacePath: string } => { const [pluginLoaded, setPluginLoaded] = useAtom(atomPluginLoaded) + // Atoms + const [noFileSelected, setNoFileSelected] = useAtom(noFileSelectedAtom) + const [currentFileName, setCurrentFileName] = useAtom(currentFilenameAtom) + const setIsValidCairo = useSetAtom(isValidCairoAtom) + const setTomlPaths = useSetAtom(tomlPathsAtom) + const [currWorkspacePath, setCurrWorkspacePath] = useState('') + const [currentFilePath, setCurrentFilePath] = useState('') + + useEffect(() => { + remixClient.onload(() => { + console.log('Remix Plugin Loaded') + setPluginLoaded(true) + checkWorkspaceAndPopulateExample(remixClient).catch(e => { console.error(e) }) + remixClient.filePanel.getCurrentWorkspace().then(currWorkspace => { + setCurrWorkspacePath(currWorkspace.absolutePath) + }).catch(e => { + console.error(e) + }) + }).catch(e => { + console.error(e) + }) + }, []) + useEffect(() => { - // eslint-disable-next-line @typescript-eslint/no-misused-promises - const id = setTimeout(async (): Promise => { - await remixClient.onload(() => { - setPluginLoaded(true) - // eslint-disable-next-line @typescript-eslint/no-misused-promises - setTimeout(async () => { - const workspaces = await remixClient.filePanel.getWorkspaces() - - const workspaceLets: Array<{ name: string, isGitRepo: boolean }> = - JSON.parse(JSON.stringify(workspaces)) - - if ( - !workspaceLets.some( - (workspaceLet) => workspaceLet.name === 'cairo_scarb_sample' - ) - ) { - await remixClient.filePanel.createWorkspace( - 'cairo_scarb_sample', - true - ) - try { - await remixClient.fileManager.mkdir('hello_world') - } catch (e) { - console.log(e) - } - const exampleRepo = await fetchGitHubFilesRecursively( - 'software-mansion/scarb', - 'examples/starknet_multiple_contracts' - ) - - try { - for (const file of exampleRepo) { - const filePath = file?.path - .replace('examples/starknet_multiple_contracts/', '') - .replace('examples/starknet_multiple_contracts', '') ?? '' - - let fileContent: string = file?.content ?? '' - - if (file != null && file.fileName === 'Scarb.toml') { - fileContent = fileContent.concat('\ncasm = true') - } - - // eslint-disable-next-line @typescript-eslint/restrict-template-expressions - await remixClient.fileManager.writeFile( - `hello_world/${ - // eslint-disable-next-line @typescript-eslint/restrict-template-expressions - filePath - // eslint-disable-next-line @typescript-eslint/restrict-template-expressions - }/${file?.fileName}`, - fileContent - ) - } - } catch (e) { - if (e instanceof Error) { - await remixClient.call('notification' as any, 'alert', { - id: 'starknetRemixPluginAlert', - title: 'Please check the write file permission', - message: e.message + '\n' + 'Did you provide the write file permission?' - }) - } - console.log(e) - } - } + // This runs every second once + const timeoutId = setTimeout(() => { + remixClient.filePanel.getCurrentWorkspace().then((currWorkspace) => { + setCurrWorkspacePath(currWorkspace.absolutePath) + }).catch(e => { + console.error(e) + }) + }, 1000) + return () => { clearInterval(timeoutId) } + }, []) + + // Remix Client Event Listeners + remixClient.on('fileManager', 'noFileSelected', () => { + setNoFileSelected(true) + }) + + remixClient.on( + 'fileManager', + 'currentFileChanged', + (currentFileChanged: any) => { + const filename = getFileNameFromPath(currentFileChanged) + const currentFileExtension = getFileExtension(filename) + setIsValidCairo(currentFileExtension === 'cairo') + setCurrentFileName(filename) + remixClient.emit('statusChanged', { + key: 'succeed', + type: 'info', + title: 'Current file: ' + filename + }) + setNoFileSelected(false) + } + ) + + remixClient.on('fileManager', 'fileAdded', (_: any) => { + getAndSetTomlPaths(remixClient, currWorkspacePath, setTomlPaths).catch(e => { console.error(e) }) + }) + remixClient.on('fileManager', 'folderAdded', (_: any) => { + getAndSetTomlPaths(remixClient, currWorkspacePath, setTomlPaths).catch(e => { console.error(e) }) + }) + remixClient.on('fileManager', 'fileRemoved', (_: any) => { + getAndSetTomlPaths(remixClient, currWorkspacePath, setTomlPaths).catch(e => { console.error(e) }) + }) + remixClient.on('filePanel', 'workspaceCreated', (_: any) => { + getAndSetTomlPaths(remixClient, currWorkspacePath, setTomlPaths).catch(e => { console.error(e) }) + }) + remixClient.on('filePanel', 'workspaceRenamed', (_: any) => { + getAndSetTomlPaths(remixClient, currWorkspacePath, setTomlPaths).catch(e => { console.error(e) }) + }) + + const getCurrentFileInfo = async (): Promise => { + try { + if (noFileSelected) { + throw new Error('No file selected') + } + + // get current file + const currentFilePath = await remixClient.call( + 'fileManager', + 'getCurrentFile' + ) + if (currentFilePath.length > 0) { + const filename = getFileNameFromPath(currentFilePath) + const currentFileExtension = getFileExtension(filename) + setIsValidCairo(currentFileExtension === 'cairo') + setCurrentFileName(filename) + setCurrentFilePath(currentFilePath) + + remixClient.emit('statusChanged', { + key: 'succeed', + type: 'info', + title: 'Current file: ' + filename }) + } + } catch (e) { + remixClient.emit('statusChanged', { + key: 'failed', + type: 'info', + title: 'Please open a cairo file to compile' }) - }, 1) - return () => { - clearInterval(id) + console.log('error: ', e) } - }, []) + } + + useEffect(() => { + getCurrentFileInfo().catch(e => { console.error(e) }) + }, [currentFileName, noFileSelected]) - return { remixClient, isPluginLoaded: pluginLoaded } + return { + remixClient, + isPluginLoaded: pluginLoaded, + currentFilePath, + currWorkspacePath + } } export default useRemixClient diff --git a/plugin/src/utils/initial_scarb_codes.ts b/plugin/src/utils/initial_scarb_codes.ts index 0e1bdfea..85aa3587 100644 --- a/plugin/src/utils/initial_scarb_codes.ts +++ b/plugin/src/utils/initial_scarb_codes.ts @@ -3,7 +3,7 @@ import axios from 'axios' export async function fetchGitHubFilesRecursively ( repository: string, path: string -): Promise> { +): Promise> { const apiUrl = `https://api.github.com/repos/${repository}/contents/${path}` try { From 760f01313274d3c99fe5121183bdb699d7be147e Mon Sep 17 00:00:00 2001 From: Prince Anuragi Date: Thu, 9 Nov 2023 17:17:14 +0530 Subject: [PATCH 2/3] fix: remove shadow and more reafctoring --- .../ui_components/Accordian/accordian.css | 1 - plugin/src/features/Compilation/index.tsx | 65 +++++++------------ plugin/src/hooks/useRemixClient.ts | 42 +++++++++++- 3 files changed, 63 insertions(+), 45 deletions(-) diff --git a/plugin/src/components/ui_components/Accordian/accordian.css b/plugin/src/components/ui_components/Accordian/accordian.css index 76eb3c47..8d0513fe 100644 --- a/plugin/src/components/ui_components/Accordian/accordian.css +++ b/plugin/src/components/ui_components/Accordian/accordian.css @@ -7,7 +7,6 @@ h3 { .AccordionRoot { border-radius: 6px; width: 100%; - box-shadow: 0 2px 10px var(--primary-color-100); } .AccordionItem { diff --git a/plugin/src/features/Compilation/index.tsx b/plugin/src/features/Compilation/index.tsx index 8fcbc145..76fb44b8 100644 --- a/plugin/src/features/Compilation/index.tsx +++ b/plugin/src/features/Compilation/index.tsx @@ -45,7 +45,14 @@ interface CompilationProps { } const Compilation: React.FC = ({ setAccordian }) => { - const { remixClient, currentFilePath, currWorkspacePath } = useRemixClient() + const { + remixClient, + currentFilePath, + currWorkspacePath, + writeFileContent, + getCurrentFileContent, + showNotification + } = useRemixClient() const cairoVersion = useAtomValue(cairoVersionAtom) const [contracts, setContracts] = useAtom(compiledContractsAtom) @@ -134,18 +141,8 @@ const Compilation: React.FC = ({ setAccordian }) => { // clear current file annotations: inline syntax error reporting await remixClient.editor.clearAnnotations() try { - setStatus('Getting cairo file path...') - const currentFilePath = await remixClient.call( - 'fileManager', - 'getCurrentFile' - ) - setStatus('Getting cairo file content...') - const currentFileContent = await remixClient.call( - 'fileManager', - 'readFile', - currentFilePath - ) + const currentFileContent = await getCurrentFileContent() setStatus('Parsing cairo code...') const saveCodeResponse = await fetch( @@ -293,15 +290,11 @@ const Compilation: React.FC = ({ setAccordian }) => { }) try { - await remixClient.call( - 'fileManager', - 'writeFile', + await writeFileContent( sierraPath, sierra.file_content ) - await remixClient.call( - 'fileManager', - 'writeFile', + await writeFileContent( casmPath, casm.file_content ) @@ -328,11 +321,10 @@ const Compilation: React.FC = ({ setAccordian }) => { // await remixClient.fileManager.open(sierraPath) - await remixClient.call( - 'notification' as any, - 'toast', + await showNotification( `Cairo compilation output written to: ${sierraPath} ` ) + setStatus('done') } catch (e) { setStatus('failed') @@ -388,9 +380,7 @@ const Compilation: React.FC = ({ setAccordian }) => { } ) if (!response.ok) { - await remixClient.call( - 'notification' as any, - 'toast', + await showNotification( 'Could not reach cairo compilation server' ) throw new Error('Cairo Compilation Request Failed') @@ -423,9 +413,7 @@ const Compilation: React.FC = ({ setAccordian }) => { '' )}/${scarbPath}`, 'compile-scarb-result') } catch (e) { - await remixClient.call( - 'notification' as any, - 'toast', + await showNotification( 'Could not reach cairo compilation server' ) throw new Error('Cairo Compilation Request Failed') @@ -433,14 +421,13 @@ const Compilation: React.FC = ({ setAccordian }) => { const scarbCompile: ScarbCompileResponse = JSON.parse(result) if (scarbCompile.status !== 'Success') { - await remixClient.call( - 'notification' as any, - 'alert', + await showNotification( { id: 'starknetRemixPluginAlert', title: 'Scarb compilation failed!', message: 'Scarb compilation failed!, you can read logs in the terminal console' - } + }, + 'alert' ) remixClient.emit('statusChanged', { key: 'failed', @@ -499,9 +486,7 @@ const Compilation: React.FC = ({ setAccordian }) => { if (selectedContract == null) setSelectedContract(contracts[0]) } if (notifyCasmInclusion) { - await remixClient.call( - 'notification' as any, - 'toast', + await showNotification( 'Please include \'casm=true\' in Scarb.toml to deploy cairo contracts' ) } @@ -511,23 +496,17 @@ const Compilation: React.FC = ({ setAccordian }) => { for (const file of scarbCompile.file_content_map_array) { // eslint-disable-next-line @typescript-eslint/restrict-template-expressions const filePath = `${scarbPath}/target/dev/${file.file_name}` - await remixClient.call( - 'fileManager', - 'writeFile', + await writeFileContent( filePath, JSON.stringify(JSON.parse(file.file_content)) ) } - await remixClient.call( - 'notification' as any, - 'toast', + await showNotification( `Compilation resultant files are written to ${scarbPath}/target/dev directory` ) } catch (e) { if (e instanceof Error) { - await remixClient.call( - 'notification' as any, - 'toast', + await showNotification( e.message + ' try deleting the dir: ' + scarbPath + 'target/dev' ) } diff --git a/plugin/src/hooks/useRemixClient.ts b/plugin/src/hooks/useRemixClient.ts index 86440e92..742f18b7 100644 --- a/plugin/src/hooks/useRemixClient.ts +++ b/plugin/src/hooks/useRemixClient.ts @@ -120,6 +120,12 @@ const useRemixClient = (): { isPluginLoaded: boolean currentFilePath: string currWorkspacePath: string + getCurrentFileContent: () => Promise + writeFileContent: (path: string, content: any) => Promise + showNotification: ( + message: string | Record, + type?: string + ) => Promise } => { const [pluginLoaded, setPluginLoaded] = useAtom(atomPluginLoaded) @@ -234,11 +240,45 @@ const useRemixClient = (): { getCurrentFileInfo().catch(e => { console.error(e) }) }, [currentFileName, noFileSelected]) + const getCurrentFileContent = async (): Promise => { + return await remixClient.call( + 'fileManager', + 'readFile', + currentFilePath + ) + } + + const writeFileContent = async ( + path: string, + content: string + ): Promise => { + await remixClient.call( + 'fileManager', + 'writeFile', + path, + content + ) + } + + const showNotification = async ( + message: string | Record, + type?: string + ): Promise => { + return await remixClient.call( + 'notification' as any, + type ?? 'toast', + message + ) + } + return { remixClient, isPluginLoaded: pluginLoaded, currentFilePath, - currWorkspacePath + currWorkspacePath, + getCurrentFileContent, + writeFileContent, + showNotification } } From af1d01dfa234c650c782c19392637a8bd78b3d9e Mon Sep 17 00:00:00 2001 From: Prince Anuragi Date: Thu, 16 Nov 2023 11:29:58 +0530 Subject: [PATCH 3/3] fix: move client subscriber to a only load in init --- plugin/src/hooks/useRemixClient.ts | 72 +++++++++++++++--------------- 1 file changed, 37 insertions(+), 35 deletions(-) diff --git a/plugin/src/hooks/useRemixClient.ts b/plugin/src/hooks/useRemixClient.ts index 742f18b7..29323f95 100644 --- a/plugin/src/hooks/useRemixClient.ts +++ b/plugin/src/hooks/useRemixClient.ts @@ -164,43 +164,45 @@ const useRemixClient = (): { return () => { clearInterval(timeoutId) } }, []) - // Remix Client Event Listeners - remixClient.on('fileManager', 'noFileSelected', () => { - setNoFileSelected(true) - }) + useEffect(() => { + // Remix Client Event Listeners + remixClient.on('fileManager', 'noFileSelected', () => { + setNoFileSelected(true) + }) - remixClient.on( - 'fileManager', - 'currentFileChanged', - (currentFileChanged: any) => { - const filename = getFileNameFromPath(currentFileChanged) - const currentFileExtension = getFileExtension(filename) - setIsValidCairo(currentFileExtension === 'cairo') - setCurrentFileName(filename) - remixClient.emit('statusChanged', { - key: 'succeed', - type: 'info', - title: 'Current file: ' + filename - }) - setNoFileSelected(false) - } - ) + remixClient.on( + 'fileManager', + 'currentFileChanged', + (currentFileChanged: any) => { + const filename = getFileNameFromPath(currentFileChanged) + const currentFileExtension = getFileExtension(filename) + setIsValidCairo(currentFileExtension === 'cairo') + setCurrentFileName(filename) + remixClient.emit('statusChanged', { + key: 'succeed', + type: 'info', + title: 'Current file: ' + filename + }) + setNoFileSelected(false) + } + ) - remixClient.on('fileManager', 'fileAdded', (_: any) => { - getAndSetTomlPaths(remixClient, currWorkspacePath, setTomlPaths).catch(e => { console.error(e) }) - }) - remixClient.on('fileManager', 'folderAdded', (_: any) => { - getAndSetTomlPaths(remixClient, currWorkspacePath, setTomlPaths).catch(e => { console.error(e) }) - }) - remixClient.on('fileManager', 'fileRemoved', (_: any) => { - getAndSetTomlPaths(remixClient, currWorkspacePath, setTomlPaths).catch(e => { console.error(e) }) - }) - remixClient.on('filePanel', 'workspaceCreated', (_: any) => { - getAndSetTomlPaths(remixClient, currWorkspacePath, setTomlPaths).catch(e => { console.error(e) }) - }) - remixClient.on('filePanel', 'workspaceRenamed', (_: any) => { - getAndSetTomlPaths(remixClient, currWorkspacePath, setTomlPaths).catch(e => { console.error(e) }) - }) + remixClient.on('fileManager', 'fileAdded', (_: any) => { + getAndSetTomlPaths(remixClient, currWorkspacePath, setTomlPaths).catch(e => { console.error(e) }) + }) + remixClient.on('fileManager', 'folderAdded', (_: any) => { + getAndSetTomlPaths(remixClient, currWorkspacePath, setTomlPaths).catch(e => { console.error(e) }) + }) + remixClient.on('fileManager', 'fileRemoved', (_: any) => { + getAndSetTomlPaths(remixClient, currWorkspacePath, setTomlPaths).catch(e => { console.error(e) }) + }) + remixClient.on('filePanel', 'workspaceCreated', (_: any) => { + getAndSetTomlPaths(remixClient, currWorkspacePath, setTomlPaths).catch(e => { console.error(e) }) + }) + remixClient.on('filePanel', 'workspaceRenamed', (_: any) => { + getAndSetTomlPaths(remixClient, currWorkspacePath, setTomlPaths).catch(e => { console.error(e) }) + }) + }, []) const getCurrentFileInfo = async (): Promise => { try {