diff --git a/.github/workflows/pr-reminder.yml b/.github/workflows/pr-reminder.yml index eaedd51125..ee24eebb0b 100644 --- a/.github/workflows/pr-reminder.yml +++ b/.github/workflows/pr-reminder.yml @@ -14,4 +14,4 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: webhook-url: ${{ secrets.DISCORD_WEBHOOK_URL }} - freeze-date: '2024-09-09T18:00:00Z' + freeze-date: '2024-10-07T18:00:00Z' diff --git a/apps/circuit-compiler/src/app/actions/index.ts b/apps/circuit-compiler/src/app/actions/index.ts index 2f48faf2fb..84417c7fea 100644 --- a/apps/circuit-compiler/src/app/actions/index.ts +++ b/apps/circuit-compiler/src/app/actions/index.ts @@ -3,7 +3,6 @@ import type { CircomPluginClient } from "../services/circomPluginClient" import { ActionPayloadTypes, AppState, ICircuitAppContext } from "../types" import { GROTH16_VERIFIER, PLONK_VERIFIER } from './constant' import { extractNameFromKey, extractParentFromKey } from '@remix-ui/helper' -import { ethers } from 'ethers' export const compileCircuit = async (plugin: CircomPluginClient, appState: AppState) => { try { @@ -19,12 +18,21 @@ export const compileCircuit = async (plugin: CircomPluginClient, appState: AppSt } } -export const computeWitness = async (plugin: CircomPluginClient, status: string, witnessValues: Record) => { +export const computeWitness = async (plugin: CircomPluginClient, appState: AppState, dispatch: ICircuitAppContext['dispatch'], status: string, witnessValues: Record) => { try { if (status !== "computing") { const input = JSON.stringify(witnessValues) + const witness = await plugin.computeWitness(input) - await plugin.computeWitness(input) + if (appState.exportWtnsJson) { + const wtns = await snarkjs.wtns.exportJson(witness) + const wtnsJson = wtns.map(wtn => wtn.toString()) + const fileName = extractNameFromKey(appState.filePath) + const writePath = extractParentFromKey(appState.filePath) + `/.bin/${fileName.replace('.circom', '.wtn.json')}` + + await plugin.call('fileManager', 'writeFile', writePath, JSON.stringify(wtnsJson, null, 2)) + plugin._paq.push(['trackEvent', 'circuit-compiler', 'computeWitness', 'wtns.exportJson', writePath]) + } } else { console.log('Existing witness computation in progress') } @@ -38,6 +46,8 @@ export const computeWitness = async (plugin: CircomPluginClient, status: string, export const runSetupAndExport = async (plugin: CircomPluginClient, appState: AppState, dispatch: ICircuitAppContext['dispatch']) => { try { dispatch({ type: 'SET_COMPILER_STATUS', payload: 'exporting' }) + dispatch({ type: 'SET_SETUP_EXPORT_FEEDBACK', payload: null }) + plugin.emit('statusChanged', { key: 'none' }) const ptau_final = `https://ipfs-cluster.ethdevops.io/ipfs/${appState.ptauList.find(ptau => ptau.name === appState.ptauValue)?.ipfsHash}` await plugin.generateR1cs(appState.filePath, { version: appState.version, prime: appState.primeValue }) @@ -50,32 +60,38 @@ export const runSetupAndExport = async (plugin: CircomPluginClient, appState: Ap const zkey_final = { type: "mem" } if (appState.provingScheme === 'groth16') { + plugin._paq.push(['trackEvent', 'circuit-compiler', 'runSetupAndExport', 'provingScheme', 'groth16']) await snarkjs.zKey.newZKey(r1cs, ptau_final, zkey_final, zkLogger(plugin, dispatch, 'SET_SETUP_EXPORT_FEEDBACK')) const vKey = await snarkjs.zKey.exportVerificationKey(zkey_final, zkLogger(plugin, dispatch, 'SET_SETUP_EXPORT_FEEDBACK')) if (appState.exportVerificationKey) { await plugin.call('fileManager', 'writeFile', `${extractParentFromKey(appState.filePath)}/groth16/zk/keys/verification_key.json`, JSON.stringify(vKey, null, 2)) + plugin._paq.push(['trackEvent', 'circuit-compiler', 'runSetupAndExport', 'zKey.exportVerificationKey', `${extractParentFromKey(appState.filePath)}/groth16/zk/keys/verification_key.json`]) } if (appState.exportVerificationContract) { const templates = { groth16: GROTH16_VERIFIER } const solidityContract = await snarkjs.zKey.exportSolidityVerifier(zkey_final, templates, zkLogger(plugin, dispatch, 'SET_SETUP_EXPORT_FEEDBACK')) await plugin.call('fileManager', 'writeFile', `${extractParentFromKey(appState.filePath)}/groth16/zk/build/zk_verifier.sol`, solidityContract) + plugin._paq.push(['trackEvent', 'circuit-compiler', 'runSetupAndExport', 'zKey.exportSolidityVerifier', `${extractParentFromKey(appState.filePath)}/groth16/zk/build/zk_verifier.sol`]) } dispatch({ type: 'SET_ZKEY', payload: zkey_final }) dispatch({ type: 'SET_VERIFICATION_KEY', payload: vKey }) } else if (appState.provingScheme === 'plonk') { + plugin._paq.push(['trackEvent', 'circuit-compiler', 'runSetupAndExport', 'provingScheme', 'plonk']) await snarkjs.plonk.setup(r1cs, ptau_final, zkey_final, zkLogger(plugin, dispatch, 'SET_SETUP_EXPORT_FEEDBACK')) const vKey = await snarkjs.zKey.exportVerificationKey(zkey_final, zkLogger(plugin, dispatch, 'SET_SETUP_EXPORT_FEEDBACK')) if (appState.exportVerificationKey) { await plugin.call('fileManager', 'writeFile', `${extractParentFromKey(appState.filePath)}/plonk/zk/keys/verification_key.json`, JSON.stringify(vKey, null, 2)) + plugin._paq.push(['trackEvent', 'circuit-compiler', 'runSetupAndExport', 'zKey.exportVerificationKey', `${extractParentFromKey(appState.filePath)}/plonk/zk/keys/verification_key.json`]) } if (appState.exportVerificationContract) { const templates = { plonk: PLONK_VERIFIER } const solidityContract = await snarkjs.zKey.exportSolidityVerifier(zkey_final, templates, zkLogger(plugin, dispatch, 'SET_SETUP_EXPORT_FEEDBACK')) await plugin.call('fileManager', 'writeFile', `${extractParentFromKey(appState.filePath)}/plonk/zk/build/zk_verifier.sol`, solidityContract) + plugin._paq.push(['trackEvent', 'circuit-compiler', 'runSetupAndExport', 'zKey.exportSolidityVerifier', `${extractParentFromKey(appState.filePath)}/plonk/zk/build/zk_verifier.sol`]) } dispatch({ type: 'SET_ZKEY', payload: zkey_final }) dispatch({ type: 'SET_VERIFICATION_KEY', payload: vKey }) @@ -83,6 +99,7 @@ export const runSetupAndExport = async (plugin: CircomPluginClient, appState: Ap dispatch({ type: 'SET_COMPILER_STATUS', payload: 'idle' }) dispatch({ type: 'SET_SETUP_EXPORT_STATUS', payload: 'done' }) } catch (e) { + plugin._paq.push(['trackEvent', 'circuit-compiler', 'runSetupAndExport', 'error', e.message]) dispatch({ type: 'SET_COMPILER_STATUS', payload: 'errored' }) console.error(e) } @@ -91,6 +108,8 @@ export const runSetupAndExport = async (plugin: CircomPluginClient, appState: Ap export const generateProof = async (plugin: CircomPluginClient, appState: AppState, dispatch: ICircuitAppContext['dispatch']) => { try { dispatch({ type: 'SET_COMPILER_STATUS', payload: 'proving' }) + dispatch({ type: 'SET_PROOF_FEEDBACK', payload: null }) + plugin.emit('statusChanged', { key: 'none' }) const fileName = extractNameFromKey(appState.filePath) const r1csPath = extractParentFromKey(appState.filePath) + `/.bin/${fileName.replace('.circom', '.r1cs')}` // @ts-ignore @@ -110,21 +129,27 @@ export const generateProof = async (plugin: CircomPluginClient, appState: AppSta const { proof, publicSignals } = await snarkjs.groth16.prove(zkey_final, wtns, zkLogger(plugin, dispatch, 'SET_PROOF_FEEDBACK')) const verified = await snarkjs.groth16.verify(vKey, publicSignals, proof, zkLogger(plugin, dispatch, 'SET_PROOF_FEEDBACK')) + plugin.call('fileManager', 'writeFile', `${extractParentFromKey(appState.filePath)}/groth16/zk/build/proof.json`, JSON.stringify(proof, null, 2)) plugin.call('terminal', 'log', { type: 'log', value: 'zk proof validity ' + verified }) + plugin._paq.push(['trackEvent', 'circuit-compiler', 'generateProof', 'groth16.prove', verified]) if (appState.exportVerifierCalldata) { const calldata = await snarkjs.groth16.exportSolidityCallData(proof, publicSignals) plugin.call('fileManager', 'writeFile', `${extractParentFromKey(appState.filePath)}/groth16/zk/build/verifierCalldata.json`, calldata) + plugin._paq.push(['trackEvent', 'circuit-compiler', 'generateProof', 'groth16.exportSolidityCallData', `${extractParentFromKey(appState.filePath)}/groth16/zk/build/verifierCalldata.json`]) } } else if (appState.provingScheme === 'plonk') { const { proof, publicSignals } = await snarkjs.plonk.prove(zkey_final, wtns, zkLogger(plugin, dispatch, 'SET_PROOF_FEEDBACK')) const verified = await snarkjs.plonk.verify(vKey, publicSignals, proof, zkLogger(plugin, dispatch, 'SET_PROOF_FEEDBACK')) + plugin.call('fileManager', 'writeFile', `${extractParentFromKey(appState.filePath)}/plonk/zk/build/proof.json`, JSON.stringify(proof, null, 2)) plugin.call('terminal', 'log', { type: 'log', value: 'zk proof validity ' + verified }) + plugin._paq.push(['trackEvent', 'circuit-compiler', 'generateProof', 'plonk.prove', verified]) if (appState.exportVerifierCalldata) { const calldata = await snarkjs.plonk.exportSolidityCallData(proof, publicSignals) plugin.call('fileManager', 'writeFile', `${extractParentFromKey(appState.filePath)}/plonk/zk/build/verifierCalldata.json`, calldata) + plugin._paq.push(['trackEvent', 'circuit-compiler', 'generateProof', 'plonk.exportSolidityCallData', `${extractParentFromKey(appState.filePath)}/plonk/zk/build/verifierCalldata.json`]) } } dispatch({ type: 'SET_COMPILER_STATUS', payload: 'idle' }) diff --git a/apps/circuit-compiler/src/app/components/container.tsx b/apps/circuit-compiler/src/app/components/container.tsx index 7cf3fe7ac1..2c7cc41e16 100644 --- a/apps/circuit-compiler/src/app/components/container.tsx +++ b/apps/circuit-compiler/src/app/components/container.tsx @@ -140,7 +140,7 @@ export function Container () { 0}> <> - + diff --git a/apps/circuit-compiler/src/app/components/witness.tsx b/apps/circuit-compiler/src/app/components/witness.tsx index 0a14537cde..dd40b9b2d0 100644 --- a/apps/circuit-compiler/src/app/components/witness.tsx +++ b/apps/circuit-compiler/src/app/components/witness.tsx @@ -1,12 +1,14 @@ import { RenderIf, RenderIfNot } from "@remix-ui/helper"; import { FormattedMessage } from "react-intl"; -import { CompilerStatus } from "../types"; import { computeWitness } from "../actions"; -import { useState } from "react"; -import type { CircomPluginClient } from "../services/circomPluginClient"; +import { useContext, useState } from "react"; import * as remixLib from '@remix-project/remix-lib' +import { CircuitAppContext } from "../contexts"; -export function WitnessSection ({ plugin, signalInputs, status }: {plugin: CircomPluginClient, signalInputs: string[], status: CompilerStatus}) { +export function WitnessSection () { + const circuitApp = useContext(CircuitAppContext) + const { signalInputs, status, exportWtnsJson } = circuitApp.appState + const { plugin, dispatch, appState } = circuitApp const [witnessValues, setWitnessValues] = useState>({}) const handleSignalInput = (e: any) => { @@ -47,9 +49,22 @@ export function WitnessSection ({ plugin, signalInputs, status }: {plugin: Circo )) } +
+ { dispatch({ type: 'SET_EXPORT_WTNS_JSON', payload: !exportWtnsJson }) }} + checked={exportWtnsJson} + /> + +
+ }}>Login with GitHub } {gitHubResponse && !authorized &&
@@ -105,15 +104,15 @@ export const GetDeviceCode = () => {
} { - (context.gitHubUser && context.gitHubUser.login) ? + (context.gitHubUser && context.gitHubUser.isConnected) ?
-
: null } { - (context.gitHubUser && context.gitHubUser.login) ? + (context.gitHubUser && context.gitHubUser.isConnected) ?
Connected as {context.gitHubUser.login}
diff --git a/libs/remix-ui/git/src/components/github/repositoryselect.tsx b/libs/remix-ui/git/src/components/github/repositoryselect.tsx index 40a9d7b4a3..72b055ba9a 100644 --- a/libs/remix-ui/git/src/components/github/repositoryselect.tsx +++ b/libs/remix-ui/git/src/components/github/repositoryselect.tsx @@ -1,7 +1,8 @@ import React, { useState, useEffect } from 'react'; import Select from 'react-select'; import { gitActionsContext } from '../../state/context'; -import { gitMatomoEventTypes, repository } from '../../types'; +import { repository } from '@remix-api'; +import { gitMatomoEventTypes } from '../../types'; import { selectStyles, selectTheme } from '../../types/styles'; import { gitPluginContext } from '../gitui'; import { sendToMatomo } from '../../lib/pluginActions'; diff --git a/libs/remix-ui/git/src/components/github/selectandclonerepositories.tsx b/libs/remix-ui/git/src/components/github/selectandclonerepositories.tsx index 5557c3f13b..9c3e879c71 100644 --- a/libs/remix-ui/git/src/components/github/selectandclonerepositories.tsx +++ b/libs/remix-ui/git/src/components/github/selectandclonerepositories.tsx @@ -1,6 +1,6 @@ import React, { useEffect, useState } from "react"; import { gitActionsContext } from "../../state/context"; -import { repository } from "../../types"; +import { repository } from "@remix-api"; import { gitPluginContext } from "../gitui"; import RepositorySelect from "./repositoryselect"; import { BranchSelect } from "./branchselect"; diff --git a/libs/remix-ui/git/src/components/gitui.tsx b/libs/remix-ui/git/src/components/gitui.tsx index f5d1460487..b7444e0b8d 100644 --- a/libs/remix-ui/git/src/components/gitui.tsx +++ b/libs/remix-ui/git/src/components/gitui.tsx @@ -1,11 +1,11 @@ -import React, { useEffect, useReducer, useState } from 'react' -import { add, addall, checkout, checkoutfile, clone, commit, createBranch, remoteBranches, repositories, rm, getCommitChanges, diff, resolveRef, getBranchCommits, setUpstreamRemote, loadGitHubUserFromToken, getBranches, getRemotes, remoteCommits, saveGitHubCredentials, getGitHubCredentialsFromLocalStorage, fetch, pull, push, setDefaultRemote, addRemote, removeRemote, sendToGitLog, clearGitLog, getBranchDifferences, getFileStatusMatrix, init, showAlert, gitlog } from '../lib/gitactions' +import React, { useEffect, useReducer, useState, useContext } from 'react' +import { add, addall, checkout, checkoutfile, clone, commit, createBranch, remoteBranches, repositories, rm, getCommitChanges, diff, resolveRef, getBranchCommits, setUpstreamRemote, loadGitHubUserFromToken, getBranches, getRemotes, remoteCommits, saveGitHubCredentials, getGitHubCredentialsFromLocalStorage, fetch, pull, push, setDefaultRemote, addRemote, removeRemote, sendToGitLog, clearGitLog, getBranchDifferences, getFileStatusMatrix, init, showAlert, gitlog, setStateGitLogCount } from '../lib/gitactions' import { loadFiles, setCallBacks } from '../lib/listeners' -import { openDiff, openFile, saveToken, sendToMatomo, setModifiedDecorator, setPlugin, setUntrackedDecorator, statusChanged } from '../lib/pluginActions' +import { openDiff, openFile, openFolderInSameWindow, sendToMatomo, saveToken, setModifiedDecorator, setPlugin, setUntrackedDecorator, statusChanged } from '../lib/pluginActions' import { gitActionsContext, pluginActionsContext } from '../state/context' import { gitReducer } from '../state/gitreducer' -import { defaultGitState, defaultLoaderState, gitMatomoEventTypes, gitState, gitUIPanels, loaderState } from '../types' -import { Accordion } from "react-bootstrap"; +import { IGitUi, defaultGitState, defaultLoaderState, gitMatomoEventTypes, gitState, gitUIPanels, loaderState } from '../types' +import { Accordion, Button } from "react-bootstrap"; import { CommitMessage } from './buttons/commitmessage' import { Commits } from './panels/commits' import { Branches } from './panels/branches' @@ -19,7 +19,6 @@ import { Commands } from './panels/commands' import { CommandsNavigation } from './navigation/commands' import { RemotesNavigation } from './navigation/remotes' import { Remotes } from './panels/remotes' -import { ViewPlugin } from '@remixproject/engine-web' import { GitHubNavigation } from './navigation/github' import { loaderReducer } from '../state/loaderReducer' import { GetDeviceCode } from './github/devicecode' @@ -31,17 +30,13 @@ import { SourceControl } from './panels/sourcontrol' import { GitHubCredentials } from './panels/githubcredentials' import { Setup } from './panels/setup' import { Init } from './panels/init' -import { CustomRemixApi } from "@remix-api" -import { Plugin } from "@remixproject/engine" import { Disabled } from './disabled' +import { AppContext, appPlatformTypes, platformContext } from '@remix-ui/app' +import { Version } from './panels/version' export const gitPluginContext = React.createContext(defaultGitState) export const loaderContext = React.createContext(defaultLoaderState) -interface IGitUi { - plugin: Plugin -} - export const GitUI = (props: IGitUi) => { const plugin = props.plugin const [gitState, gitDispatch] = useReducer(gitReducer, defaultGitState) @@ -50,6 +45,9 @@ export const GitUI = (props: IGitUi) => { const [setup, setSetup] = useState(false) const [needsInit, setNeedsInit] = useState(true) const [appLoaded, setAppLoaded] = useState(false) + const appContext = useContext(AppContext) + + const platform = useContext(platformContext) useEffect(() => { plugin.emit('statusChanged', { @@ -64,12 +62,17 @@ export const GitUI = (props: IGitUi) => { useEffect(() => { if (!appLoaded) return - setCallBacks(plugin, gitDispatch, loaderDispatch, setActivePanel) + setCallBacks(plugin, gitDispatch, appContext.appStateDispatch, loaderDispatch, setActivePanel, platform) setPlugin(plugin, gitDispatch, loaderDispatch) loaderDispatch({ type: 'plugin', payload: true }) }, [appLoaded]) + useEffect(() => { + if (!appLoaded) return + gitlog(gitState.gitLogCount) + }, [gitState.timestamp, gitState.gitLogCount]) + useEffect(() => { if (!appLoaded) return async function checkconfig() { @@ -155,7 +158,8 @@ export const GitUI = (props: IGitUi) => { clearGitLog, getFileStatusMatrix, gitlog, - init + init, + setStateGitLogCount } const pluginActionsProviderValue = { @@ -166,7 +170,8 @@ export const GitUI = (props: IGitUi) => { saveToken, saveGitHubCredentials, getGitHubCredentialsFromLocalStorage, - showAlert + showAlert, + openFolderInSameWindow } return ( @@ -177,13 +182,10 @@ export const GitUI = (props: IGitUi) => { - - {setup && !needsInit ? : null} - {needsInit ? : null} - {!setup && !needsInit ? - + {setup ? : null} + + {!setup && !needsInit ? <> -
@@ -219,30 +221,34 @@ export const GitUI = (props: IGitUi) => {

- - -
-
-
-
- - -
- -
- -
-
-
- - -
- -
-
+ : null} + {needsInit ? <> + : null} + + +
+
+
+
-
- : null} + + +
+ +
+ +
+
+
+ + +
+ +
+
+
+ { platform === appPlatformTypes.desktop && + }
diff --git a/libs/remix-ui/git/src/components/navigation/branchedetails.tsx b/libs/remix-ui/git/src/components/navigation/branchedetails.tsx index 2407e5a071..0eeac2c0c2 100644 --- a/libs/remix-ui/git/src/components/navigation/branchedetails.tsx +++ b/libs/remix-ui/git/src/components/navigation/branchedetails.tsx @@ -2,7 +2,7 @@ import { faCaretUp, faCaretDown, faCaretRight, faArrowUp, faArrowDown, faArrowRo import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import React, { useContext, useEffect } from "react"; import { gitActionsContext } from "../../state/context"; -import { branch } from "../../types"; +import { branch } from "@remix-api"; import GitUIButton from "../buttons/gituibutton"; import { gitPluginContext } from "../gitui"; import { removeGitFromUrl } from "../../utils"; @@ -64,7 +64,7 @@ export const BrancheDetailsNavigation = (props: BrancheDetailsNavigationProps) = return ( <>
-
handleClick()} role={'button'} className='pointer d-flex flex-row w-100 commit-navigation'> +
handleClick()} role={'button'} className='pointer d-flex flex-row w-100 commit-navigation'> { activePanel === eventKey ? : } diff --git a/libs/remix-ui/git/src/components/navigation/branches.tsx b/libs/remix-ui/git/src/components/navigation/branches.tsx index 21decc6e7a..be02305932 100644 --- a/libs/remix-ui/git/src/components/navigation/branches.tsx +++ b/libs/remix-ui/git/src/components/navigation/branches.tsx @@ -3,6 +3,9 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import React, { } from "react"; import { gitActionsContext, pluginActionsContext } from "../../state/context"; import LoaderIndicator from "./loaderindicator"; +import { gitUIPanels } from "../../types"; +import { SourceControlBase } from "../buttons/sourceControlBase"; +import { SourceControlButtons } from "../buttons/sourcecontrolbuttons"; export const BranchesNavigation = ({ eventKey, activePanel, callback }) => { const pluginactions = React.useContext(pluginActionsContext) @@ -26,6 +29,7 @@ export const BranchesNavigation = ({ eventKey, activePanel, callback }) => { +
); diff --git a/libs/remix-ui/git/src/components/navigation/commitdetails.tsx b/libs/remix-ui/git/src/components/navigation/commitdetails.tsx index 2e49875f52..8848aae460 100644 --- a/libs/remix-ui/git/src/components/navigation/commitdetails.tsx +++ b/libs/remix-ui/git/src/components/navigation/commitdetails.tsx @@ -3,7 +3,7 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import React, { useContext, useEffect } from "react"; import { CommitSummary } from "../panels/commits/commitsummary"; import { ReadCommitResult } from "isomorphic-git" -import { branch } from "../../types"; +import { branch } from "@remix-api"; interface CommitDetailsNavigationProps { commit: ReadCommitResult, diff --git a/libs/remix-ui/git/src/components/navigation/commits.tsx b/libs/remix-ui/git/src/components/navigation/commits.tsx index 08798b4576..85c7dd1815 100644 --- a/libs/remix-ui/git/src/components/navigation/commits.tsx +++ b/libs/remix-ui/git/src/components/navigation/commits.tsx @@ -4,11 +4,12 @@ import { CustomTooltip } from "@remix-ui/helper"; import React, { useEffect } from "react"; import { FormattedMessage } from "react-intl"; import { pluginActionsContext } from "../../state/context"; -import { branch, remote } from "../../types"; +import { branch, remote } from "@remix-api"; import { SourceControlBase } from "../buttons/sourceControlBase"; import { SourceControlButtons } from "../buttons/sourcecontrolbuttons"; import { gitPluginContext } from "../gitui"; import LoaderIndicator from "./loaderindicator"; +import { gitUIPanels } from "../../types"; export interface CommitsNavigationProps { title: string, @@ -53,7 +54,7 @@ export const CommitsNavigation = ({ eventKey, activePanel, callback, title, bran {showButtons ? - + : null}
diff --git a/libs/remix-ui/git/src/components/navigation/loaderindicator.tsx b/libs/remix-ui/git/src/components/navigation/loaderindicator.tsx index 8c13e101b3..ee5e44aff0 100644 --- a/libs/remix-ui/git/src/components/navigation/loaderindicator.tsx +++ b/libs/remix-ui/git/src/components/navigation/loaderindicator.tsx @@ -13,7 +13,7 @@ const LoaderIndicator = ({ type, isLoadingCondition }: LoaderIndicatorProps) => const isLoading = loading || isLoadingCondition if (!isLoading) return null return ( - + ); }; diff --git a/libs/remix-ui/git/src/components/navigation/remotesdetails.tsx b/libs/remix-ui/git/src/components/navigation/remotesdetails.tsx index 626834feb1..4a702b1193 100644 --- a/libs/remix-ui/git/src/components/navigation/remotesdetails.tsx +++ b/libs/remix-ui/git/src/components/navigation/remotesdetails.tsx @@ -3,7 +3,8 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { CustomTooltip } from "@remix-ui/helper"; import React, { useContext, useEffect } from "react"; import { gitActionsContext } from "../../state/context"; -import { branch, gitMatomoEventTypes, remote } from "../../types"; +import { remote } from "@remix-api"; +import { gitMatomoEventTypes } from "../../types"; import GitUIButton from "../buttons/gituibutton"; import { gitPluginContext } from "../gitui"; import { removeGitFromUrl } from "../../utils"; diff --git a/libs/remix-ui/git/src/components/navigation/sourcecontrol.tsx b/libs/remix-ui/git/src/components/navigation/sourcecontrol.tsx index 7baf2f50e1..9f66bc9314 100644 --- a/libs/remix-ui/git/src/components/navigation/sourcecontrol.tsx +++ b/libs/remix-ui/git/src/components/navigation/sourcecontrol.tsx @@ -9,6 +9,7 @@ import { SourceControlButtons } from "../buttons/sourcecontrolbuttons"; import { gitPluginContext } from "../gitui"; import LoaderIndicator from "./loaderindicator"; import { SourceControlMenu } from "./menu/sourcecontrolmenu"; +import { gitUIPanels } from "../../types"; export const SourceControlNavigation = ({ eventKey, activePanel, callback }) => { const pluginactions = React.useContext(pluginActionsContext) @@ -35,7 +36,7 @@ export const SourceControlNavigation = ({ eventKey, activePanel, callback }) => - +
diff --git a/libs/remix-ui/git/src/components/panels/branches.tsx b/libs/remix-ui/git/src/components/panels/branches.tsx index 789550589e..e0db3e4a4e 100644 --- a/libs/remix-ui/git/src/components/panels/branches.tsx +++ b/libs/remix-ui/git/src/components/panels/branches.tsx @@ -1,46 +1,81 @@ import React, { useEffect, useState } from "react"; -import { Alert } from "react-bootstrap"; import { gitActionsContext } from "../../state/context"; -import { remote } from "../../types"; import GitUIButton from "../buttons/gituibutton"; import { gitPluginContext } from "../gitui"; import { LocalBranchDetails } from "./branches/localbranchdetails"; import { RemoteBranchDetails } from "./branches/remotebranchedetails"; import { faSync } from "@fortawesome/free-solid-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { branch } from "@remix-api"; + +const pageLength = 5; export const Branches = () => { const context = React.useContext(gitPluginContext) const actions = React.useContext(gitActionsContext) + const [localBranchPage, setLocalBranchPage] = useState(1); + const [remoteBranchPage, setRemoteBranchPage] = useState(1); const [newBranch, setNewBranch] = useState({ value: "" }); + const [localBranches, setLocalBranches] = useState([]); + const [remoteBranches, setRemoteBranches] = useState([]); + const [currentBranch, setCurrentBranch] = useState(null); const handleChange = (e: React.ChangeEvent) => { setNewBranch({ value: e.currentTarget.value }); }; + useEffect(() => { + if (context.branches) { + + if (context.currentBranch && context.currentBranch.name !== '') { + setCurrentBranch(context.branches.filter((branch, index) => !branch.remote && branch.name === context.currentBranch.name)[0]); + setLocalBranches(context.branches.filter((branch, index) => !branch.remote && branch.name !== context.currentBranch.name)); + } else { + setLocalBranches(context.branches.filter((branch, index) => !branch.remote)); + } + if (context.upstream) { + setRemoteBranches(context.branches.filter((branch, index) => branch.remote && branch.remote.name === context.upstream.name)); + } else { + setRemoteBranches([]); + } + } else { + setLocalBranches([]); + setRemoteBranches([]); + } + }, [context.branches, context.defaultRemote, context.upstream, context.currentBranch]); + return ( <>
{context.branches && context.branches.length ?
- - {context.branches && context.branches.filter((branch, index) => !branch.remote).map((branch, index) => { +
{localBranches.length}
+ {currentBranch && } + {context.branches && localBranches.slice(0, localBranchPage * pageLength).map((branch, index) => { return ( ); })} + {context.branches && localBranches.length > localBranchPage * pageLength && { + setLocalBranchPage(localBranchPage + 1) + }}>Show more}

{context.upstream ? <>
- - {context.branches && context.branches.filter((branch, index) => branch.remote && branch.remote.name === context.upstream.name).map((branch, index) => { - return ( - - ); - })} +
{remoteBranches.length}
+ {context.branches && remoteBranches + .slice(0, remoteBranchPage * pageLength) + .map((branch, index) => { + return ( + + ); + })} + {context.branches && remoteBranches.length > remoteBranchPage * pageLength && <> { + setRemoteBranchPage(remoteBranchPage + 1); + }}>Show more

} { await actions.fetch({ remote: context.upstream diff --git a/libs/remix-ui/git/src/components/panels/branches/branchdifferencedetails.tsx b/libs/remix-ui/git/src/components/panels/branches/branchdifferencedetails.tsx index c2090a87a5..b2a266c00a 100644 --- a/libs/remix-ui/git/src/components/panels/branches/branchdifferencedetails.tsx +++ b/libs/remix-ui/git/src/components/panels/branches/branchdifferencedetails.tsx @@ -3,7 +3,7 @@ import { Accordion } from "react-bootstrap"; import React, { useEffect, useState } from "react"; import { CommitDetails } from "../commits/commitdetails"; import { CommitsNavigation } from "../../navigation/commits"; -import { branch, remote } from "../../../types"; +import { branch, remote } from "@remix-api"; import { gitActionsContext } from "../../../state/context"; import { gitPluginContext } from "../../gitui"; diff --git a/libs/remix-ui/git/src/components/panels/branches/branchdifferences.tsx b/libs/remix-ui/git/src/components/panels/branches/branchdifferences.tsx index 846d0230d1..86d4584724 100644 --- a/libs/remix-ui/git/src/components/panels/branches/branchdifferences.tsx +++ b/libs/remix-ui/git/src/components/panels/branches/branchdifferences.tsx @@ -1,4 +1,4 @@ -import { branch, remote } from "../../../types"; +import { branch, remote } from "@remix-api"; import React, { useEffect, useState } from "react"; import { gitPluginContext } from "../../gitui"; import { CommitDetails } from "../commits/commitdetails"; diff --git a/libs/remix-ui/git/src/components/panels/branches/localbranchdetails.tsx b/libs/remix-ui/git/src/components/panels/branches/localbranchdetails.tsx index 2b996a3d34..dd9ab94358 100644 --- a/libs/remix-ui/git/src/components/panels/branches/localbranchdetails.tsx +++ b/libs/remix-ui/git/src/components/panels/branches/localbranchdetails.tsx @@ -4,7 +4,8 @@ import { Accordion } from "react-bootstrap"; import { CommitDetailsNavigation } from "../../navigation/commitdetails"; import { gitActionsContext } from "../../../state/context"; import { gitPluginContext } from "../../gitui"; -import { branch, gitMatomoEventTypes } from "../../../types"; +import { branch } from "@remix-api"; +import { gitMatomoEventTypes } from "../../../types"; import { BrancheDetailsNavigation } from "../../navigation/branchedetails"; import { CommitDetailsItems } from "../commits/commitdetailsitem"; import { CommitDetails } from "../commits/commitdetails"; @@ -81,7 +82,7 @@ export const LocalBranchDetails = (props: BrancheDetailsProps) => { })}
- {hasNextPage && Load more} + {hasNextPage && Load more} ) diff --git a/libs/remix-ui/git/src/components/panels/branches/remotebranchedetails.tsx b/libs/remix-ui/git/src/components/panels/branches/remotebranchedetails.tsx index d80e999ee1..fcff0754a3 100644 --- a/libs/remix-ui/git/src/components/panels/branches/remotebranchedetails.tsx +++ b/libs/remix-ui/git/src/components/panels/branches/remotebranchedetails.tsx @@ -4,7 +4,8 @@ import { Accordion } from "react-bootstrap"; import { CommitDetailsNavigation } from "../../navigation/commitdetails"; import { gitActionsContext } from "../../../state/context"; import { gitPluginContext } from "../../gitui"; -import { branch, gitMatomoEventTypes } from "../../../types"; +import { branch } from "@remix-api"; +import { gitMatomoEventTypes } from "../../../types"; import { BrancheDetailsNavigation } from "../../navigation/branchedetails"; import { CommitDetailsItems } from "../commits/commitdetailsitem"; import { CommitDetails } from "../commits/commitdetails"; @@ -59,7 +60,6 @@ export const RemoteBranchDetails = (props: BrancheDetailsProps) => { }) await actions.checkout({ ref: branch.name, - remote: branch.remote && branch.remote.name || null, refresh: true }); await actions.getBranches() @@ -107,7 +107,7 @@ export const RemoteBranchDetails = (props: BrancheDetailsProps) => { })}
- {hasNextPage && Load more} + {hasNextPage && Load more} ) diff --git a/libs/remix-ui/git/src/components/panels/clone.tsx b/libs/remix-ui/git/src/components/panels/clone.tsx index e7719fe68e..ab3ed7d6cb 100644 --- a/libs/remix-ui/git/src/components/panels/clone.tsx +++ b/libs/remix-ui/git/src/components/panels/clone.tsx @@ -78,7 +78,7 @@ export const Clone = (props: CloneProps) => { onGitHubCloneUrlChange(e.target.value)} aria-describedby="urlprepend" /> - onCloneBranchChange(e.target.value)} value={cloneBranch} className="form-control mb-2 mt-2" placeholder="branch" type="text" id="clonebranch" /> + onCloneBranchChange(e.target.value)} value={cloneBranch} className="form-control mb-2 mt-2" placeholder="branch" type="text" id="clonebranch" /> { clone() }}>clone diff --git a/libs/remix-ui/git/src/components/panels/commands/pushpull.tsx b/libs/remix-ui/git/src/components/panels/commands/pushpull.tsx index 981542f7cc..3fae193fd9 100644 --- a/libs/remix-ui/git/src/components/panels/commands/pushpull.tsx +++ b/libs/remix-ui/git/src/components/panels/commands/pushpull.tsx @@ -4,7 +4,8 @@ import { gitPluginContext } from "../../gitui"; import { selectStyles, selectTheme } from "../../../types/styles"; import Select, { Options, OptionsOrGroups } from 'react-select' import GitUIButton from "../../buttons/gituibutton"; -import { gitMatomoEventTypes, remote } from "../../../types"; +import { remote } from "@remix-api"; +import { gitMatomoEventTypes } from "../../../types"; import { relative } from "path"; import { sendToMatomo } from "../../../lib/pluginActions"; diff --git a/libs/remix-ui/git/src/components/panels/commits.tsx b/libs/remix-ui/git/src/components/panels/commits.tsx index 8fa50a9d99..584c3f2fb4 100644 --- a/libs/remix-ui/git/src/components/panels/commits.tsx +++ b/libs/remix-ui/git/src/components/panels/commits.tsx @@ -1,12 +1,10 @@ -import { checkout, ReadCommitResult } from "isomorphic-git"; +import { ReadCommitResult } from "isomorphic-git"; import React from "react"; import { gitActionsContext } from "../../state/context"; import GitUIButton from "../buttons/gituibutton"; import { gitPluginContext } from "../gitui"; -import LoaderIndicator from "../navigation/loaderindicator"; import { BranchDifferences } from "./branches/branchdifferences"; import { CommitDetails } from "./commits/commitdetails"; -import { CommitSummary } from "./commits/commitsummary"; export const Commits = () => { const [hasNextPage, setHasNextPage] = React.useState(true) @@ -21,15 +19,16 @@ export const Commits = () => { } }; - const loadNextPage = () => { - actions.fetch({ + const loadNextPage = async () => { + await actions.fetch({ remote: null, ref: context.currentBranch, relative: true, depth: 5, - singleBranch: true + singleBranch: true, + quiet: true }) - + await actions.setStateGitLogCount(context.gitLogCount + 5) } const getRemote = () => { @@ -56,7 +55,7 @@ export const Commits = () => { })}
- {hasNextPage && Load more} + {hasNextPage && Load more} :
No commits
} diff --git a/libs/remix-ui/git/src/components/panels/commits/commitdetailsitem.tsx b/libs/remix-ui/git/src/components/panels/commits/commitdetailsitem.tsx index 3a02aefd87..cf7d80ed88 100644 --- a/libs/remix-ui/git/src/components/panels/commits/commitdetailsitem.tsx +++ b/libs/remix-ui/git/src/components/panels/commits/commitdetailsitem.tsx @@ -1,4 +1,4 @@ -import { branch, commitChange } from "../../../types"; +import { branch, commitChange } from "@remix-api"; import React from "react"; import path from "path"; import { gitActionsContext, pluginActionsContext } from "../../../state/context"; diff --git a/libs/remix-ui/git/src/components/panels/commits/commitsummary.tsx b/libs/remix-ui/git/src/components/panels/commits/commitsummary.tsx index bff01b4712..bd1e3a7dbd 100644 --- a/libs/remix-ui/git/src/components/panels/commits/commitsummary.tsx +++ b/libs/remix-ui/git/src/components/panels/commits/commitsummary.tsx @@ -61,7 +61,7 @@ export const CommitSummary = (props: CommitSummaryProps) => { return ( <> -
+
{commit.commit.message}
{commit.commit.author.name || ""} diff --git a/libs/remix-ui/git/src/components/panels/githubcredentials.tsx b/libs/remix-ui/git/src/components/panels/githubcredentials.tsx index 3635fbe988..e466aeeaf9 100644 --- a/libs/remix-ui/git/src/components/panels/githubcredentials.tsx +++ b/libs/remix-ui/git/src/components/panels/githubcredentials.tsx @@ -22,7 +22,11 @@ export const GitHubCredentials = () => { useEffect(() => { refresh() if (context.gitHubUser) { - setScopeWarning(!(context.gitHubScopes && context.gitHubScopes.length > 0)) + setScopeWarning(!(context.gitHubScopes + && context.gitHubScopes.includes('repo') + && context.gitHubScopes.includes('read:user') + && context.gitHubScopes.includes('user:email') + && context.gitHubScopes.includes('gist'))) } else { setScopeWarning(false) } @@ -92,7 +96,7 @@ export const GitHubCredentials = () => {
{scopeWarning ? -
Your GitHub token may not have the correct permissions. Please use the login with GitHub feature.
: null} +
Your GitHub token may or may not have the correct permissions. Remix can't verify the permissions when using your own token. Please use the login with GitHub feature.
: null}
); diff --git a/libs/remix-ui/git/src/components/panels/init.tsx b/libs/remix-ui/git/src/components/panels/init.tsx index 37969cfb0b..37996deddd 100644 --- a/libs/remix-ui/git/src/components/panels/init.tsx +++ b/libs/remix-ui/git/src/components/panels/init.tsx @@ -27,9 +27,6 @@ export const Init = () => { > -
-
CLONE
- ) } \ No newline at end of file diff --git a/libs/remix-ui/git/src/components/panels/remoteselect.tsx b/libs/remix-ui/git/src/components/panels/remoteselect.tsx index 1bff2867b9..1111a84172 100644 --- a/libs/remix-ui/git/src/components/panels/remoteselect.tsx +++ b/libs/remix-ui/git/src/components/panels/remoteselect.tsx @@ -1,42 +1,63 @@ -import { branch, checkout, ReadCommitResult } from "isomorphic-git"; import React, { useEffect, useState } from "react"; import { gitActionsContext } from "../../state/context"; import { gitPluginContext } from "../gitui"; import { default as dateFormat } from "dateformat"; import { RemotesDetailsNavigation } from "../navigation/remotesdetails"; import { Accordion } from "react-bootstrap"; -import { remote } from "../../types"; +import { remote } from "@remix-api"; import { RemoteBranchDetails } from "./branches/remotebranchedetails"; import GitUIButton from "../buttons/gituibutton"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { faSync } from "@fortawesome/free-solid-svg-icons"; +import { branch } from "@remix-api"; export interface RemoteSelectProps { remote: remote openDefault: boolean } +const pageLength = 5; + export const Remoteselect = (props: RemoteSelectProps) => { const { remote, openDefault } = props; const context = React.useContext(gitPluginContext) const actions = React.useContext(gitActionsContext) const [activePanel, setActivePanel] = useState(""); + const [remoteBranchPage, setRemoteBranchPage] = useState(1); + const [remoteBranches, setRemoteBranches] = useState([]); useEffect(() => { setActivePanel(openDefault ? "0" : "") }, [openDefault]) + useEffect(() => { + if (context.branches) { + if (remote && remote.name) { + setRemoteBranches(context.branches.filter((branch, index) => branch.remote && branch.remote.name === remote.name)) + } else { + setRemoteBranches([]); + } + } else { + setRemoteBranches([]); + } + }, [context.branches, context.defaultRemote, context.upstream, remote]); + return ( <> <> - {context.branches && context.branches.filter((branch, index) => branch.remote && branch.remote.name === remote.name).map((branch, index) => { - return ( - - ); - })} + {context.branches && remoteBranches + .slice(0, remoteBranchPage * pageLength) + .map((branch, index) => { + return ( + + ); + })} + {context.branches && remoteBranches.length > remoteBranchPage * pageLength && <> { + setRemoteBranchPage(remoteBranchPage + 1); + }}>Show more

} { await actions.fetch({ remote diff --git a/libs/remix-ui/git/src/components/panels/remotesimport.tsx b/libs/remix-ui/git/src/components/panels/remotesimport.tsx index 47c714f186..fc1a423de3 100644 --- a/libs/remix-ui/git/src/components/panels/remotesimport.tsx +++ b/libs/remix-ui/git/src/components/panels/remotesimport.tsx @@ -1,8 +1,8 @@ -import React, { useEffect, useState } from "react" -import { Alert, Button } from "react-bootstrap" -import { gitActionsContext } from "../../state/context" -import { repository } from "../../types" -import { gitPluginContext } from "../gitui" +import React, { useEffect, useState } from "react"; +import { Alert, Button } from "react-bootstrap"; +import { gitActionsContext } from "../../state/context"; +import { repository } from "@remix-api"; +import { gitPluginContext } from "../gitui"; import Select from 'react-select' import { selectStyles, selectTheme } from "../../types/styles" import { TokenWarning } from "./tokenWarning" diff --git a/libs/remix-ui/git/src/components/panels/setup.tsx b/libs/remix-ui/git/src/components/panels/setup.tsx index 71b35f1499..184a46eadf 100644 --- a/libs/remix-ui/git/src/components/panels/setup.tsx +++ b/libs/remix-ui/git/src/components/panels/setup.tsx @@ -1,39 +1,28 @@ import React, { useEffect, useState } from 'react' -import { GetDeviceCode } from '../github/devicecode' -import { GitHubCredentials } from './githubcredentials' -import { Clone } from './clone' +import { gitUIPanels } from '../../types' +import GitUIButton from '../buttons/gituibutton' +import { FormattedMessage } from 'react-intl' -export const Setup = () => { +export const Setup = ({ callback }) => { - const [screen, setScreen] = useState(0) + const startSetingUp = () => { + callback(gitUIPanels.GITHUB) + } - if (screen === 0) { - return ( - <> -
SETUP
-
-
- To ensure that your commits are properly attributed in Git, you need to configure a username and email address. - These will be used to identify the author of the commit. -
- -
- -
-
CLONE
- - - ) - } else if (screen === 1) { - return ( - <> -
SETUP
-
Step 2
-
- To ensure that your commits are properly attributed in Git, you need to configure your username and email address. - + return ( + <> +
SETUP REQUIRED
+
+
+ To ensure that your commits are properly attributed in Git, you need to configure a username and email address or connect to GitHub. + These credentials will be used to identify the author of the commit. + + +
- - ) - } +
+
+ + ) + } \ No newline at end of file diff --git a/libs/remix-ui/git/src/components/panels/sourcecontrol/sourcecontrolitem.tsx b/libs/remix-ui/git/src/components/panels/sourcecontrol/sourcecontrolitem.tsx index a28d2a6664..0a96f7b728 100644 --- a/libs/remix-ui/git/src/components/panels/sourcecontrol/sourcecontrolitem.tsx +++ b/libs/remix-ui/git/src/components/panels/sourcecontrol/sourcecontrolitem.tsx @@ -1,4 +1,4 @@ -import { commitChange, fileStatusResult, sourceControlGroup } from "../../../types"; +import { fileStatusResult, sourceControlGroup } from "../../../types"; import React from "react"; import path from "path"; import { gitActionsContext, pluginActionsContext } from "../../../state/context"; @@ -6,6 +6,7 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { faGlobe } from "@fortawesome/free-solid-svg-icons"; import { SourceControlItemButtons } from "./sourcontrolitembuttons"; import { removeSlash } from "../../../utils"; +import { commitChange } from "@remix-api"; export interface SourceControlItemProps { file: fileStatusResult; diff --git a/libs/remix-ui/git/src/components/panels/sourcecontrol/sourcontrolitembuttons.tsx b/libs/remix-ui/git/src/components/panels/sourcecontrol/sourcontrolitembuttons.tsx index d1ba05ef1f..572180329c 100644 --- a/libs/remix-ui/git/src/components/panels/sourcecontrol/sourcontrolitembuttons.tsx +++ b/libs/remix-ui/git/src/components/panels/sourcecontrol/sourcontrolitembuttons.tsx @@ -1,4 +1,4 @@ -import { commitChange, fileStatusResult, sourceControlGroup } from "../../../types"; +import { fileStatusResult, sourceControlGroup } from "../../../types"; import React from "react"; import path from "path"; import { gitActionsContext, pluginActionsContext } from "../../../state/context"; diff --git a/libs/remix-ui/git/src/components/panels/version.tsx b/libs/remix-ui/git/src/components/panels/version.tsx new file mode 100644 index 0000000000..ccfef84ac9 --- /dev/null +++ b/libs/remix-ui/git/src/components/panels/version.tsx @@ -0,0 +1,10 @@ +import React, { useEffect, useState } from 'react' +import { gitPluginContext } from '../gitui' +export const Version = () => { + const context = React.useContext(gitPluginContext) + return ( +
+

{context.version.includes('version') ? context.version : `Git version: ${context.version}` }

+
+ ) +} \ No newline at end of file diff --git a/libs/remix-ui/git/src/index.ts b/libs/remix-ui/git/src/index.ts index 677c174059..57959fe7e1 100644 --- a/libs/remix-ui/git/src/index.ts +++ b/libs/remix-ui/git/src/index.ts @@ -1,4 +1,4 @@ export * from './types' export { GitUI } from './components/gitui' -export { commitChange, commitChangeType, remote, branch } from './types' +export { commitChange, commitChangeType, remote, branch } from '@remix-api' export * from './types/styles' \ No newline at end of file diff --git a/libs/remix-ui/git/src/lib/gitactions.ts b/libs/remix-ui/git/src/lib/gitactions.ts index 1805289dfc..f7e549de2c 100644 --- a/libs/remix-ui/git/src/lib/gitactions.ts +++ b/libs/remix-ui/git/src/lib/gitactions.ts @@ -1,13 +1,13 @@ import { ReadBlobResult, ReadCommitResult } from "isomorphic-git"; import React from "react"; -import { fileStatus, fileStatusMerge, setRemoteBranchCommits, resetRemoteBranchCommits, setBranches, setCanCommit, setCommitChanges, setCommits, setCurrentBranch, setGitHubUser, setLoading, setRemoteBranches, setRemotes, setRepos, setUpstream, setLocalBranchCommits, setBranchDifferences, setRemoteAsDefault, setScopes, setLog, clearLog, setUserEmails, setCurrenHead, setStoragePayload, resetBranchDifferences } from "../state/gitpayload"; -import { GitHubUser, branch, commitChange, gitActionDispatch, statusMatrixType, gitState, branchDifference, remote, gitLog, fileStatusResult, customGitApi, IGitApi, cloneInputType, fetchInputType, pullInputType, pushInputType, checkoutInput, rmInput, addInput, repository, userEmails, storage, gitMatomoEventTypes } from '../types'; +import { fileStatus, fileStatusMerge, setRemoteBranchCommits, resetRemoteBranchCommits, setBranches, setCanCommit, setCommitChanges, setCommits, setCurrentBranch, setGitHubUser, setLoading, setRemoteBranches, setRemotes, setRepos, setUpstream, setLocalBranchCommits, setBranchDifferences, setRemoteAsDefault, setScopes, setLog, clearLog, setUserEmails, setCurrenHead, setStoragePayload, resetBranchDifferences, setTimestamp, setGitLogCount } from "../state/gitpayload"; +import { gitActionDispatch, statusMatrixType, gitState, gitLog, fileStatusResult, storage, gitMatomoEventTypes } from '../types'; import { removeSlash } from "../utils"; import { disableCallBacks, enableCallBacks } from "./listeners"; -import { ModalTypes } from "@remix-ui/app"; +import { ModalTypes, appActionTypes, AppAction } from "@remix-ui/app"; import { sendToMatomo, setFileDecorators } from "./pluginActions"; import { Plugin } from "@remixproject/engine"; -import { CustomRemixApi } from "@remix-api"; +import { addInputType, branch, branchDifference, checkoutInputType, cloneInputType, commitChange, CustomRemixApi, fetchInputType, GitHubUser, pullInputType, pushInputType, remote, rmInputType, userEmails } from "@remix-api"; export const fileStatuses = [ ["new,untracked", 0, 2, 0], // new, untracked @@ -20,7 +20,7 @@ export const fileStatuses = [ ["deleted,unstaged", 1, 0, 1], // deleted, unstaged ["deleted,staged", 1, 0, 0], ["unmodified", 1, 1, 3], - ["deleted,not in git", 0, 0, 3], + ["added,deleted", 0, 0, 3], ["unstaged,modified", 1, 2, 0] ]; @@ -31,29 +31,31 @@ const statusmatrix: statusMatrixType[] = fileStatuses.map((x: any) => { }; }); -let plugin: Plugin, dispatch: React.Dispatch +let plugin: Plugin, dispatch: React.Dispatch, appDispatcher: React.Dispatch -export const setPlugin = (p: Plugin, dispatcher: React.Dispatch) => { +export const setPlugin = (p: Plugin, dispatcher: React.Dispatch, appDispatch: React.Dispatch) => { plugin = p dispatch = dispatcher + appDispatcher = appDispatch } export const init = async () => { await sendToMatomo(gitMatomoEventTypes.INIT) await plugin.call('dgitApi', "init"); - await gitlog(); + dispatch(setTimestamp(Date.now())) await getBranches(); } export const getBranches = async () => { - const branches = await plugin.call('dgitApi', "branches") + const branches = await plugin.call('dgitApi', 'branches') dispatch(setBranches(branches)); + await showCurrentBranch(); } export const getRemotes = async () => { - const remotes: remote[] = await plugin.call('dgitApi', "remotes"); + const remotes: remote[] = await plugin.call('dgitApi', 'remotes'); dispatch(setRemotes(remotes)); } @@ -63,6 +65,7 @@ export const setUpstreamRemote = async (remote: remote) => { } export const getFileStatusMatrix = async (filepaths: string[]) => { + dispatch(setLoading(true)) const fileStatusResult = await statusMatrix(filepaths); fileStatusResult.map((m) => { @@ -78,16 +81,17 @@ export const getFileStatusMatrix = async (filepaths: string[]) => { dispatch(fileStatusMerge(fileStatusResult)) setFileDecorators(fileStatusResult) } + dispatch(setLoading(false)) } -export const getCommits = async () => { +export const getCommits = async (depth: number) => { try { const commits: ReadCommitResult[] = await plugin.call( 'dgitApi', "log", - { ref: "HEAD" } + { ref: "HEAD", depth: depth } ); return commits; @@ -96,16 +100,21 @@ export const getCommits = async () => { } } -export const gitlog = async () => { +export const gitlog = async (depth: number) => { dispatch(setLoading(true)) let commits = [] try { - commits = await getCommits() + commits = await getCommits(depth) } catch (e) { } dispatch(setCommits(commits)) await showCurrentBranch() dispatch(setLoading(false)) + +} + +export const setStateGitLogCount = async (count: number) => { + dispatch(setGitLogCount(count)) } export const showCurrentBranch = async () => { @@ -228,7 +237,7 @@ export const addall = async (files: fileStatusResult[]) => { } } -export const add = async (filepath: addInput) => { +export const add = async (filepath: addInputType) => { await sendToMatomo(gitMatomoEventTypes.ADD) try { if (typeof filepath.filepath === "string") { @@ -255,7 +264,7 @@ const getLastCommmit = async () => { } } -export const rm = async (args: rmInput) => { +export const rm = async (args: rmInputType) => { await sendToMatomo(gitMatomoEventTypes.RM) await plugin.call('dgitApi', 'rm', { filepath: removeSlash(args.filepath), @@ -292,7 +301,7 @@ export const checkoutfile = async (filename: string) => { } } -export const checkout = async (cmd: checkoutInput) => { +export const checkout = async (cmd: checkoutInputType) => { sendToMatomo(gitMatomoEventTypes.CHECKOUT) await disableCallBacks(); await plugin.call('fileManager', 'closeAllFiles') @@ -342,7 +351,7 @@ export const fetch = async (input: fetchInputType) => { try { await plugin.call('dgitApi', 'fetch', input); if (!input.quiet) { - await gitlog() + dispatch(setTimestamp(Date.now())) await getBranches() } } catch (e: any) { @@ -359,7 +368,7 @@ export const pull = async (input: pullInputType) => { await disableCallBacks() try { await plugin.call('dgitApi', 'pull', input) - await gitlog() + dispatch(setTimestamp(Date.now())) } catch (e: any) { console.log(e) await parseError(e) @@ -393,6 +402,8 @@ const tokenWarning = async () => { const parseError = async (e: any) => { console.trace(e) + if (!e.message) return + // if message conttains 401 Unauthorized, show token warning if (e.message.includes('401')) { await sendToMatomo(gitMatomoEventTypes.ERROR, ['401']) @@ -522,6 +533,7 @@ export const remoteBranches = async (owner: string, repo: string) => { } export const remoteCommits = async (url: string, branch: string, length: number) => { + const urlParts = url.split("/"); // check if it's github @@ -571,7 +583,9 @@ export const saveGitHubCredentials = async (credentials: { username: string, ema } dispatch(setGitHubUser({ login: credentials.username, + isConnected: false })) + appDispatcher({ type: appActionTypes.setGitHubUser, payload: { login: credentials.username, isConnected: false } }) dispatch(setUserEmails([{ email: credentials.email, primary: true, @@ -631,6 +645,7 @@ export const loadGitHubUserFromToken = async () => { if (data.user && data.user.login && (storedUsername !== data.user.login)) await plugin.call('config', 'setAppParameter', 'settings/github-user-name', data.user.login) dispatch(setGitHubUser(data.user)) + appDispatcher({ type: appActionTypes.setGitHubUser, payload: data.user }) dispatch(setScopes(data.scopes)) dispatch(setUserEmails(data.emails)) sendToGitLog({ @@ -646,6 +661,7 @@ export const loadGitHubUserFromToken = async () => { message: `Please check your GitHub token in the GitHub settings.` }) dispatch(setGitHubUser(null)) + appDispatcher({ type: appActionTypes.setGitHubUser, payload: null }) return false } } else { @@ -654,6 +670,7 @@ export const loadGitHubUserFromToken = async () => { message: `Please check your GitHub token in the GitHub settings.` }) dispatch(setGitHubUser(null)) + appDispatcher({ type: appActionTypes.setGitHubUser, payload: null }) return false } } catch (e) { @@ -663,7 +680,9 @@ export const loadGitHubUserFromToken = async () => { } export const statusMatrix = async (filepaths: string[]) => { + const matrix = await plugin.call('dgitApi', 'status', { ref: "HEAD", filepaths: filepaths || ['.']}); + const result = (matrix || []).map((x) => { return { filename: `/${x.shift()}`, @@ -726,6 +745,7 @@ export const diff = async (commitChange: commitChange) => { } export const getCommitChanges = async (oid1: string, oid2: string, branch?: branch, remote?: remote) => { + try { let log try { @@ -738,6 +758,7 @@ export const getCommitChanges = async (oid1: string, oid2: string, branch?: bran console.log(e, 'log error') } if (log) { + const foundCommit = log.find((commit: ReadCommitResult) => commit.oid === oid2) if (!foundCommit && remote) { @@ -774,6 +795,7 @@ async function getRepoDetails(url: string) { } export const fetchBranch = async (branch: branch, page: number) => { + if (!branch.remote || !branch.remote.url) return const token = await tokenWarning(); if (page == 1) { @@ -793,6 +815,7 @@ export const fetchBranch = async (branch: branch, page: number) => { } export const getBranchDifferences = async (branch: branch, remote: remote, state: gitState) => { + if (!remote && state) { if (state.defaultRemote) { remote = state.defaultRemote diff --git a/libs/remix-ui/git/src/lib/listeners.ts b/libs/remix-ui/git/src/lib/listeners.ts index a873b303f7..42f450c058 100644 --- a/libs/remix-ui/git/src/lib/listeners.ts +++ b/libs/remix-ui/git/src/lib/listeners.ts @@ -1,12 +1,14 @@ import React from "react"; -import { setCanUseApp, setLoading, setRepoName, setGItHubToken, setLog, setGitHubUser, setUserEmails } from "../state/gitpayload"; +import { setCanUseApp, setLoading, setRepoName, setGItHubToken, setLog, setGitHubUser, setUserEmails, setTimestamp, setDesktopWorkingDir, setVersion } from "../state/gitpayload"; import { gitActionDispatch, gitUIPanels, storage } from "../types"; import { Plugin } from "@remixproject/engine"; import { getBranches, getFileStatusMatrix, loadGitHubUserFromToken, getRemotes, gitlog, setPlugin, setStorage } from "./gitactions"; import { Profile } from "@remixproject/plugin-utils"; import { CustomRemixApi } from "@remix-api"; import { statusChanged } from "./pluginActions"; +import { appPlatformTypes } from "@remix-ui/app"; +import { AppAction } from "@remix-ui/app"; let plugin: Plugin, gitDispatch: React.Dispatch, loaderDispatch: React.Dispatch, loadFileQueue: AsyncDebouncedQueue let callBackEnabled: boolean = false @@ -34,13 +36,13 @@ class AsyncDebouncedQueue { } } -export const setCallBacks = (viewPlugin: Plugin, gitDispatcher: React.Dispatch, loaderDispatcher: React.Dispatch, setAtivePanel: React.Dispatch>) => { +export const setCallBacks = (viewPlugin: Plugin, gitDispatcher: React.Dispatch, appDispatcher: React.Dispatch, loaderDispatcher: React.Dispatch, setAtivePanel: React.Dispatch>, platform: appPlatformTypes) => { plugin = viewPlugin gitDispatch = gitDispatcher loaderDispatch = loaderDispatcher loadFileQueue = new AsyncDebouncedQueue() - setPlugin(viewPlugin, gitDispatcher) + setPlugin(viewPlugin, gitDispatcher, appDispatcher) plugin.on("fileManager", "fileSaved", async (file: string) => { loadFileQueue.enqueue(async () => { @@ -66,13 +68,44 @@ export const setCallBacks = (viewPlugin: Plugin, gitDispatcher: React.Dispatch { + + gitDispatcher(setDesktopWorkingDir(path)) + gitDispatch(setCanUseApp(path ? true : false)) + const version = await plugin.call('dgitApi', 'version') + + gitDispatch(setVersion(version)) + loadFileQueue.enqueue(async () => { + loadFiles() + }) + loadFileQueue.enqueue(async () => { + gitDispatch(setTimestamp(Date.now())) + }) + loadFileQueue.enqueue(async () => { + getBranches() + }) + loadFileQueue.enqueue(async () => { + getRemotes() + }) + }) + plugin.on("filePanel", "setWorkspace", async (x: any) => { - gitDispatch(setCanUseApp(x && !x.isLocalhost && x.name)) + + if (platform == appPlatformTypes.desktop) { + const workingDir = await plugin.call('fs', 'getWorkingDir') + gitDispatch(setCanUseApp(workingDir? true : false)) + const version = await plugin.call('dgitApi', 'version') + + gitDispatch(setVersion(version)) + } else { + gitDispatch(setCanUseApp(x && !x.isLocalhost && x.name)) + } + loadFileQueue.enqueue(async () => { loadFiles() }) loadFileQueue.enqueue(async () => { - gitlog() + gitDispatch(setTimestamp(Date.now())) }) loadFileQueue.enqueue(async () => { getBranches() @@ -84,7 +117,7 @@ export const setCallBacks = (viewPlugin: Plugin, gitDispatcher: React.Dispatch { loadFileQueue.enqueue(async () => { - gitlog() + gitDispatch(setTimestamp(Date.now())) }) loadFileQueue.enqueue(async () => { getBranches() @@ -110,8 +143,12 @@ export const setCallBacks = (viewPlugin: Plugin, gitDispatcher: React.Dispatch { + + loadFileQueue.enqueue(async () => { + loadFiles() + }, 10) loadFileQueue.enqueue(async () => { - gitlog() + gitDispatch(setTimestamp(Date.now())) }, 10) loadFileQueue.enqueue(async () => { getBranches() @@ -123,7 +160,7 @@ export const setCallBacks = (viewPlugin: Plugin, gitDispatcher: React.Dispatch { loadFileQueue.enqueue(async () => { - gitlog() + gitDispatch(setTimestamp(Date.now())) }) loadFileQueue.enqueue(async () => { getBranches() @@ -145,7 +182,7 @@ export const setCallBacks = (viewPlugin: Plugin, gitDispatcher: React.Dispatch { - gitlog() + gitDispatch(setTimestamp(Date.now())) }) }) plugin.on('manager', 'pluginActivated', async (p: Profile) => { diff --git a/libs/remix-ui/git/src/lib/pluginActions.ts b/libs/remix-ui/git/src/lib/pluginActions.ts index 7d9e81ee7a..d1c7a8854a 100644 --- a/libs/remix-ui/git/src/lib/pluginActions.ts +++ b/libs/remix-ui/git/src/lib/pluginActions.ts @@ -1,9 +1,10 @@ -import { commitChange, fileStatusResult, gitActionDispatch, gitMatomoEventTypes, gitState } from "../types" +import { fileStatusResult, gitActionDispatch, gitState } from "../types" +import { gitMatomoEventTypes } from "../types" import { fileDecoration, fileDecorationType } from "@remix-ui/file-decorators" import { removeSlash } from "../utils" import { getFilesByStatus } from "./fileHelpers" -import { CustomRemixApi } from "@remix-api"; +import { commitChange, CustomRemixApi } from "@remix-api"; import { Plugin } from "@remixproject/engine"; let plugin: Plugin, gitDispatch: React.Dispatch, loaderDispatch: React.Dispatch @@ -98,6 +99,13 @@ export const clearFileDecorator = async(path: string) => { await plugin.call('fileDecorator', 'clearFileDecorators', path) } +export const openFolderInSameWindow = async (path: string) => { + await plugin.call('fs', 'openFolderInSameWindow', path) +} + +export const openCloneDialog = async () => { + plugin.call('filePanel', 'clone') +} export const sendToMatomo = async (event: gitMatomoEventTypes, args?: string[]) => { const trackArgs = args ? ['trackEvent', 'git', event, ...args] : ['trackEvent', 'git', event]; plugin && await plugin.call('matomo', 'track', trackArgs); diff --git a/libs/remix-ui/git/src/state/actions.ts b/libs/remix-ui/git/src/state/actions.ts index 6aa8b95bff..4cd9de59e0 100644 --- a/libs/remix-ui/git/src/state/actions.ts +++ b/libs/remix-ui/git/src/state/actions.ts @@ -1,5 +1,7 @@ import { ReadCommitResult } from "isomorphic-git" -import { branch, branchDifference, commitChange, fileStatusResult, GitHubUser, gitLog, pagedCommits, remote, remoteBranch, repository, storage, userEmails } from "../types" +import { fileStatusResult, gitLog } from "../types" +import { GitHubUser, branch, branchDifference, commitChange, pagedCommits, remote, remoteBranch, repository, userEmails } from '@remix-api' +import { storage } from "../types" export interface ActionPayloadTypes { FILE_STATUS: fileStatusResult[], @@ -43,7 +45,11 @@ export interface ActionPayloadTypes { SET_LOG: gitLog CLEAR_LOG: void SET_USER_EMAILS: userEmails + DESKTOP_SET_WORKING_DIR: string + SET_VERSION: string SET_STORAGE: storage + SET_TIMESTAMP: number + SET_GIT_LOG_COUNT: number } export interface Action { diff --git a/libs/remix-ui/git/src/state/context.tsx b/libs/remix-ui/git/src/state/context.tsx index 4608406a7f..ff59a40d91 100644 --- a/libs/remix-ui/git/src/state/context.tsx +++ b/libs/remix-ui/git/src/state/context.tsx @@ -1,12 +1,13 @@ +import { branch, addInputType, checkoutInputType, cloneInputType, commitChange, fetchInputType, pullInputType, pushInputType, remote, rmInputType } from "@remix-api" import { ReadCommitResult } from "isomorphic-git" import React from "react" -import { addInput, branch, checkoutInput, cloneInputType, commitChange, fetchInputType, fileStatusResult, gitLog, gitState, pullInputType, pushInputType, remote, rmInput } from "../types" +import { fileStatusResult, gitLog, gitState } from "../types" export interface gitActions { removeRemote(remote: remote): void clone(input: cloneInputType): Promise - add(input: addInput): Promise - rm(input: rmInput): Promise + add(input: addInputType): Promise + rm(input: rmInputType): Promise commit(message: string): Promise addall(files: fileStatusResult[]): Promise push(input: pushInputType): Promise @@ -14,7 +15,7 @@ export interface gitActions { fetch(input: fetchInputType): Promise repositories(): Promise checkoutfile(file: string): Promise - checkout(input: checkoutInput): Promise + checkout(input: checkoutInputType): Promise createBranch(branch: string): Promise remoteBranches(owner: string, repo: string): Promise getCommitChanges(oid1: string, oid2: string, branch?: branch, remote?: remote): Promise @@ -31,8 +32,9 @@ export interface gitActions { sendToGitLog: (message: gitLog) => Promise clearGitLog: () => Promise getFileStatusMatrix(filespaths:[]): Promise - gitlog(): Promise + gitlog(depth: number): Promise init(): Promise + setStateGitLogCount(count: number): Promise } export const gitActionsContext = React.createContext(null) @@ -54,6 +56,7 @@ export interface pluginActions { token: string }> showAlert({ title, message }:{title: string, message: string}): Promise + openFolderInSameWindow(path: string): Promise } export const pluginActionsContext = React.createContext(null) \ No newline at end of file diff --git a/libs/remix-ui/git/src/state/gitpayload.ts b/libs/remix-ui/git/src/state/gitpayload.ts index 1c93a40a90..36fc1f837d 100644 --- a/libs/remix-ui/git/src/state/gitpayload.ts +++ b/libs/remix-ui/git/src/state/gitpayload.ts @@ -1,5 +1,7 @@ import { ReadCommitResult } from "isomorphic-git" -import { GitHubUser, branch, commitChange, fileStatusResult, remote, pagedCommits, branchDifference, gitLog, repository, userEmails, storage } from "../types" +import { fileStatusResult, gitLog } from "../types" +import { repository, pagedCommits, branch, remote, commitChange, branchDifference, GitHubUser, userEmails } from "@remix-api" +import { storage } from "../types" import { Endpoints } from "@octokit/types" export const fileStatus = (files: fileStatusResult[]) => { @@ -225,9 +227,36 @@ export const clearLog = () => { } } +export const setDesktopWorkingDir = (dir: string) => { + return { + type: 'DESKTOP_SET_WORKING_DIR', + payload: dir + } +} + +export const setVersion = (version: string) => { + return { + type: 'SET_VERSION', + payload: version + } +} export const setStoragePayload = (storage: storage) => { return { type: 'SET_STORAGE', payload: storage } } + +export const setTimestamp = (timestamp: number) => { + return { + type: 'SET_TIMESTAMP', + payload: timestamp + } +} + +export const setGitLogCount = (count: number) => { + return { + type: 'SET_GIT_LOG_COUNT', + payload: count + } +} diff --git a/libs/remix-ui/git/src/state/gitreducer.tsx b/libs/remix-ui/git/src/state/gitreducer.tsx index 592360a94a..65ab5e57a8 100644 --- a/libs/remix-ui/git/src/state/gitreducer.tsx +++ b/libs/remix-ui/git/src/state/gitreducer.tsx @@ -1,6 +1,6 @@ -import { ReadCommitResult } from "isomorphic-git" -import { allChangedButNotStagedFiles, getFilesByStatus, getFilesWithNotModifiedStatus } from "../lib/fileHelpers" -import { branch, commitChange, defaultGitState, fileStatusResult, gitState, setRemoteBranchCommitsAction, setLocalBranchCommitsAction, setBranchDifferencesAction, setDefaultRemoteAction, setRemotesAction, setUpstreamAction } from "../types" +import { commitChange } from "@remix-api" +import { allChangedButNotStagedFiles, getFilesByStatus } from "../lib/fileHelpers" +import { defaultGitState, fileStatusResult, gitState } from "../types" import { Actions } from "./actions" export const gitReducer = (state: gitState = defaultGitState, action: Actions): gitState => { @@ -210,11 +210,33 @@ export const gitReducer = (state: gitState = defaultGitState, action: Actions): log: [] } + case 'DESKTOP_SET_WORKING_DIR': + return { + ...state, + desktopWorkingDir: action.payload + } + + case 'SET_VERSION': + return { + ...state, + version: action.payload + } case 'SET_STORAGE': return { ...state, storage: action.payload } + case 'SET_TIMESTAMP': + return { + ...state, + timestamp: action.payload + } + case 'SET_GIT_LOG_COUNT': + return { + ...state, + gitLogCount: action.payload + } } + } diff --git a/libs/remix-ui/git/src/types/index.ts b/libs/remix-ui/git/src/types/index.ts index 31e34db978..f87ee222f8 100644 --- a/libs/remix-ui/git/src/types/index.ts +++ b/libs/remix-ui/git/src/types/index.ts @@ -1,155 +1,12 @@ import { Endpoints } from "@octokit/types" -import { IRemixApi } from "@remixproject/plugin-api" -import { LibraryProfile, StatusEvents } from "@remixproject/plugin-utils" -import { CommitObject, ReadBlobResult, ReadCommitResult, StatusRow } from "isomorphic-git" -export type GitHubUser = Partial -export type userEmails = Endpoints["GET /user/emails"]["response"]["data"] - -export interface IGitApi { - events: { - "checkout": () => void - "clone": () => void - "add": () => void - "rm": () => void - "commit": () => void - "branch": () => void - "init": () => void - } & StatusEvents, - methods: { - getCommitChanges(oid1: string, oid2: string): Promise - repositories(input: repositoriesInput): Promise - clone(input: cloneInputType): Promise - branches(input?: branchesInput): Promise, - remotes(): Promise, - log(cmd: { ref: string }): Promise, - remotecommits(input: remoteCommitsInputType): Promise - fetch(input: fetchInputType): Promise - pull(input: pullInputType): Promise - push(input: pushInputType): Promise - currentbranch(input?: currentBranchInput): Promise - branch(input: branchInputType): Promise - checkout(input: checkoutInput): Promise - add(input: addInput): Promise - rm(input: rmInput): Promise - resolveref(input: resolveRefInput): Promise - readblob(input: readBlobInput): Promise - commit(input: commitInput): Promise - addremote(input: remote): Promise - delremote(input: remote): Promise - status(input?: statusInput): Promise> - compareBranches(input: compareBranchesInput): Promise - init(input?: initInput): Promise - updateSubmodules: (input: updateSubmodulesInput) => Promise - } -} - -export type initInput = { - defaultBranch: string -} - -export type updateSubmodulesInput = { - dir?: string - token?: string -} - -export type remoteCommitsInputType = { - owner: string, repo: string, token: string, branch: string, length: number, page: number -} - -export type compareBranchesInput = { - branch: branch, remote: remote -} - -export type fetchInputType = { - remote: remote, - ref?: branch, - remoteRef?: branch, - depth?: number, - singleBranch?: boolean, - relative?: boolean, - quiet?: boolean -} - -export type pullInputType = { - remote: remote, ref: branch, remoteRef?: branch -} - -export type pushInputType = { - remote: remote, ref: branch, remoteRef?: branch, force?: boolean -} - -export type branchInputType = { - ref: string, - checkout?: boolean - refresh?: boolean - force?: boolean -} - -export type currentBranchInput = { - fs: any, - dir: string -} - -export type checkoutInput = { - ref: string, - force?: boolean, - remote?: string - refresh?: boolean - fetch?: boolean -} - -export type addInput = { - filepath: string | string[] -} - -export type rmInput = { - filepath: string -} - -export type resolveRefInput = { - ref: string -} - -export type readBlobInput = { - oid: string, - filepath: string -} - -export type commitInput = { - author: { - name: string, - email: string, - }, - message: string, -} - -export type branchesInput = { - fs?: any - dir?: string -} - -export interface cloneInputType { - url: string, - branch?: string, - depth?: number, - singleBranch?: boolean - workspaceName?: string - workspaceExists?: boolean - token?: string -} +import { GitHubUser, branch, branchDifference, commitChange, pagedCommits, remote, remoteBranch, repository, syncStatus, userEmails } from "@remix-api" +import { ReadCommitResult } from "isomorphic-git" +import { Plugin } from "@remixproject/engine"; +import { CustomRemixApi } from "@remix-api" -export interface repositoriesInput { token: string, page?: number, per_page?: number } - -export interface statusInput { ref: string, filepaths?: string[] } - -export const dGitProfile: LibraryProfile = { - name: 'dgitApi', - methods: ['clone', 'branches', 'remotes', 'getCommitChanges', 'log', 'remotecommits'], -} - -export interface customGitApi extends IRemixApi { - dgit: IGitApi -} +export interface IGitUi { + plugin: Plugin + } export type gitState = { currentBranch: branch @@ -185,6 +42,10 @@ export type gitState = { gitHubScopes: string[] gitHubAccessToken: string log: gitLog[] + desktopWorkingDir?: string + version: string + timestamp: number + gitLogCount: number } export type gitLog = { type: 'error' | 'warning' | 'info' | 'success', @@ -193,19 +54,6 @@ export type gitLog = { export type remoteBranchIdentifier = `${string}/${string}` -export type branchDifference = { - uniqueHeadCommits: ReadCommitResult[], - uniqueRemoteCommits: ReadCommitResult[], -} - -export type pagedCommits = { - page: number, - perPage: number, - total: number, - hasNextPage: boolean, - commits: ReadCommitResult[] -} - export type loaderState = { branches: boolean remotes: boolean @@ -214,57 +62,6 @@ export type loaderState = { plugin: boolean } -export type commitChangeTypes = { - "deleted": "D" - "modified": "M" - "added": "A", - "unknown": "?" -} - -export enum syncStatus { - "sync" = "sync", - "publishBranch" = "publishBranch", - "none" = "none", -} - -export type commitChangeType = keyof commitChangeTypes - -export type commitChange = { - type: commitChangeType - path: string, - hashModified: string, - hashOriginal: string, - original?: string, - modified?: string, - readonly?: boolean -} - -export type repository = { - name: string - html_url: string - owner: { - login: string - }, - full_name: string - default_branch: string - id: number - url: string -} - -export type branch = { - name: string - remote: remote -} - -export type remote = { - name: string - url: string -} - -export type remoteBranch = { - name: string -} - export const defaultGitState: gitState = { currentBranch: { name: "", remote: { name: "", url: "" } }, currentHead: "", @@ -280,7 +77,7 @@ export const defaultGitState: gitState = { deleted: [], modified: [], allchangesnotstaged: [], - canUseApp: true, + canUseApp: false, loading: false, storage: { used: 0, @@ -304,7 +101,11 @@ export const defaultGitState: gitState = { userEmails: [] as userEmails, gitHubScopes: [], gitHubAccessToken: "", - log: [] + log: [], + desktopWorkingDir: null, + version: "", + timestamp: 0, + gitLogCount: 22 } export const defaultLoaderState: loaderState = { @@ -494,4 +295,14 @@ export interface clearLogAction { type: string } -export type gitActionDispatch = setCurrentHeadAction | clearLogAction | setLogAction | setDefaultRemoteAction | setTokenAction | setUpstreamAction | setRemoteBranchCommitsAction | setLocalBranchCommitsAction | setBranchDifferencesAction | setRemotesAction | setCurrentBranchAction | fileStatusAction | setLoadingAction | setCanUseAppAction | setRepoNameAction | setCommitsAction | setBranchesAction | setReposAction | setRemoteBranchesAction \ No newline at end of file +export interface setDesktopWorkingDirAction { + type: string, + payload: string +} + +export interface setTimeStampAction { + type: string, + payload: number +} + +export type gitActionDispatch = setTimeStampAction |setDesktopWorkingDirAction | setCurrentHeadAction | clearLogAction | setLogAction | setDefaultRemoteAction | setTokenAction | setUpstreamAction | setRemoteBranchCommitsAction | setLocalBranchCommitsAction | setBranchDifferencesAction | setRemotesAction | setCurrentBranchAction | fileStatusAction | setLoadingAction | setCanUseAppAction | setRepoNameAction | setCommitsAction | setBranchesAction | setReposAction | setRemoteBranchesAction diff --git a/libs/remix-ui/grid-view/src/lib/remix-ui-grid-cell.tsx b/libs/remix-ui/grid-view/src/lib/remix-ui-grid-cell.tsx index 3055d0d4e7..96deee2398 100644 --- a/libs/remix-ui/grid-view/src/lib/remix-ui-grid-cell.tsx +++ b/libs/remix-ui/grid-view/src/lib/remix-ui-grid-cell.tsx @@ -47,7 +47,7 @@ export const RemixUIGridCell = (props: RemixUIGridCellProps) => { // check for filter if (filterCon.filter != '') enabled = (props.title?.toLowerCase().includes(filterCon.filter?.toLowerCase()) || - props.searchKeywords?.map(keyword => keyword.toLowerCase()).some(searchKeyword => searchKeyword.toLowerCase().includes(filterCon.filter.toLocaleLowerCase()))) + props.searchKeywords?.map(keyword => keyword?.toLowerCase()).some(searchKeyword => searchKeyword?.toLowerCase().includes(filterCon.filter?.toLocaleLowerCase()))) setAnyEnabled(enabled) }, [filterCon, props.tagList]) diff --git a/libs/remix-ui/grid-view/src/lib/remix-ui-grid-section.css b/libs/remix-ui/grid-view/src/lib/remix-ui-grid-section.css index 5c79533a71..50588fc36b 100644 --- a/libs/remix-ui/grid-view/src/lib/remix-ui-grid-section.css +++ b/libs/remix-ui/grid-view/src/lib/remix-ui-grid-section.css @@ -21,6 +21,6 @@ } * { - scrollbar-width: thin; + scrollbar-width: 0.5rem; scrollbar-color: var(--bg-dark) var(--bg-light); -} \ No newline at end of file +} diff --git a/libs/remix-ui/grid-view/src/lib/remix-ui-grid-section.tsx b/libs/remix-ui/grid-view/src/lib/remix-ui-grid-section.tsx index a3cb8b15c0..33fb25fb48 100644 --- a/libs/remix-ui/grid-view/src/lib/remix-ui-grid-section.tsx +++ b/libs/remix-ui/grid-view/src/lib/remix-ui-grid-section.tsx @@ -1,4 +1,5 @@ import React, {useState, useEffect, useContext, useRef, ReactNode} from 'react' // eslint-disable-line +import { CustomTooltip } from "@remix-ui/helper"; import './remix-ui-grid-section.css' import FiltersContext from "./filtersContext" @@ -13,6 +14,7 @@ const _paq = window._paq = window._paq || [] interface RemixUIGridSectionProps { plugin: any title?: string + tooltipTitle?: string hScrollable: boolean classList?: string styleList?: any @@ -61,7 +63,7 @@ export const RemixUIGridSection = (props: RemixUIGridSectionProps) => { data-id={"remixUIGS" + props.title} style={{ overflowX: 'auto' }} > -
+
{ props.title &&
{ props.title }
}
{ !hasChildCell(children) && No items found } diff --git a/libs/remix-ui/home-tab/src/lib/components/homeTabFeatured.tsx b/libs/remix-ui/home-tab/src/lib/components/homeTabFeatured.tsx index da0bced867..30d99e2e8d 100644 --- a/libs/remix-ui/home-tab/src/lib/components/homeTabFeatured.tsx +++ b/libs/remix-ui/home-tab/src/lib/components/homeTabFeatured.tsx @@ -7,8 +7,11 @@ import 'react-multi-carousel/lib/styles.css' import * as releaseDetails from './../../../../../../releaseDetails.json' const _paq = (window._paq = window._paq || []) // eslint-disable-line +export type HomeTabFeaturedProps = { + plugin: any + } -function HomeTabFeatured() { +function HomeTabFeatured(props:HomeTabFeaturedProps) { const themeFilter = useContext(ThemeContext) return ( @@ -64,23 +67,27 @@ function HomeTabFeatured() {
diff --git a/libs/remix-ui/home-tab/src/lib/components/homeTabFeaturedPlugins.tsx b/libs/remix-ui/home-tab/src/lib/components/homeTabFeaturedPlugins.tsx index 017caea368..10cf7d82bc 100644 --- a/libs/remix-ui/home-tab/src/lib/components/homeTabFeaturedPlugins.tsx +++ b/libs/remix-ui/home-tab/src/lib/components/homeTabFeaturedPlugins.tsx @@ -67,10 +67,10 @@ function HomeTabFeaturedPlugins({ plugin }: HomeTabFeaturedPluginsProps) { plugin.verticalIcons.select('solidityStaticAnalysis') _paq.push(['trackEvent', 'hometabActivate', 'userActivate', 'solidityStaticAnalysis']) } - const startSourceVerify = async () => { - await plugin.appManager.activatePlugin(['solidity', 'sourcify']) - plugin.verticalIcons.select('sourcify') - _paq.push(['trackEvent', 'hometabActivate', 'userActivate', 'sourcify']) + const startLearnEth = async () => { + await plugin.appManager.activatePlugin(['LearnEth', 'solidity', 'solidityUnitTesting']) + plugin.verticalIcons.select('LearnEth') + _paq.push(['trackEvent', 'hometabActivate', 'userActivate', 'LearnEth']) } const startCookbook = async () => { await plugin.appManager.activatePlugin(['cookbookdev']) @@ -109,7 +109,7 @@ function HomeTabFeaturedPlugins({ plugin }: HomeTabFeaturedPluginsProps) { } }} renderButtonGroupOutside={true} - ssr={true} // means to render carousel on server-side. + ssr={false} // means to render carousel on server-side. keyBoardControl={true} containerClass="carousel-container" deviceType={'desktop'} @@ -125,6 +125,16 @@ function HomeTabFeaturedPlugins({ plugin }: HomeTabFeaturedPluginsProps) { remixMaintained={true} callback={() => startCodeAnalyzer()} /> + startLearnEth()} + /> startSolidity()} /> - startSourceVerify()} - /> {
- +
diff --git a/libs/remix-ui/run-tab/src/lib/actions/deploy.ts b/libs/remix-ui/run-tab/src/lib/actions/deploy.ts index a1375b473d..8103a4e832 100644 --- a/libs/remix-ui/run-tab/src/lib/actions/deploy.ts +++ b/libs/remix-ui/run-tab/src/lib/actions/deploy.ts @@ -9,7 +9,7 @@ import { DeployMode, MainnetPrompt } from "../types" import { displayNotification, fetchProxyDeploymentsSuccess, setDecodedResponse, updateInstancesBalance } from "./payload" import { addInstance } from "./actions" import { addressToString, logBuilder } from "@remix-ui/helper" -import Web3 from "web3" +import { Web3 } from "web3" declare global { interface Window { diff --git a/libs/remix-ui/run-tab/src/lib/actions/events.ts b/libs/remix-ui/run-tab/src/lib/actions/events.ts index 41deac6c6f..8d13ac5776 100644 --- a/libs/remix-ui/run-tab/src/lib/actions/events.ts +++ b/libs/remix-ui/run-tab/src/lib/actions/events.ts @@ -6,7 +6,7 @@ import { addDeployOption, clearAllInstances, clearAllPinnedInstances, clearRecor import { updateInstanceBalance } from './deploy' import { CompilerAbstract } from '@remix-project/remix-solidity' import BN from 'bn.js' -import Web3 from 'web3' +import { Web3 } from 'web3' import { Plugin } from "@remixproject/engine" import { getNetworkProxyAddresses } from "./deploy" import { shortenAddress } from "@remix-ui/helper" diff --git a/libs/remix-ui/run-tab/src/lib/components/environment.tsx b/libs/remix-ui/run-tab/src/lib/components/environment.tsx index d499b9c917..4f6c2964ae 100644 --- a/libs/remix-ui/run-tab/src/lib/components/environment.tsx +++ b/libs/remix-ui/run-tab/src/lib/components/environment.tsx @@ -23,7 +23,7 @@ export function EnvironmentUI(props: EnvironmentProps) { 'L2 - Arbitrum': 'https://bridge.arbitrum.io/' } - const isL2 = (providerDisplayName: string) => providerDisplayName === 'L2 - Optimism' || providerDisplayName === 'L2 - Arbitrum' + const isL2 = (providerDisplayName: string) => providerDisplayName && (providerDisplayName.startsWith('L2 - Optimism') || providerDisplayName.startsWith('L2 - Arbitrum')) return (
@@ -298,11 +303,14 @@ export const RemixUiSettings = (props: RemixUiSettingsProps) => {
@@ -311,7 +319,7 @@ export const RemixUiSettings = (props: RemixUiSettingsProps) => { - + {' '} {' '} @@ -319,6 +327,13 @@ export const RemixUiSettings = (props: RemixUiSettingsProps) => { Matomo + + +
diff --git a/libs/remix-ui/solidity-compiler/src/lib/logic/compileTabLogic.ts b/libs/remix-ui/solidity-compiler/src/lib/logic/compileTabLogic.ts index 49aad01d31..2b3b6e0000 100644 --- a/libs/remix-ui/solidity-compiler/src/lib/logic/compileTabLogic.ts +++ b/libs/remix-ui/solidity-compiler/src/lib/logic/compileTabLogic.ts @@ -129,26 +129,26 @@ export class CompileTabLogic { } async isHardhatProject () { - if (this.api.getFileManagerMode() === 'localhost') { + if (this.api.getFileManagerMode() === ('localhost') || this.api.isDesktop()) { return await this.api.fileExists('hardhat.config.js') || await this.api.fileExists('hardhat.config.ts') } else return false } async isTruffleProject () { - if (this.api.getFileManagerMode() === 'localhost') { + if (this.api.getFileManagerMode() === ('localhost') || this.api.isDesktop()) { return await this.api.fileExists('truffle-config.js') } else return false } async isFoundryProject () { - if (this.api.getFileManagerMode() === 'localhost') { + if (this.api.getFileManagerMode() === ('localhost') || this.api.isDesktop()) { return await this.api.fileExists('foundry.toml') } else return false } runCompiler (externalCompType) { try { - if (this.api.getFileManagerMode() === 'localhost') { + if (this.api.getFileManagerMode() === 'localhost' || this.api.isDesktop()) { if (externalCompType === 'hardhat') { const { currentVersion, optimize, runs } = this.compiler.state if (currentVersion) { diff --git a/libs/remix-ui/solidity-compiler/src/lib/solidity-compiler.tsx b/libs/remix-ui/solidity-compiler/src/lib/solidity-compiler.tsx index 46f13d3047..4d6f5773d6 100644 --- a/libs/remix-ui/solidity-compiler/src/lib/solidity-compiler.tsx +++ b/libs/remix-ui/solidity-compiler/src/lib/solidity-compiler.tsx @@ -1,4 +1,4 @@ -import React, { useEffect, useState } from 'react' // eslint-disable-line +import React, { useContext, useEffect, useState } from 'react' // eslint-disable-line import { CompileErrors, ContractsFile, SolidityCompilerProps } from './types' import { CompilerContainer } from './compiler-container' // eslint-disable-line import { ContractSelection } from './contract-selection' // eslint-disable-line @@ -9,6 +9,7 @@ import { baseURLBin, baseURLWasm, pathToURL } from '@remix-project/remix-solidit import * as packageJson from '../../../../../package.json' import './css/style.css' import { iSolJsonBinData, iSolJsonBinDataBuild } from '@remix-project/remix-lib' +import { appPlatformTypes, platformContext } from '@remix-ui/app' export const SolidityCompiler = (props: SolidityCompilerProps) => { const { @@ -47,6 +48,7 @@ export const SolidityCompiler = (props: SolidityCompilerProps) => { const [compileErrors, setCompileErrors] = useState>({ [currentFile]: api.compileErrors }) const [badgeStatus, setBadgeStatus] = useState>({}) const [contractsFile, setContractsFile] = useState({}) + const platform = useContext(platformContext) useEffect(() => { ; (async () => { @@ -77,9 +79,12 @@ export const SolidityCompiler = (props: SolidityCompilerProps) => { } api.onSetWorkspace = async (isLocalhost: boolean, workspaceName: string) => { - const isHardhat = isLocalhost && (await compileTabLogic.isHardhatProject()) - const isTruffle = isLocalhost && (await compileTabLogic.isTruffleProject()) - const isFoundry = isLocalhost && (await compileTabLogic.isFoundryProject()) + const isDesktop = platform === appPlatformTypes.desktop + + const isHardhat = (isLocalhost || isDesktop) && (await compileTabLogic.isHardhatProject()) + const isTruffle = (isLocalhost || isDesktop) && (await compileTabLogic.isTruffleProject()) + const isFoundry = (isLocalhost || isDesktop) && (await compileTabLogic.isFoundryProject()) + setState((prevState) => { return { ...prevState, diff --git a/libs/remix-ui/statusbar/src/lib/components/aiStatus.tsx b/libs/remix-ui/statusbar/src/lib/components/aiStatus.tsx index 255602004f..fc6d774ce4 100644 --- a/libs/remix-ui/statusbar/src/lib/components/aiStatus.tsx +++ b/libs/remix-ui/statusbar/src/lib/components/aiStatus.tsx @@ -14,13 +14,11 @@ export default function AIStatus(props: AIStatusProps) { const [copilotActive, setCopilotActive] = useState(false) useEffect(() => { const run = async () => { - props.plugin.on('fileManager', 'currentFileChanged', async (isAiActive) => { - const aiActivate = await props.plugin.call('settings', 'get', 'settings/copilot/suggest/activate') - setCopilotActive(aiActivate) - }) + const aiActivate = await props.plugin.call('settings', 'get', 'settings/copilot/suggest/activate') + setCopilotActive(aiActivate) } run() - }, [props.plugin.isAiActive, props.isAiActive]) + }, []) useEffect(() => { const run = async () => { @@ -30,14 +28,14 @@ export default function AIStatus(props: AIStatusProps) { }) } run() - }, [props.plugin.isAiActive]) + }, [props.plugin.isAiActive, props.plugin.isAiActive]) return (
- {copilotActive === false ? 'Remix Copilot (disabled)' : 'Remix Copilot (enabled)'} + {copilotActive === false ? 'RemixAI Copilot (disabled)' : 'RemixAI Copilot (enabled)'}
diff --git a/libs/remix-ui/statusbar/src/lib/remixui-statusbar-panel.tsx b/libs/remix-ui/statusbar/src/lib/remixui-statusbar-panel.tsx index a807151029..de67337743 100644 --- a/libs/remix-ui/statusbar/src/lib/remixui-statusbar-panel.tsx +++ b/libs/remix-ui/statusbar/src/lib/remixui-statusbar-panel.tsx @@ -10,6 +10,7 @@ import { appPlatformTypes, platformContext } from '@remix-ui/app' import { StatusBar } from 'apps/remix-ide/src/app/components/status-bar' import { StatusBarContextProvider } from '../contexts/statusbarcontext' import DidYouKnow from './components/didYouKnow' +import { appPlatformTypes, platformContext } from '@remix-ui/app' export interface RemixUIStatusBarProps { statusBarPlugin: StatusBar @@ -21,6 +22,7 @@ export type ScamAlert = { } export function RemixUIStatusBar({ statusBarPlugin }: RemixUIStatusBarProps) { + const platform = useContext(platformContext) const [showScamDetails, setShowScamDetails] = useState(true) const [scamAlerts, setScamAlerts] = useState([]) const [gitBranchName, setGitBranchName] = useState('') @@ -70,7 +72,7 @@ export function RemixUIStatusBar({ statusBarPlugin }: RemixUIStatusBarProps) { return ( <> - {showScamDetails && ( + {(platform !== appPlatformTypes.desktop) && showScamDetails && ( @@ -88,9 +90,9 @@ export function RemixUIStatusBar({ statusBarPlugin }: RemixUIStatusBarProps) {
-
+ { (platform !== appPlatformTypes.desktop) &&
-
+
}
diff --git a/libs/remix-ui/workspace/src/lib/actions/workspace.ts b/libs/remix-ui/workspace/src/lib/actions/workspace.ts index 8bd5f120e5..dbd6ba738f 100644 --- a/libs/remix-ui/workspace/src/lib/actions/workspace.ts +++ b/libs/remix-ui/workspace/src/lib/actions/workspace.ts @@ -43,10 +43,11 @@ import { ROOT_PATH } from '../utils/constants' import { IndexedDBStorage } from '../../../../../../apps/remix-ide/src/app/files/filesystems/indexedDB' import { getUncommittedFiles } from '../utils/gitStatusFilter' import { AppModal, ModalTypes } from '@remix-ui/app' -import { branch, cloneInputType, IGitApi, gitUIPanels } from '@remix-ui/git' + +import { gitUIPanels } from '@remix-ui/git' import * as templates from '@remix-project/remix-ws-templates' import { Plugin } from "@remixproject/engine"; -import { CustomRemixApi } from '@remix-api' +import { CustomRemixApi, branch, cloneInputType } from '@remix-api' declare global { interface Window { @@ -220,7 +221,7 @@ export const populateWorkspace = async ( dispatch(cloneRepositorySuccess()) }).catch((e) => { dispatch(cloneRepositorySuccess()) - plugin.call('notification', 'toast', 'error adding template ' + e.message || e) + plugin.call('notification', 'toast', 'error adding template ' + (e.message || e)) }) }, 5000) } else if (!isEmpty && !(isGitRepo && createCommit)) await loadWorkspacePreset(workspaceTemplateName, opts) @@ -273,6 +274,7 @@ export const loadWorkspacePreset = async (template: WorkspaceTemplate = 'remixDe let content if (params.code) { + _paq.push(['trackEvent', 'workspace', 'template', 'code-template-code-param']) const hashed = bytesToHex(hash.keccakFromString(params.code)) path = 'contract-' + hashed.replace('0x', '').substring(0, 10) + (params.language && params.language.toLowerCase() === 'yul' ? '.yul' : '.sol') @@ -280,6 +282,7 @@ export const loadWorkspacePreset = async (template: WorkspaceTemplate = 'remixDe await workspaceProvider.set(path, content) } if (params.shareCode) { + _paq.push(['trackEvent', 'workspace', 'template', 'code-template-shareCode-param']) const host = '127.0.0.1' const port = 5001 const protocol = 'http' @@ -304,6 +307,7 @@ export const loadWorkspacePreset = async (template: WorkspaceTemplate = 'remixDe await workspaceProvider.set(path, content) } if (params.url) { + _paq.push(['trackEvent', 'workspace', 'template', 'code-template-url-param']) const data = await plugin.call('contentImport', 'resolve', params.url) path = data.cleanUrl content = data.content @@ -327,6 +331,7 @@ export const loadWorkspacePreset = async (template: WorkspaceTemplate = 'remixDe } if (params.ghfolder) { try { + _paq.push(['trackEvent', 'workspace', 'template', 'code-template-ghfolder-param']) const files = await plugin.call('contentImport', 'resolveGithubFolder', params.ghfolder) for (const [path, content] of Object.entries(files)) { await workspaceProvider.set(path, content) @@ -345,6 +350,7 @@ export const loadWorkspacePreset = async (template: WorkspaceTemplate = 'remixDe case 'gist-template': // creates a new workspace gist-sample and get the file from gist try { + _paq.push(['trackEvent', 'workspace', 'template', 'gist-template']) const gistId = params.gist const response: AxiosResponse = await axios.get(`https://api.github.com/gists/${gistId}`) const data = response.data as { files: any } diff --git a/libs/remix-ui/workspace/src/lib/components/createModal.tsx b/libs/remix-ui/workspace/src/lib/components/createModal.tsx new file mode 100644 index 0000000000..81b9d24a08 --- /dev/null +++ b/libs/remix-ui/workspace/src/lib/components/createModal.tsx @@ -0,0 +1,51 @@ +import React from 'react' +import { FormattedMessage } from 'react-intl' + +export const createModalMessage = async ( + defaultName: string, + gitConfigNotSet: boolean, + onChangeTemplateName: (name: string) => void, + onChangeInitGit: (name: string) => void) => { + + return ( + <> + + onChangeTemplateName(e.target.value)} + onInput={(e) => onChangeTemplateName((e.target as any).value)} + /> +
+ onChangeInitGit(e.target.value)} + onInput={(e) => onChangeInitGit((e.target as any).value)} + /> + +
+ {gitConfigNotSet ? ( +
+ +
+ ) : ( + <> + )} + + ) +} diff --git a/libs/remix-ui/workspace/src/lib/components/workspace-hamburger-item.tsx b/libs/remix-ui/workspace/src/lib/components/workspace-hamburger-item.tsx index 25622b3c9a..f5df61691a 100644 --- a/libs/remix-ui/workspace/src/lib/components/workspace-hamburger-item.tsx +++ b/libs/remix-ui/workspace/src/lib/components/workspace-hamburger-item.tsx @@ -32,7 +32,7 @@ export function HamburgerMenuItem(props: HamburgerMenuItemProps) { > - + {props.kind === 'create' ? :}
diff --git a/libs/remix-ui/workspace/src/lib/components/workspace-hamburger.tsx b/libs/remix-ui/workspace/src/lib/components/workspace-hamburger.tsx index 95de007539..860ac4042e 100644 --- a/libs/remix-ui/workspace/src/lib/components/workspace-hamburger.tsx +++ b/libs/remix-ui/workspace/src/lib/components/workspace-hamburger.tsx @@ -7,6 +7,7 @@ import { WorkspaceMetadata } from '../types' export interface HamburgerMenuProps { selectedWorkspace: WorkspaceMetadata createWorkspace: () => void + createBlankWorkspace: () => Promise renameCurrentWorkspace: () => void downloadCurrentWorkspace: () => void deleteCurrentWorkspace: () => void @@ -26,6 +27,16 @@ export function HamburgerMenu(props: HamburgerMenuProps) { const { showIconsMenu, hideWorkspaceOptions, hideLocalhostOptions, hideFileOperations, selectedWorkspace } = props return ( <> + { + props.createBlankWorkspace() + props.hideIconsMenu(!showIconsMenu) + }} + platforms={[appPlatformTypes.web]} + > ({ ctrlKey: false, cutShortcut: false, @@ -334,6 +337,26 @@ export function Workspace() { ) } + const [counter, setCounter] = useState(1) + const createBlankWorkspace = async () => { + const username = await global.plugin.call('settings', 'get', 'settings/github-user-name') + const email = await global.plugin.call('settings', 'get', 'settings/github-email') + const gitNotSet = !username || !email + const defaultName = await global.plugin.call('filePanel', 'getAvailableWorkspaceName', 'blank') + let workspace = defaultName + let gitInit = false + setCounter((previous) => { + return previous + 1 + }) + global.modal( + intl.formatMessage({ id: 'filePanel.workspace.createBlank' }), + await createModalMessage(`blank - ${counter}`, gitNotSet, (value) => { workspace = value }, (value) => gitInit = false), + intl.formatMessage({ id: 'filePanel.ok' }), + () => global.dispatchCreateWorkspace(`blank - ${counter}`, 'blank', false), + intl.formatMessage({ id: 'filePanel.cancel' }) + ) + } + const saveSampleCodeWorkspace = () => { const workspaceName = global.plugin.getAvailableWorkspaceName('code-sample') global.modal( @@ -887,6 +910,13 @@ export function Workspace() { ) } + + const logInGithub = async () => { + await global.plugin.call('menuicons', 'select', 'dgit'); + await global.plugin.call('dgit', 'open', gitUIPanels.GITHUB) + _paq.push(['trackEvent', 'Workspace', 'GIT', 'login']) + } + return (
) : null} - - - {selectedWorkspace && selectedWorkspace.name === 'code-sample' && } - > - saveSampleCodeWorkspace()} className="far fa-exclamation-triangle text-warning ml-2 align-self-center" aria-hidden="true"> - } - - {selectedWorkspace && selectedWorkspace.isGist && selectedWorkspace.isGist} direction="bottom" icon="far fa-copy"> - - - } - - +
+ + + {selectedWorkspace && selectedWorkspace.name === 'code-sample' && } + > + saveSampleCodeWorkspace()} className="far fa-exclamation-triangle text-warning ml-2 align-self-center" aria-hidden="true"> + } + + {selectedWorkspace && selectedWorkspace.isGist && selectedWorkspace.isGist} direction="bottom" icon="far fa-copy"> + + + } + + + { + (!appContext.appState.gitHubUser || !appContext.appState.gitHubUser.isConnected) && } + > +
+ logInGithub() } className="fa-brands fa-github-alt ml-2 align-self-center" style={{ fontSize: '1.1rem', cursor: 'pointer' }} aria-hidden="true"> + logInGithub() } className="ml-1"> Sign in +
+
+ } + { + appContext.appState.gitHubUser && appContext.appState.gitHubUser.isConnected && + + + } +
+
{(platform !== appPlatformTypes.desktop) ? ( @@ -1198,22 +1255,32 @@ export function Workspace() {
GIT
{ selectedWorkspace.hasGitSubmodules? - } - > -
- { global.fs.browser.isRequestingCloning ? : + +
+ { global.fs.browser.isRequestingCloning ? + + + : + } + > } -
- + Update submodules + + + } +
: null } , path?: string[], extension?: string[], pattern?: string[], id: string, multiselect: boolean, label: string, sticky?: boolean, group: number, platform?: appPlatformTypes } export interface JSONStandardInput { diff --git a/libs/remix-ui/workspace/src/lib/utils/constants.ts b/libs/remix-ui/workspace/src/lib/utils/constants.ts index fcde9c1830..1d28b8d40a 100644 --- a/libs/remix-ui/workspace/src/lib/utils/constants.ts +++ b/libs/remix-ui/workspace/src/lib/utils/constants.ts @@ -34,6 +34,90 @@ export const TEMPLATE_METADATA: Record = { name: 'cookbookdev', endpoint: 'openPattern', params: ['Uniswap-V4-HookBook-MultiSigSwapHook', true] + }, + 'token-sale': { + type: 'plugin', + name: 'cookbookdev', + endpoint: 'openContract', + params: ['token-sale'] + }, + 'simple-nft-sale': { + type: 'plugin', + name: 'cookbookdev', + endpoint: 'openContract', + params: ['simple-nft-sale'] + }, + 'Azuki-ERC721A-NFT-Sale-basic': { + type: 'plugin', + name: 'cookbookdev', + endpoint: 'openContract', + params: ['Azuki-ERC721A-NFT-Sale-basic'] + }, + 'Azuki-ERC721A-ERC721A': { + type: 'plugin', + name: 'cookbookdev', + endpoint: 'openContract', + params: ['Azuki-ERC721A-ERC721A'] + }, + 'token-staking-with-infinite-rewards': { + type: 'plugin', + name: 'cookbookdev', + endpoint: 'openContract', + params: ['token-staking-with-infinite-rewards'] + }, + 'nft-staking-with-infinite-rewards': { + type: 'plugin', + name: 'cookbookdev', + endpoint: 'openContract', + params: ['nft-staking-with-infinite-rewards'] + }, + 'basic-dao': { + type: 'plugin', + name: 'cookbookdev', + endpoint: 'openContract', + params: ['basic-dao'] + }, + 'soulbound-nft': { + type: 'plugin', + name: 'cookbookdev', + endpoint: 'openContract', + params: ['soulbound-nft'] + }, + 'multi-collection-nft-with-burnable-nfts-and-pausable-transfers': { + type: 'plugin', + name: 'cookbookdev', + endpoint: 'openContract', + params: ['multi-collection-nft-with-burnable-nfts-and-pausable-transfers'] + }, + 'OpenSea-Seaport': { + type: 'plugin', + name: 'cookbookdev', + endpoint: 'openProtocol', + params: ['OpenSea-Seaport'] + }, + 'Ethereum-Name-Service': { + type: 'plugin', + name: 'cookbookdev', + endpoint: 'openProtocol', + params: ['Ethereum-Name-Service'] + }, + 'Umbra-Cash': { + type: 'plugin', + name: 'cookbookdev', + endpoint: 'openProtocol', + params: ['Umbra-Cash'] + }, + 'Aave-V3': { + type: 'plugin', + name: 'cookbookdev', + endpoint: 'openProtocol', + params: ['Aave-V3'] + }, + 'ChainLink': { + type: 'plugin', + name: 'cookbookdev', + endpoint: 'openProtocol', + params: ['ChainLink'] } } diff --git a/libs/remix-url-resolver/package.json b/libs/remix-url-resolver/package.json index 415143f95d..f775b72458 100644 --- a/libs/remix-url-resolver/package.json +++ b/libs/remix-url-resolver/package.json @@ -1,6 +1,6 @@ { "name": "@remix-project/remix-url-resolver", - "version": "0.0.85", + "version": "0.0.86", "description": "Solidity import url resolver engine", "main": "src/index.js", "types": "src/index.d.ts", @@ -41,5 +41,5 @@ "typescript": "^3.1.6" }, "typings": "src/index.d.ts", - "gitHead": "57f4196f41faf8a2879a8013327f5e275e623444" + "gitHead": "28b25d08084ff0dd952f2cd649dbcd1c1ab30e01" } \ No newline at end of file diff --git a/libs/remix-ws-templates/package.json b/libs/remix-ws-templates/package.json index c26118f563..1787101d43 100644 --- a/libs/remix-ws-templates/package.json +++ b/libs/remix-ws-templates/package.json @@ -1,6 +1,6 @@ { "name": "@remix-project/remix-ws-templates", - "version": "1.0.50", + "version": "1.0.51", "description": "Create a Remix IDE workspace using different templates", "main": "src/index.js", "types": "src/index.d.ts", @@ -24,5 +24,5 @@ "ethers": "^5.4.2", "web3": "^4.1.1" }, - "gitHead": "57f4196f41faf8a2879a8013327f5e275e623444" + "gitHead": "28b25d08084ff0dd952f2cd649dbcd1c1ab30e01" } \ No newline at end of file diff --git a/libs/remixd/package.json b/libs/remixd/package.json index 118affc943..0da157670c 100644 --- a/libs/remixd/package.json +++ b/libs/remixd/package.json @@ -1,6 +1,6 @@ { "name": "@remix-project/remixd", - "version": "0.6.36", + "version": "0.6.37", "description": "remix server: allow accessing file system from remix.ethereum.org and start a dev environment (see help section)", "main": "index.js", "types": "./index.d.ts", diff --git a/package.json b/package.json index d93aae6dfa..31668fbca0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "remix-project", - "version": "0.54.0-dev", + "version": "0.55.0-dev", "license": "MIT", "description": "Ethereum Remix Monorepo", "main": "index.js", @@ -92,11 +92,11 @@ "@erebos/bzz-node": "^0.13.0", "@ethereumjs/block": "5.3.0", "@ethereumjs/common": "4.4.0", - "@ethereumjs/evm": "3.1.0", + "@ethereumjs/evm": "3.1.1", "@ethereumjs/statemanager": "2.4.0", "@ethereumjs/tx": "5.4.0", "@ethereumjs/util": "9.1.0", - "@ethereumjs/vm": "8.1.0", + "@ethereumjs/vm": "8.1.1", "@ethersphere/bee-js": "^3.2.0", "@floating-ui/react": "^0.26.15", "@fortawesome/fontawesome-svg-core": "^6.5.1", @@ -382,11 +382,11 @@ "@ethereumjs/blockchain": "7.3.0", "@ethereumjs/block": "5.3.0", "@ethereumjs/common": "4.4.0", - "@ethereumjs/evm": "3.1.0", + "@ethereumjs/evm": "3.1.1", "@ethereumjs/statemanager": "2.4.0", "@ethereumjs/tx": "5.4.0", "@ethereumjs/util": "9.1.0", - "@ethereumjs/vm": "8.1.0", + "@ethereumjs/vm": "8.1.1", "@ethereumjs/trie": "6.2.1" } } diff --git a/releaseDetails.json b/releaseDetails.json index 241101d8b9..15b21653c2 100644 --- a/releaseDetails.json +++ b/releaseDetails.json @@ -1,11 +1,13 @@ { - "version": "v0.53.0", + "version": "v0.54.0", "title": "RELEASE HIGHLIGHTS", - "highlight1": "Keyboard shortcut for Cut-Copy-Paste files and folder", - "highlight2": "Interface to generate proof in Circom compiler plugin", - "highlight3": "Publish multi-selected files to Gist", + "highlight1": "Login to GitHub from 'File Explorer'", + "highlight2": "Added Cookbook workspace templates", + "highlight3": "Added 'sendRawTransaction' API to remix-simulator", "highlight4": "", "more": "Read More", - "moreLink": "https://medium.com/remix-ide/remix-release-v0-53-0-615d9e7c6c58?source=friends_link&sk=35e918e8487aaab02e79ea4dc557a7e7" + "moreLink": "https://medium.com/remix-ide/remix-release-v0-54-0-021575d54849?source=friends_link&sk=e3960ba90994b63993987b007ee3ac63" } + + \ No newline at end of file diff --git a/tsconfig.paths.json b/tsconfig.paths.json index e69a28a187..d373a783b1 100644 --- a/tsconfig.paths.json +++ b/tsconfig.paths.json @@ -187,6 +187,9 @@ ], "@remix-api": [ "libs/remix-api/src/index.ts" + ], + "@remix-git": [ + "libs/remix-git/" ] } }