diff --git a/apps/remix-ide-e2e/src/tests/fileExplorer.test.ts b/apps/remix-ide-e2e/src/tests/fileExplorer.test.ts index 3c915bb8fa..40e31b311e 100644 --- a/apps/remix-ide-e2e/src/tests/fileExplorer.test.ts +++ b/apps/remix-ide-e2e/src/tests/fileExplorer.test.ts @@ -117,69 +117,68 @@ module.exports = { 'Should add deep tree with buttons #group3': function (browser: NightwatchBrowser) { browser - .waitForElementVisible('div[data-id="remixIdeSidePanel"]') - .clickLaunchIcon('filePanel') - .waitForElementVisible('*[data-id="filePanelFileExplorerTree"]') - .waitForElementVisible('[data-id="fileExplorerNewFilecreateNewFolder"]') - .click('[data-id="fileExplorerNewFilecreateNewFolder"]') - .waitForElementVisible('*[data-id$="fileExplorerTreeItemInput"]') - .sendKeys('*[data-id$="fileExplorerTreeItemInput"]', 'deep1') - .sendKeys('*[data-id$="fileExplorerTreeItemInput"]', browser.Keys.ENTER) - .waitForElementVisible('*[data-id="treeViewLitreeViewItemdeep1"]') - .waitForElementVisible('[data-id="fileExplorerNewFilecreateNewFolder"]') - .click('[data-id="fileExplorerNewFilecreateNewFolder"]') - .waitForElementVisible('*[data-id$="fileExplorerTreeItemInput"]') - .sendKeys('*[data-id$="fileExplorerTreeItemInput"]', 'deep2') - .sendKeys('*[data-id$="fileExplorerTreeItemInput"]', browser.Keys.ENTER) - .waitForElementVisible('*[data-id="treeViewLitreeViewItemdeep1/deep2"]') - .waitForElementVisible('[data-id="fileExplorerNewFilecreateNewFolder"]') - .click('[data-id="fileExplorerNewFilecreateNewFolder"]') - .waitForElementVisible('*[data-id$="fileExplorerTreeItemInput"]') - .sendKeys('*[data-id$="fileExplorerTreeItemInput"]', 'deep3') - .sendKeys('*[data-id$="fileExplorerTreeItemInput"]', browser.Keys.ENTER) - .waitForElementVisible('*[data-id="treeViewLitreeViewItemdeep1/deep2/deep3"]') - .waitForElementVisible('[data-id="fileExplorerNewFilecreateNewFile"]') - .click('[data-id="fileExplorerNewFilecreateNewFile"]') - .waitForElementVisible('*[data-id$="fileExplorerTreeItemInput"]') - .sendKeys('*[data-id$="fileExplorerTreeItemInput"]', 'deep4.sol') - .sendKeys('*[data-id$="fileExplorerTreeItemInput"]', browser.Keys.ENTER) - .waitForElementVisible('*[data-id="treeViewLitreeViewItemdeep1/deep2/deep3/deep4.sol"]') + .waitForElementVisible('div[data-id="remixIdeSidePanel"]') + .clickLaunchIcon('filePanel') + .waitForElementVisible('*[data-id="filePanelFileExplorerTree"]') + .waitForElementVisible('[data-id="fileExplorerNewFilecreateNewFolder"]') + .click('[data-id="fileExplorerNewFilecreateNewFolder"]') + .waitForElementVisible('*[data-id$="fileExplorerTreeItemInput"]') + .sendKeys('*[data-id$="fileExplorerTreeItemInput"]', 'deep1') + .sendKeys('*[data-id$="fileExplorerTreeItemInput"]', browser.Keys.ENTER) + .waitForElementVisible('*[data-id="treeViewLitreeViewItemdeep1"]') + .waitForElementVisible('[data-id="fileExplorerNewFilecreateNewFolder"]') + .click('[data-id="fileExplorerNewFilecreateNewFolder"]') + .waitForElementVisible('*[data-id$="fileExplorerTreeItemInput"]') + .sendKeys('*[data-id$="fileExplorerTreeItemInput"]', 'deep2') + .sendKeys('*[data-id$="fileExplorerTreeItemInput"]', browser.Keys.ENTER) + .waitForElementVisible('*[data-id="treeViewLitreeViewItemdeep1/deep2"]') + .waitForElementVisible('[data-id="fileExplorerNewFilecreateNewFolder"]') + .click('[data-id="fileExplorerNewFilecreateNewFolder"]') + .waitForElementVisible('*[data-id$="fileExplorerTreeItemInput"]') + .sendKeys('*[data-id$="fileExplorerTreeItemInput"]', 'deep3') + .sendKeys('*[data-id$="fileExplorerTreeItemInput"]', browser.Keys.ENTER) + .waitForElementVisible('*[data-id="treeViewLitreeViewItemdeep1/deep2/deep3"]') + .waitForElementVisible('[data-id="fileExplorerNewFilecreateNewFile"]') + .click('[data-id="fileExplorerNewFilecreateNewFile"]') + .waitForElementVisible('*[data-id$="fileExplorerTreeItemInput"]') + .sendKeys('*[data-id$="fileExplorerTreeItemInput"]', 'deep4.sol') + .sendKeys('*[data-id$="fileExplorerTreeItemInput"]', browser.Keys.ENTER) + .waitForElementVisible('*[data-id="treeViewLitreeViewItemdeep1/deep2/deep3/deep4.sol"]') // click on root to focus - .click('li[data-id="treeViewLitreeViewItemREADME.txt"]') - .waitForElementVisible('[data-id="fileExplorerNewFilecreateNewFolder"]') - .click('[data-id="fileExplorerNewFilecreateNewFolder"]') - .waitForElementVisible('*[data-id$="fileExplorerTreeItemInput"]') - .sendKeys('*[data-id$="fileExplorerTreeItemInput"]', 'deep5') - .sendKeys('*[data-id$="fileExplorerTreeItemInput"]', browser.Keys.ENTER) - .waitForElementVisible('*[data-id="treeViewLitreeViewItemdeep5"]') - .waitForElementVisible('[data-id="fileExplorerNewFilecreateNewFolder"]') - .click('[data-id="fileExplorerNewFilecreateNewFolder"]') - .waitForElementVisible('*[data-id$="fileExplorerTreeItemInput"]') - .sendKeys('*[data-id$="fileExplorerTreeItemInput"]', 'deep6') - .sendKeys('*[data-id$="fileExplorerTreeItemInput"]', browser.Keys.ENTER) - .waitForElementVisible('*[data-id="treeViewLitreeViewItemdeep5/deep6"]') + .click('li[data-id="treeViewLitreeViewItemREADME.txt"]') + .waitForElementVisible('[data-id="fileExplorerNewFilecreateNewFolder"]') + .click('[data-id="fileExplorerNewFilecreateNewFolder"]') + .waitForElementVisible('*[data-id$="fileExplorerTreeItemInput"]') + .sendKeys('*[data-id$="fileExplorerTreeItemInput"]', 'deep5') + .sendKeys('*[data-id$="fileExplorerTreeItemInput"]', browser.Keys.ENTER) + .waitForElementVisible('*[data-id="treeViewLitreeViewItemdeep5"]') + .waitForElementVisible('[data-id="fileExplorerNewFilecreateNewFolder"]') + .click('[data-id="fileExplorerNewFilecreateNewFolder"]') + .waitForElementVisible('*[data-id$="fileExplorerTreeItemInput"]') + .sendKeys('*[data-id$="fileExplorerTreeItemInput"]', 'deep6') + .sendKeys('*[data-id$="fileExplorerTreeItemInput"]', browser.Keys.ENTER) + .waitForElementVisible('*[data-id="treeViewLitreeViewItemdeep5/deep6"]') // focus on contracts - .click('li[data-id="treeViewLitreeViewItemcontracts"]') - .waitForElementVisible('[data-id="fileExplorerNewFilecreateNewFolder"]') - .click('[data-id="fileExplorerNewFilecreateNewFolder"]') - .waitForElementVisible('*[data-id$="fileExplorerTreeItemInput"]') - .sendKeys('*[data-id$="fileExplorerTreeItemInput"]', 'deep7') - .sendKeys('*[data-id$="fileExplorerTreeItemInput"]', browser.Keys.ENTER) - .waitForElementVisible('*[data-id="treeViewLitreeViewItemcontracts/deep7"]') - .waitForElementVisible('[data-id="fileExplorerNewFilecreateNewFolder"]') - .click('[data-id="fileExplorerNewFilecreateNewFolder"]') - .waitForElementVisible('*[data-id$="fileExplorerTreeItemInput"]') - .sendKeys('*[data-id$="fileExplorerTreeItemInput"]', 'deep8') - .sendKeys('*[data-id$="fileExplorerTreeItemInput"]', browser.Keys.ENTER) - .waitForElementVisible('*[data-id="treeViewLitreeViewItemcontracts/deep7/deep8"]') - .waitForElementVisible('[data-id="fileExplorerNewFilecreateNewFile"]') - .click('[data-id="fileExplorerNewFilecreateNewFile"]') - .waitForElementVisible('*[data-id$="fileExplorerTreeItemInput"]') - .sendKeys('*[data-id$="fileExplorerTreeItemInput"]', 'deep9.sol') - .sendKeys('*[data-id$="fileExplorerTreeItemInput"]', browser.Keys.ENTER) - .waitForElementVisible('*[data-id="treeViewLitreeViewItemcontracts/deep7/deep8/deep9.sol"]') - .end() + .click('li[data-id="treeViewLitreeViewItemcontracts"]') + .waitForElementVisible('[data-id="fileExplorerNewFilecreateNewFolder"]') + .click('[data-id="fileExplorerNewFilecreateNewFolder"]') + .waitForElementVisible('*[data-id$="fileExplorerTreeItemInput"]') + .sendKeys('*[data-id$="fileExplorerTreeItemInput"]', 'deep7') + .sendKeys('*[data-id$="fileExplorerTreeItemInput"]', browser.Keys.ENTER) + .waitForElementVisible('*[data-id="treeViewLitreeViewItemcontracts/deep7"]') + .waitForElementVisible('[data-id="fileExplorerNewFilecreateNewFolder"]') + .click('[data-id="fileExplorerNewFilecreateNewFolder"]') + .waitForElementVisible('*[data-id$="fileExplorerTreeItemInput"]') + .sendKeys('*[data-id$="fileExplorerTreeItemInput"]', 'deep8') + .sendKeys('*[data-id$="fileExplorerTreeItemInput"]', browser.Keys.ENTER) + .waitForElementVisible('*[data-id="treeViewLitreeViewItemcontracts/deep7/deep8"]') + .waitForElementVisible('[data-id="fileExplorerNewFilecreateNewFile"]') + .click('[data-id="fileExplorerNewFilecreateNewFile"]') + .waitForElementVisible('*[data-id$="fileExplorerTreeItemInput"]') + .sendKeys('*[data-id$="fileExplorerTreeItemInput"]', 'deep9.sol') + .sendKeys('*[data-id$="fileExplorerTreeItemInput"]', browser.Keys.ENTER) + .waitForElementVisible('*[data-id="treeViewLitreeViewItemcontracts/deep7/deep8/deep9.sol"]') + .end() } - } diff --git a/apps/remix-ide-e2e/src/tests/file_explorer_context_menu.test.ts b/apps/remix-ide-e2e/src/tests/file_explorer_context_menu.test.ts index 91730b50f4..9e54dbd885 100644 --- a/apps/remix-ide-e2e/src/tests/file_explorer_context_menu.test.ts +++ b/apps/remix-ide-e2e/src/tests/file_explorer_context_menu.test.ts @@ -90,7 +90,7 @@ module.exports = { .rightClick('li[data-id="treeViewLitreeViewItemREADME.txt"]') .waitForElementPresent('[data-id="contextMenuItemcopy') .click('[data-id="contextMenuItemcopy"]') - .rightClick('*[data-id="treeViewLiMenu"]') + .rightClick('*[data-id="treeViewUltreeViewMenu"]') .saveScreenshot('./reports/screenshot/file_explorer_context_menu.png') .click('*[data-id="contextMenuItempaste"]') .waitForElementVisible('*[data-id="treeViewLitreeViewItemCopy_README.txt"]', 7000) @@ -111,7 +111,7 @@ module.exports = { .rightClick('li[data-id="treeViewLitreeViewItemcontracts"]') .waitForElementPresent('[data-id="contextMenuItemcopy') .click('[data-id="contextMenuItemcopy"]') - .rightClick('*[data-id="treeViewLiMenu"]') + .rightClick('*[data-id="treeViewUltreeViewMenu"]') .click('*[data-id="contextMenuItempaste"]') .waitForElementVisible('*[data-id="treeViewLitreeViewItemCopy_contracts"]', 7000) }, diff --git a/apps/remix-ide-e2e/src/tests/file_explorer_dragdrop.test.ts b/apps/remix-ide-e2e/src/tests/file_explorer_dragdrop.test.ts index 949bf86d59..6bf875f82a 100644 --- a/apps/remix-ide-e2e/src/tests/file_explorer_dragdrop.test.ts +++ b/apps/remix-ide-e2e/src/tests/file_explorer_dragdrop.test.ts @@ -6,7 +6,6 @@ const checkBrowserIsChrome = function (browser: NightwatchBrowser) { return browser.browserName.indexOf('chrome') > -1 } - module.exports = { '@disabled': true, before: function (browser: NightwatchBrowser, done: VoidFunction) { @@ -98,6 +97,4 @@ module.exports = { } } - - } diff --git a/apps/remix-ide-e2e/src/tests/homeTab.test.ts b/apps/remix-ide-e2e/src/tests/homeTab.test.ts index 2c009d65b5..46faaef303 100644 --- a/apps/remix-ide-e2e/src/tests/homeTab.test.ts +++ b/apps/remix-ide-e2e/src/tests/homeTab.test.ts @@ -3,15 +3,52 @@ import { NightwatchBrowser } from 'nightwatch' import init from '../helpers/init' module.exports = { - + '@disabled': true, before: function (browser: NightwatchBrowser, done: VoidFunction) { init(browser, done) }, - 'Should start coding': function (browser: NightwatchBrowser) { + 'Should start coding #group1': function (browser: NightwatchBrowser) { + browser + .waitForElementVisible('*[data-id="homeTabGetStartedremixDefault"]') + .click('*[data-id="homeTabGetStartedremixDefault"]') + .waitForElementVisible('*[data-id="treeViewDivtreeViewItemcontracts/1_Storage.sol"]') + .waitForElementVisible('*[data-id="treeViewLitreeViewItemcontracts/2_Owner.sol"') + .waitForElementVisible('*[data-id="treeViewDivDraggableItemREADME.txt"') + .click('*[data-id="treeViewDivtreeViewItemcontracts/1_Storage.sol"]') + .waitForElementPresent({ + selector: "//div[contains(@class, 'view-line') and contains(.//span, 'pragma')]", + locateStrategy: 'xpath' + }) + .getEditorValue((editorContent) => { + browser.assert.ok(editorContent.indexOf(`pragma solidity`) !== -1, 'unexpected content encountered!') + }) + }, + + 'Should start with ERC20 workspace #group1': function (browser: NightwatchBrowser) { + browser + .click('*[data-path="home"') + .waitForElementVisible('*[data-id="homeTabGetStartedERC20"]') + .click('*[data-id="homeTabGetStartedERC20"') + .waitForElementVisible('*[data-id="treeViewLitreeViewItemcontracts/MyToken.sol"]') + .waitForElementVisible('*[data-id="treeViewDivtreeViewItemtests/MyToken_test.sol"]') + .click('*[data-id="treeViewDivtreeViewItemtests/MyToken_test.sol"]') + .waitForElementPresent({ + selector: "//div[contains(@class, 'view-line') and contains(.//span, 'pragma')]", + locateStrategy: 'xpath' + }) + .getEditorValue((editorContent) => { + browser.assert.ok(editorContent.indexOf(`import "../contracts/MyToken.sol";`) !== -1, 'content encountered!') + }) + }, + 'Should create a new file in the current workspace': '' +function (browser: NightwatchBrowser) { browser - .waitForElementVisible('*[data-id="homeTabStartCoding"]') - .click('*[data-id="homeTabStartCoding"]') - .waitForElementVisible('div[data-id="treeViewDivtreeViewItemcontracts/HelloWorld.sol"]') + .click('*[data-path="home"]') + .waitForElementVisible('*[data-id="homeTabNewFile"]') + .click('*[data-id="homeTabNewFile"]') + .waitForElementVisible('*[data-id$="fileExplorerTreeItemInput"]') + .sendKeys('*[data-id$="fileExplorerTreeItemInput"]', 'HometabNewFile.txt') + .sendKeys('*[data-id$="fileExplorerTreeItemInput"]', browser.Keys.ENTER) + .waitForElementVisible('*[data-id="treeViewLitreeViewItemHometabNewFile.txt"]', 7000) } -} \ No newline at end of file +} diff --git a/apps/remix-ide-e2e/src/tests/terminal.test.ts b/apps/remix-ide-e2e/src/tests/terminal.test.ts index fdbc8fb8b1..8c716a187d 100644 --- a/apps/remix-ide-e2e/src/tests/terminal.test.ts +++ b/apps/remix-ide-e2e/src/tests/terminal.test.ts @@ -117,6 +117,7 @@ module.exports = { .waitForElementPresent('*[data-id="universalDappUiContractActionWrapper"]', 60000) .clickInstance(0) .clickFunction('changeOwner - transact (not payable)', { types: 'address newOwner', values: '0xd9145CCE52D386f254917e481eB44e9943F39138' }) // execute the "changeOwner" function + .pause() .waitForElementContainsText('*[data-id="terminalJournal"]', 'previousOwner', 60000) // check that the script is logging the event .waitForElementContainsText('*[data-id="terminalJournal"]', '0x5B38Da6a701c568545dCfcB03FcB875f56beddC4', 60000) // check that the script is logging the event .waitForElementContainsText('*[data-id="terminalJournal"]', 'newOwner', 60000) diff --git a/apps/remix-ide-e2e/src/tests/url.test.ts b/apps/remix-ide-e2e/src/tests/url.test.ts index 7c8fa078cd..b55a66f90f 100644 --- a/apps/remix-ide-e2e/src/tests/url.test.ts +++ b/apps/remix-ide-e2e/src/tests/url.test.ts @@ -11,31 +11,31 @@ const sources = [ content: ` // SPDX-License-Identifier: MIT pragma solidity ^0.8.20; - + import "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol"; import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; import "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; - + contract MyToken is Initializable, ERC721Upgradeable, OwnableUpgradeable, UUPSUpgradeable { /// @custom:oz-upgrades-unsafe-allow constructor constructor() { _disableInitializers(); } - + function initialize(address initialOwner) initializer public { __ERC721_init("MyToken", "MTK"); __Ownable_init(initialOwner); __UUPSUpgradeable_init(); } - + function _authorizeUpgrade(address newImplementation) internal onlyOwner override {} } - + ` } } @@ -117,7 +117,7 @@ module.exports = { }) }, - 'Should load Blockscout verified contracts from URL "address" and "blockscout" params (single source)': function (browser: NightwatchBrowser) { + 'Should load Blockscout verified contracts from URL "address" and "blockscout" params (single source)': ''+function (browser: NightwatchBrowser) { browser .url('http://127.0.0.1:8080/#address=0xdAC17F958D2ee523a2206206994597C13D831ec7&blockscout=eth.blockscout.com') .refreshPage() diff --git a/apps/remix-ide-e2e/src/tests/workspace.test.ts b/apps/remix-ide-e2e/src/tests/workspace.test.ts index b0e261f554..d351b05ce1 100644 --- a/apps/remix-ide-e2e/src/tests/workspace.test.ts +++ b/apps/remix-ide-e2e/src/tests/workspace.test.ts @@ -577,7 +577,7 @@ module.exports = { .getEditorValue((content) => { browser.assert.ok(content.indexOf(`contract Create2FactoryAssembly {`) !== -1, 'current displayed content is not Create2FactoryAssembly') - }) + }) }, tearDown: sauce diff --git a/apps/remix-ide-e2e/src/tests/workspace_git.test.ts b/apps/remix-ide-e2e/src/tests/workspace_git.test.ts index 16870069e3..e061bdb357 100644 --- a/apps/remix-ide-e2e/src/tests/workspace_git.test.ts +++ b/apps/remix-ide-e2e/src/tests/workspace_git.test.ts @@ -159,11 +159,13 @@ module.exports = { .setValue('[data-id="modalDialogCustomPromptTextClone"]', 'https://github.com/ioedeveloper/test-branch-change') .click('[data-id="fileSystem-modal-footer-ok-react"]') .waitForElementPresent('.fa-spinner') - .pause(5000) + .pause(7000) .waitForElementNotPresent('.fa-spinner') .waitForElementContainsText('[data-id="workspacesSelect"]', 'test-branch-change') .waitForElementVisible('[data-id="workspaceGitPanel"]') + .waitForElementVisible('[data-id="workspaceGitBranchesDropdown"]') .click('[data-id="workspaceGitBranchesDropdown"]') + .pause() .waitForElementVisible('[data-id="custom-dropdown-menu"]') .waitForElementContainsText('[data-id="custom-dropdown-items"]', 'origin/dev') .waitForElementContainsText('[data-id="custom-dropdown-items"]', 'origin/production') @@ -311,66 +313,67 @@ module.exports = { }, 'When switching branches the submodules should disappear #group4': function (browser: NightwatchBrowser) { browser - .waitForElementVisible('[data-id="workspaceGitBranchesDropdown"]') - .click('[data-id="workspaceGitBranchesDropdown"]') - .waitForElementVisible('[data-id="custom-dropdown-menu"]') - .waitForElementContainsText('[data-id="custom-dropdown-items"]', 'origin/empty') - .waitForElementPresent('[data-id="workspaceGit-origin/empty"]') - .click('[data-id="workspaceGit-origin/empty"]') - .waitForElementNotPresent('[data-id="treeViewDivtreeViewItemlibdeep"]') - .waitForElementNotPresent('[data-id="treeViewDivtreeViewItemtest-branch-submodule-recursive"]') - .waitForElementNotPresent('[data-id="treeViewDivtreeViewItemtest-branch-submodule-2"]') + .waitForElementVisible('[data-id="workspaceGitBranchesDropdown"]') + .pause() + .click('[data-id="workspaceGitBranchesDropdown"]') + .waitForElementVisible('[data-id="custom-dropdown-menu"]') + .waitForElementContainsText('[data-id="custom-dropdown-items"]', 'origin/empty') + .waitForElementPresent('[data-id="workspaceGit-origin/empty"]') + .click('[data-id="workspaceGit-origin/empty"]') + .waitForElementNotPresent('[data-id="treeViewDivtreeViewItemlibdeep"]') + .waitForElementNotPresent('[data-id="treeViewDivtreeViewItemtest-branch-submodule-recursive"]') + .waitForElementNotPresent('[data-id="treeViewDivtreeViewItemtest-branch-submodule-2"]') }, 'When switching to main update the modules #group4': function (browser: NightwatchBrowser) { browser - .waitForElementVisible('[data-id="workspaceGitBranchesDropdown"]') - .click('[data-id="workspaceGitBranchesDropdown"]') - .waitForElementVisible('[data-id="custom-dropdown-menu"]') - .waitForElementContainsText('[data-id="custom-dropdown-items"]', 'origin/main') - .waitForElementPresent('[data-id="workspaceGit-origin/main"]') - .click('[data-id="workspaceGit-origin/main"]') - .waitForElementVisible('[data-id="updatesubmodules"]') - .click('[data-id="updatesubmodules"]') - .waitForElementPresent('.fa-spinner') - .waitForElementVisible({ - selector: '*[data-id="treeViewLitreeViewItem.git"]', - timeout: 240000 - }) - .pause(2000) + .waitForElementVisible('[data-id="workspaceGitBranchesDropdown"]') + .click('[data-id="workspaceGitBranchesDropdown"]') + .waitForElementVisible('[data-id="custom-dropdown-menu"]') + .waitForElementContainsText('[data-id="custom-dropdown-items"]', 'origin/main') + .waitForElementPresent('[data-id="workspaceGit-origin/main"]') + .click('[data-id="workspaceGit-origin/main"]') + .waitForElementVisible('[data-id="updatesubmodules"]') + .click('[data-id="updatesubmodules"]') + .waitForElementPresent('.fa-spinner') + .waitForElementVisible({ + selector: '*[data-id="treeViewLitreeViewItem.git"]', + timeout: 240000 + }) + .pause(2000) // check recursive submodule - .waitForElementVisible('[data-id="treeViewDivtreeViewItemtest-branch-submodule-recursive"]') - .click('[data-id="treeViewDivtreeViewItemtest-branch-submodule-recursive"]') - .click('[data-id="treeViewDivtreeViewItemtest-branch-submodule-recursive"]') - .waitForElementVisible('[data-id="treeViewDivtreeViewItemtest-branch-submodule-recursive/test-branch-submodule-2"]') - .click('[data-id="treeViewDivtreeViewItemtest-branch-submodule-recursive/test-branch-submodule-2"]') - .waitForElementVisible('[data-id="treeViewDivtreeViewItemtest-branch-submodule-recursive/test-branch-submodule-2/submodule2.ts"]') + .waitForElementVisible('[data-id="treeViewDivtreeViewItemtest-branch-submodule-recursive"]') + .click('[data-id="treeViewDivtreeViewItemtest-branch-submodule-recursive"]') + .click('[data-id="treeViewDivtreeViewItemtest-branch-submodule-recursive"]') + .waitForElementVisible('[data-id="treeViewDivtreeViewItemtest-branch-submodule-recursive/test-branch-submodule-2"]') + .click('[data-id="treeViewDivtreeViewItemtest-branch-submodule-recursive/test-branch-submodule-2"]') + .waitForElementVisible('[data-id="treeViewDivtreeViewItemtest-branch-submodule-recursive/test-branch-submodule-2/submodule2.ts"]') // check test-branch-submodule-2 submodule - .waitForElementVisible('[data-id="treeViewDivtreeViewItemtest-branch-submodule-2"]') - .click('[data-id="treeViewDivtreeViewItemtest-branch-submodule-2"]') - .click('[data-id="treeViewDivtreeViewItemtest-branch-submodule-2"]') - .waitForElementVisible('[data-id="treeViewDivtreeViewItemtest-branch-submodule-2/submodule2.ts"]') + .waitForElementVisible('[data-id="treeViewDivtreeViewItemtest-branch-submodule-2"]') + .click('[data-id="treeViewDivtreeViewItemtest-branch-submodule-2"]') + .click('[data-id="treeViewDivtreeViewItemtest-branch-submodule-2"]') + .waitForElementVisible('[data-id="treeViewDivtreeViewItemtest-branch-submodule-2/submodule2.ts"]') // check libdeep submodule - .waitForElementVisible('[data-id="treeViewDivtreeViewItemlibdeep"]') - .click('[data-id="treeViewDivtreeViewItemlibdeep"]') - .click('[data-id="treeViewDivtreeViewItemlibdeep"]') - .waitForElementVisible('[data-id="treeViewDivtreeViewItemlibdeep/test-branch-submodule-2"]') - .click('[data-id="treeViewDivtreeViewItemlibdeep/test-branch-submodule-2"]') - .waitForElementVisible('[data-id="treeViewDivtreeViewItemlibdeep/test-branch-submodule-2/submodule2.ts"]') + .waitForElementVisible('[data-id="treeViewDivtreeViewItemlibdeep"]') + .click('[data-id="treeViewDivtreeViewItemlibdeep"]') + .click('[data-id="treeViewDivtreeViewItemlibdeep"]') + .waitForElementVisible('[data-id="treeViewDivtreeViewItemlibdeep/test-branch-submodule-2"]') + .click('[data-id="treeViewDivtreeViewItemlibdeep/test-branch-submodule-2"]') + .waitForElementVisible('[data-id="treeViewDivtreeViewItemlibdeep/test-branch-submodule-2/submodule2.ts"]') // check libdeep2 submodule - .waitForElementVisible('[data-id="treeViewDivtreeViewItemlibdeep2"]') - .click('[data-id="treeViewDivtreeViewItemlibdeep2"]') - .waitForElementVisible('[data-id="treeViewDivtreeViewItemlibdeep2/recursive"]') - .click('[data-id="treeViewDivtreeViewItemlibdeep2/recursive"]') - .waitForElementVisible('[data-id="treeViewDivtreeViewItemlibdeep2/recursive/test-branch-submodule-2"]') - .click('[data-id="treeViewDivtreeViewItemlibdeep2/recursive/test-branch-submodule-2"]') - .waitForElementVisible('[data-id="treeViewDivtreeViewItemlibdeep2/recursive/test-branch-submodule-2/submodule2.ts"]') + .waitForElementVisible('[data-id="treeViewDivtreeViewItemlibdeep2"]') + .click('[data-id="treeViewDivtreeViewItemlibdeep2"]') + .waitForElementVisible('[data-id="treeViewDivtreeViewItemlibdeep2/recursive"]') + .click('[data-id="treeViewDivtreeViewItemlibdeep2/recursive"]') + .waitForElementVisible('[data-id="treeViewDivtreeViewItemlibdeep2/recursive/test-branch-submodule-2"]') + .click('[data-id="treeViewDivtreeViewItemlibdeep2/recursive/test-branch-submodule-2"]') + .waitForElementVisible('[data-id="treeViewDivtreeViewItemlibdeep2/recursive/test-branch-submodule-2/submodule2.ts"]') }, - // GIT SUBMODULES E2E ENDS + // GIT SUBMODULES E2E ENDS - // GIT WORKSPACE E2E STARTS + // GIT WORKSPACE E2E STARTS - 'Should create a git workspace (uniswapV4Template) #group4': function (browser: NightwatchBrowser) { + 'Should create a git workspace (uniswapV4Template) #group4': function (browser: NightwatchBrowser) { browser .click('*[data-id="workspacesMenuDropdown"]') .click('*[data-id="workspacecreate"]') @@ -389,15 +392,13 @@ module.exports = { browser.assert.ok(content.indexOf(`contract Counter is BaseHook {`) !== -1, 'Incorrect content') }) - }, + }, // GIT WORKSPACE E2E ENDS - tearDown: sauce, } - const gitmodules = `[submodule "subdemo3"] path = subdemo3 url = https://github.com/bunsenstraat/empty3 diff --git a/apps/remix-ide/src/app.js b/apps/remix-ide/src/app.js index 5a2ddf2a47..4056a57092 100644 --- a/apps/remix-ide/src/app.js +++ b/apps/remix-ide/src/app.js @@ -9,6 +9,7 @@ import {Web3ProviderModule} from './app/tabs/web3-provider' import {CompileAndRun} from './app/tabs/compile-and-run' import {PluginStateLogger} from './app/tabs/state-logger' import {SidePanel} from './app/components/side-panel' +import {StatusBar} from './app/components/status-bar' import {HiddenPanel} from './app/components/hidden-panel' import {PinnedPanel} from './app/components/pinned-panel' import {VerticalIcons} from './app/components/vertical-icons' @@ -301,7 +302,7 @@ class AppComponent { const permissionHandler = new PermissionHandlerPlugin() // ----------------- run script after each compilation results ----------- const pluginStateLogger = new PluginStateLogger() - + this.engine.register([ permissionHandler, this.layout, @@ -339,7 +340,7 @@ class AppComponent { hardhatProvider, ganacheProvider, foundryProvider, - externalHttpProvider, + externalHttpProvider, this.walkthroughService, search, solidityumlgen, @@ -386,10 +387,11 @@ class AppComponent { const pluginManagerComponent = new PluginManagerComponent(appManager, this.engine) const filePanel = new FilePanel(appManager) + this.statusBar = new StatusBar(filePanel, this.menuicons) const landingPage = new LandingPage(appManager, this.menuicons, fileManager, filePanel, contentImport) this.settings = new SettingsTab(Registry.getInstance().get('config').api, editor, appManager) - this.engine.register([this.menuicons, landingPage, this.hiddenPanel, this.sidePanel, filePanel, pluginManagerComponent, this.settings, this.pinnedPanel]) + this.engine.register([this.menuicons, landingPage, this.hiddenPanel, this.sidePanel, this.statusBar, filePanel, pluginManagerComponent, this.settings, this.pinnedPanel]) // CONTENT VIEWS & DEFAULT PLUGINS const openZeppelinProxy = new OpenZeppelinProxy(blockchain) @@ -471,6 +473,7 @@ class AppComponent { 'pluginStateLogger' ]) await this.appManager.activatePlugin(['mainPanel', 'menuicons', 'tabs']) + await this.appManager.activatePlugin(['statusBar']) await this.appManager.activatePlugin(['sidePanel']) // activating host plugin separately await this.appManager.activatePlugin(['pinnedPanel']) await this.appManager.activatePlugin(['home']) @@ -511,9 +514,9 @@ class AppComponent { await this.appManager.activatePlugin(['solidity-script']) await this.appManager.activatePlugin(['solcoder']) - - await this.appManager.activatePlugin(['filePanel']) + + await this.appManager.activatePlugin(['filePanel']) // Set workspace after initial activation this.appManager.on('editor', 'editorMounted', () => { diff --git a/apps/remix-ide/src/app/components/preload.tsx b/apps/remix-ide/src/app/components/preload.tsx index a34abe4e83..8eeba665f6 100644 --- a/apps/remix-ide/src/app/components/preload.tsx +++ b/apps/remix-ide/src/app/components/preload.tsx @@ -31,8 +31,10 @@ export const Preload = (props: any) => { ) function loadAppComponent() { + console.log('loading remix in the preloader') import('../../app') .then((AppComponent) => { + console.log('loading remix in the preloader', AppComponent) const appComponent = new AppComponent.default() appComponent.run().then(() => { props.root.render() @@ -68,6 +70,7 @@ export const Preload = (props: any) => { if (fsLoaded) { console.log(fsLoaded.name + ' activated') _paq.push(['trackEvent', 'Storage', 'activate', fsLoaded.name]) + console.log('loading remix in the preloader') loadAppComponent() } else { _paq.push(['trackEvent', 'Storage', 'error', 'no supported storage']) diff --git a/apps/remix-ide/src/app/components/side-panel.tsx b/apps/remix-ide/src/app/components/side-panel.tsx index 1a3ebc0f30..394802eca7 100644 --- a/apps/remix-ide/src/app/components/side-panel.tsx +++ b/apps/remix-ide/src/app/components/side-panel.tsx @@ -12,7 +12,7 @@ const sidePanel = { displayName: 'Side Panel', description: 'Remix IDE side panel', version: packageJson.version, - methods: ['addView', 'removeView', 'currentFocus', 'pinView', 'unPinView'] + methods: ['addView', 'removeView', 'currentFocus', 'pinView', 'unPinView', 'focus'] } export class SidePanel extends AbstractPanel { diff --git a/apps/remix-ide/src/app/components/status-bar.tsx b/apps/remix-ide/src/app/components/status-bar.tsx new file mode 100644 index 0000000000..efb105dbe0 --- /dev/null +++ b/apps/remix-ide/src/app/components/status-bar.tsx @@ -0,0 +1,106 @@ +import React from 'react' +import { EventEmitter } from 'events' +import { Plugin } from '@remixproject/engine' +import packageJson from '../../../../../package.json' +import { PluginViewWrapper } from '@remix-ui/helper' +import { PluginProfile, StatusBarInterface } from '../../types' +import { RemixUIStatusBar } from '@remix-ui/statusbar' +import { FilePanelType } from '@remix-ui/workspace' +import { VerticalIcons } from './vertical-icons' + +const statusBarProfile: PluginProfile = { + name: 'statusBar', + displayName: 'Status Bar', + description: 'Remix IDE status bar panel', + methods: ['isAIActive'], + version: packageJson.version, +} + +export class StatusBar extends Plugin implements StatusBarInterface { + htmlElement: HTMLDivElement + events: EventEmitter + filePanelPlugin: FilePanelType + verticalIcons: VerticalIcons + dispatch: React.Dispatch = () => {} + currentWorkspaceName: string = '' + isGitRepo: boolean = false + isAiActive: boolean = false + constructor(filePanel: FilePanelType, veritcalIcons: VerticalIcons) { + super(statusBarProfile) + this.filePanelPlugin = filePanel + this.verticalIcons = veritcalIcons + this.events = new EventEmitter() + this.htmlElement = document.createElement('div') + this.htmlElement.setAttribute('id', 'status-bar') + this.filePanelPlugin + } + + async isWorkspaceAGitRepo() { + const isGit = await this.call('fileManager', 'isGitRepo') + if (!isGit) return + this.isGitRepo = true + this.renderComponent() + } + + async setCurrentGitWorkspaceName() { + if (!this.isGitRepo) return + const workspaceName = localStorage.getItem('currentWorkspace') + workspaceName && workspaceName.length > 0 ? this.currentWorkspaceName = workspaceName : this.currentWorkspaceName = 'unknown' + this.renderComponent() + } + + async isAIActive() { + let aiActive + this.on('settings', 'copilotChoiceUpdated', async (isChecked) => { + aiActive = isChecked + this.isAiActive = isChecked + }) + this.renderComponent() + return aiActive + } + + onActivation(): void { + this.on('filePanel', 'workspaceInitializationCompleted', async () => { + const isGit = await this.call('fileManager', 'isGitRepo') + if (!isGit) return + const workspaceName = localStorage.getItem('currentWorkspace') + workspaceName && workspaceName.length > 0 ? this.currentWorkspaceName = workspaceName : this.currentWorkspaceName = '' + }) + this.on('filePanel', 'switchToWorkspace', async (workspace: string) => { + console.log('from status bar switchToWorkspace') + await this.isWorkspaceAGitRepo() + if (!this.isGitRepo) { + this.currentWorkspaceName = 'Not a git repo' + return + } + const workspaceName = localStorage.getItem('currentWorkspace') + workspaceName && workspaceName.length > 0 ? this.currentWorkspaceName = workspaceName : this.currentWorkspaceName = 'error' + }) + this.on('settings', 'copilotChoiceChanged', (isAiActive) => { + this.isAiActive = isAiActive + }) + this.renderComponent() + } + + setDispatch(dispatch: React.Dispatch) { + this.dispatch = dispatch + } + + renderComponent() { + this.dispatch({ + plugins: this, + }) + } + + updateComponent(state: any) { + return + } + + render() { + return ( +
+ +
+ ) + } +} diff --git a/apps/remix-ide/src/app/panels/file-panel.js b/apps/remix-ide/src/app/panels/file-panel.js index d8f55573f5..a709692452 100644 --- a/apps/remix-ide/src/app/panels/file-panel.js +++ b/apps/remix-ide/src/app/panels/file-panel.js @@ -34,6 +34,7 @@ const profile = { methods: [ 'createNewFile', 'uploadFile', + 'echoCall', 'getCurrentWorkspace', 'getAvailableWorkspaceName', 'getWorkspaces', @@ -43,7 +44,7 @@ const profile = { 'registerContextMenuItem', 'renameWorkspace', 'deleteWorkspace', - 'loadTemplate', + 'loadTemplate', 'clone', 'isExpanded', 'isGist' @@ -154,10 +155,10 @@ module.exports = class Filepanel extends ViewPlugin { return this.workspaces } - getAvailableWorkspaceName(name) { + getAvailableWorkspaceName(name) { if (!this.workspaces) return name let index = 1 - let workspace = this.workspaces.find((workspace) => workspace.name === name + ' - ' + index) + let workspace = this.workspaces.find((workspace) => workspace.name === name + ' - ' + index) while (workspace) { index++ workspace = this.workspaces.find((workspace) => workspace.name === name + ' - ' + index) diff --git a/apps/remix-ide/src/app/tabs/locales/en/home.json b/apps/remix-ide/src/app/tabs/locales/en/home.json index be2804d909..9d78937c91 100644 --- a/apps/remix-ide/src/app/tabs/locales/en/home.json +++ b/apps/remix-ide/src/app/tabs/locales/en/home.json @@ -29,7 +29,7 @@ "home.dgitPluginDesc": "Add source control to your projects.", "home.oneClickDappDesc": "Quickly generate smart contract interfaces", "home.getStarted": "Get Started", - "home.projectTemplates": "Project Templates", + "home.projectTemplates": "Explore. Prototype. Create.", "home.blankTemplateDesc": "Create an empty workspace.", "home.remixDefaultTemplateDesc": "Create a workspace with sample files.", "home.ozerc20TemplateDesc": "Create an ERC20 token by importing OpenZeppelin library.", @@ -39,7 +39,7 @@ "home.zeroxErc20TemplateDesc": "Create an ERC20 token by importing 0xProject contract.", "home.learn": "Learn", "home.learnEth1": "Remix Basics", - "home.learnEth1Desc":"An introduction to Remix's interface and basic operations.", + "home.learnEth1Desc": "An introduction to Remix's interface and basic operations.", "home.learnEth2": "Intro to Solidity", "home.learnEth2Desc": "Interactively learn Solidity beginner concepts.", "home.remixAdvanced": "Deploying with Libraries", @@ -56,15 +56,16 @@ "home.remixDesktop": "Remix Desktop", "home.searchDocumentation": "Search Documentation", "home.files": "Files", - "home.newFile": "New File", + "home.newFile": "New", "home.startCoding": "Start Coding", "home.startCodingPlayground": "Open a playground for prototyping and simple learning", - "home.openFile": "Open File", + "home.openFile": "Open", "home.openFileTooltip": "Open a File from your File System", - "home.accessFileSystem": "Access File System", + "home.accessFileSystem": "Connect to Local Filesystem", "home.loadFrom": "Load from", "home.resources": "Resources", "home.connectToLocalhost": "Connect to Localhost", "home.seeAllTutorials": "See all tutorials", "home.maintainedByRemix": "Maintained by Remix" } + diff --git a/apps/remix-ide/src/app/tabs/settings-tab.tsx b/apps/remix-ide/src/app/tabs/settings-tab.tsx index 49571922eb..3878b29e89 100644 --- a/apps/remix-ide/src/app/tabs/settings-tab.tsx +++ b/apps/remix-ide/src/app/tabs/settings-tab.tsx @@ -97,6 +97,7 @@ module.exports = class SettingsTab extends ViewPlugin { updateCopilotChoice(isChecked) { this.config.set('settings/copilot/suggest/activate', isChecked) this.useCopilot = isChecked + this.emit('copilotChoiceUpdated', isChecked) this.dispatch({ ...this }) diff --git a/apps/remix-ide/src/remixAppManager.js b/apps/remix-ide/src/remixAppManager.js index c52b50c081..07958b4491 100644 --- a/apps/remix-ide/src/remixAppManager.js +++ b/apps/remix-ide/src/remixAppManager.js @@ -31,6 +31,7 @@ let requiredModules = [ // services + layout views + system views 'menuicons', 'filePanel', 'terminal', + 'statusBar', 'settings', 'pluginManager', 'tabs', @@ -103,7 +104,7 @@ const isVM = (name) => { } export function isNative(name) { - + // nativePlugin allows to bypass the permission request const nativePlugins = [ 'vyper', @@ -117,6 +118,7 @@ export function isNative(name) { 'solhint', 'solidityUnitTesting', 'layout', + 'statusBar', 'notification', 'hardhat-provider', 'ganache-provider', diff --git a/apps/remix-ide/src/types/index.d.ts b/apps/remix-ide/src/types/index.d.ts new file mode 100644 index 0000000000..f45c485c3c --- /dev/null +++ b/apps/remix-ide/src/types/index.d.ts @@ -0,0 +1,19 @@ +export interface PluginProfile { + name: string + displayName: string + description: string + keywords?: string[] + icon?: string + url?: string + methods?: string[] + events?: string[] + version?: string +} + +export interface StatusBarInterface { + htmlElement: HTMLDivElement + events: EventEmitter + filePanelPlugin: FilePanelType + dispatch: React.Dispatch + setDispatch(dispatch: React.Dispatch): void +} diff --git a/apps/vyper/src/app/utils/compiler.tsx b/apps/vyper/src/app/utils/compiler.tsx index 3a7f4fbd0b..7fdf99e456 100644 --- a/apps/vyper/src/app/utils/compiler.tsx +++ b/apps/vyper/src/app/utils/compiler.tsx @@ -1,9 +1,8 @@ -import { ABIDescription} from '@remixproject/plugin-api' +import { ABIDescription } from '@remixproject/plugin-api' import axios from 'axios' import { remixClient } from './remix-client' import _ from 'lodash' - export interface Contract { name: string content: string @@ -72,8 +71,8 @@ const buildError = (output) => { const line = output.line if (line) { const lineColumnPos = { - start: {line: line - 1, column: 10}, - end: {line: line - 1, column: 10} + start: { line: line - 1, column: 10 }, + end: { line: line - 1, column: 10 } } // remixClient.highlight(lineColumnPos as any, _contract.name, '#e0b4b4') } else { @@ -92,8 +91,8 @@ const buildError = (output) => { } if (location?.length > 0) { const lineColumnPos = { - start: {line: parseInt(location[0]) - 1, column: 10}, - end: {line: parseInt(location[0]) - 1, column: 10} + start: { line: parseInt(location[0]) - 1, column: 10 }, + end: { line: parseInt(location[0]) - 1, column: 10 } } // remixClient.highlight(lineColumnPos as any, _contract.name, message) } @@ -175,13 +174,11 @@ export async function compile(url: string, contract: Contract): Promise { throw new Error('Use extension .vy for Vyper.') } - - let contractName = contract['name'] const compilePackage = { manifest: 'ethpm/3', sources: { - [contractName] : {content : fixContractContent(contract.content)} + [contractName] : { content : fixContractContent(contract.content) } } } let response = await axios.post(`${url}compile`, compilePackage ) @@ -266,7 +263,6 @@ export function toStandardOutput(fileName: string, compilationResult: any): any } } - export async function compileContract(contract: string, compilerUrl: string, setOutput?: any, setLoadingSpinnerState?: React.Dispatch>, spinner?: boolean) { remixClient.eventEmitter.emit('resetCompilerState', {}) spinner && spinner === true ? setLoadingSpinnerState && setLoadingSpinnerState(true) : null @@ -301,7 +297,7 @@ export async function compileContract(contract: string, compilerUrl: string, set }) setLoadingSpinnerState && setLoadingSpinnerState(false) - remixClient.eventEmitter.emit('setOutput', {status: 'failed', message: output.message, title: 'Error compiling...', line: output.line, column: output.column, key: 1 }) + remixClient.eventEmitter.emit('setOutput', { status: 'failed', message: output.message, title: 'Error compiling...', line: output.line, column: output.column, key: 1 }) output = null return } @@ -332,13 +328,10 @@ export async function compileContract(contract: string, compilerUrl: string, set }) setLoadingSpinnerState && setLoadingSpinnerState(false) - remixClient.eventEmitter.emit('setOutput', {status: 'failed', message: err.message}) + remixClient.eventEmitter.emit('setOutput', { status: 'failed', message: err.message }) } } - - - export type StandardOutput = { sources: { [fileName: string]: { diff --git a/libs/remix-ui/app/src/lib/remix-app/components/dragbar/dragbar.tsx b/libs/remix-ui/app/src/lib/remix-app/components/dragbar/dragbar.tsx index 4bbb9066e8..0c57ebaffb 100644 --- a/libs/remix-ui/app/src/lib/remix-app/components/dragbar/dragbar.tsx +++ b/libs/remix-ui/app/src/lib/remix-app/components/dragbar/dragbar.tsx @@ -23,7 +23,18 @@ const DragBar = (props: IRemixDragBarUi) => { if (props.hidden) { setDragBarPosX(offset) } else if (props.layoutPosition === 'left') { - setDragBarPosX(offset + props.refObject.current.offsetWidth) + const checkResolution = () => { + const width = window.innerWidth + const height = window.innerHeight + + if (height <= 781 && width <= 1150) { + setDragBarPosX(props.minWidth - 50) + } else { + setDragBarPosX(props.minWidth + 50) + } + } + checkResolution() + props.refObject.current.style.width = props.minWidth + 'px' } else if (props.layoutPosition === 'right') { setDragBarPosX(offset) } diff --git a/libs/remix-ui/app/src/lib/remix-app/remix-app.tsx b/libs/remix-ui/app/src/lib/remix-app/remix-app.tsx index 29dc3de3fd..aa1cc69fc6 100644 --- a/libs/remix-ui/app/src/lib/remix-app/remix-app.tsx +++ b/libs/remix-ui/app/src/lib/remix-app/remix-app.tsx @@ -217,8 +217,11 @@ const RemixApp = (props: IRemixAppUi) => { layoutPosition='right' > } +
{props.app.hiddenPanel.render()}
+
+ {props.app.statusBar.render()} +
-
{props.app.hiddenPanel.render()}
diff --git a/libs/remix-ui/app/src/lib/remix-app/style/remix-app.css b/libs/remix-ui/app/src/lib/remix-app/style/remix-app.css index a66b49dcff..8c56059bfb 100644 --- a/libs/remix-ui/app/src/lib/remix-app/style/remix-app.css +++ b/libs/remix-ui/app/src/lib/remix-app/style/remix-app.css @@ -20,6 +20,7 @@ pre { overflow : hidden; flex : 1; min-width : 320px; + padding-bottom : 1.4rem; } .iconpanel { display : flex; @@ -27,12 +28,17 @@ pre { overflow : hidden; width : 50px; user-select : none; + padding-bottom : 1.4rem; } .sidepanel { display : flex; flex-direction : row-reverse; width : 320px; transition : width 0.25s; + padding-bottom : 1.4rem; +} +.statusBar { + } .pinnedpanel { width : 320px; @@ -77,4 +83,4 @@ pre { width : 4rem; right : -10px; filter : opacity(0.5); -} \ No newline at end of file +} 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 766dd494fc..03e787e7ef 100644 --- a/libs/remix-ui/home-tab/src/lib/components/homeTabFeatured.tsx +++ b/libs/remix-ui/home-tab/src/lib/components/homeTabFeatured.tsx @@ -12,12 +12,9 @@ function HomeTabFeatured() { const themeFilter = useContext(ThemeContext) return ( -
- -
-
+
+
+
-
+
- +
{releaseDetails.version} {releaseDetails.title}
@@ -65,9 +62,9 @@ function HomeTabFeatured() {
-
+
- +
@@ -86,9 +83,9 @@ function HomeTabFeatured() {
-
+
- +
@@ -110,9 +107,9 @@ 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 51dc041cc7..017caea368 100644 --- a/libs/remix-ui/home-tab/src/lib/components/homeTabFeaturedPlugins.tsx +++ b/libs/remix-ui/home-tab/src/lib/components/homeTabFeaturedPlugins.tsx @@ -84,7 +84,7 @@ function HomeTabFeaturedPlugins({ plugin }: HomeTabFeaturedPluginsProps) { } return ( -
+
diff --git a/libs/remix-ui/home-tab/src/lib/components/homeTabFile.tsx b/libs/remix-ui/home-tab/src/lib/components/homeTabFile.tsx index ef07b97aaa..2e277f395e 100644 --- a/libs/remix-ui/home-tab/src/lib/components/homeTabFile.tsx +++ b/libs/remix-ui/home-tab/src/lib/components/homeTabFile.tsx @@ -1,8 +1,8 @@ /* eslint-disable @typescript-eslint/no-unused-vars */ import React, { useState, useRef, useReducer, useEffect } from 'react' import { FormattedMessage } from 'react-intl' -import { ModalDialog } from '@remix-ui/modal-dialog' // eslint-disable-line -import { Toaster } from '@remix-ui/toaster' // eslint-disable-line +import {ModalDialog} from '@remix-ui/modal-dialog' // eslint-disable-line +import {Toaster} from '@remix-ui/toaster' // eslint-disable-line const _paq = (window._paq = window._paq || []) // eslint-disable-line import { CustomTooltip } from '@remix-ui/helper' import { TEMPLATE_NAMES } from '@remix-ui/workspace' @@ -14,7 +14,7 @@ interface HomeTabFileProps { const loadingInitialState = { tooltip: '', showModalDialog: false, - importSource: '' + importSource: '', } const loadingReducer = (state = loadingInitialState, action) => { @@ -22,7 +22,7 @@ const loadingReducer = (state = loadingInitialState, action) => { ...state, tooltip: action.tooltip, showModalDialog: false, - importSource: '' + importSource: '', } } @@ -45,7 +45,7 @@ function HomeTabFile({ plugin }: HomeTabFileProps) { modalInfo: { title: '', loadItem: '', examples: [], prefix: '' }, importSource: '', toasterMsg: '', - recentWorkspaces: [] + recentWorkspaces: [], }) const [, dispatch] = useReducer(loadingReducer, loadingInitialState) @@ -71,7 +71,9 @@ function HomeTabFile({ plugin }: HomeTabFileProps) { if (!recents) { newRecents = [] } else { - newRecents = recents.filter((el) => { return el !== name}) + newRecents = recents.filter((el) => { + return el !== name + }) localStorage.setItem('recentWorkspaces', JSON.stringify(newRecents)) } setState((prevState) => { @@ -85,8 +87,7 @@ function HomeTabFile({ plugin }: HomeTabFileProps) { try { plugin.off('filePanel', 'setWorkspace') plugin.off('filePanel', 'workspaceDeleted') - } catch (e) { - } + } catch (e) {} } }, [plugin]) @@ -162,7 +163,6 @@ contract HelloWorld { } else { await plugin.call('fileManager', 'open', '/contracts/HelloWorld.sol') } - } const uploadFile = async (target) => { @@ -216,14 +216,7 @@ contract HelloWorld { return ( <> - hideFullMessage()} - okFn={() => processLoading(state.modalInfo.title)} - > + hideFullMessage()} okFn={() => processLoading(state.modalInfo.title)}>
{state.modalInfo.loadItem !== '' && Enter the {state.modalInfo.loadItem} you would like to load.} {state.modalInfo.examples.length !== 0 && ( @@ -236,9 +229,9 @@ contract HelloWorld { {state.modalInfo.prefix && ipfs://}
- -
-
- } - tooltipTextClasses="border bg-light text-dark p-1 pr-3" - > - - - } - tooltipTextClasses="border bg-light text-dark p-1 pr-3" - > - - - { - event.stopPropagation() - plugin.verticalIcons.select('filePanel') - uploadFile(event.target) - }} - multiple - /> - - - } - tooltipTextClasses="border bg-light text-dark p-1 pr-3" - > - - -
+
{(state.recentWorkspaces[0] || state.recentWorkspaces[1] || state.recentWorkspaces[2]) && ( -
+
{state.recentWorkspaces[0] && state.recentWorkspaces[0] !== '' && ( handleSwichToRecentWorkspace(e, state.recentWorkspaces[0])}> @@ -328,36 +270,63 @@ contract HelloWorld {
)}
- -
- - + + } tooltipTextClasses="border bg-light text-dark p-1 pr-3"> + + + { + event.stopPropagation() + plugin.verticalIcons.select('filePanel') + uploadFile(event.target) + }} + multiple + /> + + + + + - - + + + +
+
+
+ } tooltipTextClasses="border bg-light text-dark p-1 pr-3"> + + +
diff --git a/libs/remix-ui/home-tab/src/lib/components/homeTabGetStarted.tsx b/libs/remix-ui/home-tab/src/lib/components/homeTabGetStarted.tsx index e7629edea1..a986cebbfb 100644 --- a/libs/remix-ui/home-tab/src/lib/components/homeTabGetStarted.tsx +++ b/libs/remix-ui/home-tab/src/lib/components/homeTabGetStarted.tsx @@ -1,13 +1,12 @@ /* eslint-disable @typescript-eslint/no-unused-vars */ -import React, { useEffect, useRef, useContext } from 'react' +import React, { useEffect, useRef, useContext, SyntheticEvent, useState } from 'react' import { useIntl, FormattedMessage } from 'react-intl' -import { TEMPLATE_NAMES,TEMPLATE_METADATA } from '@remix-ui/workspace' +import { TEMPLATE_NAMES, TEMPLATE_METADATA } from '@remix-ui/workspace' import { ThemeContext } from '../themeContext' -import Carousel from 'react-multi-carousel' import WorkspaceTemplate from './workspaceTemplate' import 'react-multi-carousel/lib/styles.css' -import CustomNavButtons from './customNavButtons' import { appPlatformTypes, platformContext } from '@remix-ui/app' +import { CustomTooltip } from '@remix-ui/helper' declare global { interface Window { @@ -19,12 +18,65 @@ interface HomeTabGetStartedProps { plugin: any } +type WorkspaceTemplate = { + gsID: string + workspaceTitle: string + description: string + projectLogo: string + templateName: string +} + +const workspaceTemplates: WorkspaceTemplate[] = [ + { + gsID: 'sUTLogo', + workspaceTitle: 'Start Coding', + description: 'Create a new project using this template.', + projectLogo: 'assets/img/remixverticaltextLogo.png', + templateName: 'remixDefault', + }, + { + gsID: 'sUTLogo', + workspaceTitle: 'Circom', + description: 'Create a new ZK Project with Circom using this template.', + projectLogo: 'assets/img/circom.webp', + templateName: 'semaphore', + }, + { + gsID: 'sUTLogo', + workspaceTitle: 'Uniswap', + description: 'Create a new MultiSig wallet using this template.', + projectLogo: 'assets/img/gnosissafeLogo.png', + templateName: 'uniswapV4Template', + }, + { + gsID: 'sUTLogo', + workspaceTitle: 'ERC20', + description: 'Create a new ERC20 token using this template.', + projectLogo: 'assets/img/oxprojectLogo.png', + templateName: 'ozerc20', + }, + { + gsID: 'sUTLogo', + workspaceTitle: 'NFT / ERC721', + description: 'Create a new ERC721 token using this template.', + projectLogo: 'assets/img/openzeppelinLogo.png', + templateName: 'ozerc721', + }, + { + gsID: 'sUTLogo', + workspaceTitle: 'MultiSig', + description: 'Create a new MultiSig wallet using this template.', + projectLogo: 'assets/img/gnosissafeLogo.png', + templateName: 'gnosisSafeMultisig', + }, +] + function HomeTabGetStarted({ plugin }: HomeTabGetStartedProps) { const platform = useContext(platformContext) const themeFilter = useContext(ThemeContext) + const intl = useIntl() const carouselRef = useRef({}) const carouselRefDiv = useRef(null) - const intl = useIntl() useEffect(() => { document.addEventListener('wheel', handleScroll) @@ -61,8 +113,7 @@ function HomeTabGetStarted({ plugin }: HomeTabGetStartedProps) { } const createWorkspace = async (templateName) => { - - if (platform === appPlatformTypes.desktop){ + if (platform === appPlatformTypes.desktop) { await plugin.call('remix-templates', 'loadTemplateInNewWindow', templateName) return } @@ -92,90 +143,45 @@ function HomeTabGetStarted({ plugin }: HomeTabGetStartedProps) { return (
-
- } - tooltipTextClasses="border bg-light text-dark p-1 pr-3" - > - - - } - tooltipTextClasses="border bg-light text-dark p-1 pr-3" - > - - - } - tooltipTextClasses="border bg-light text-dark p-1 pr-3" - > - - - } - tooltipTextClasses="border bg-light text-dark p-1 pr-3" - > - - - - } - tooltipTextClasses="border bg-light text-dark p-1 pr-3" - > - - + {iconButtons.map((button, index) => ( + + + + ))}
@@ -149,27 +139,19 @@ function HomeTabTitle() { _paq.push(['trackEvent', 'hometab', 'header', 'webSite'])} target="__blank" href="https://remix-project.org"> - _paq.push(['trackEvent', 'hometab', 'header', 'documentation'])} target="__blank" href="https://remix-ide.readthedocs.io/en/latest" > - - _paq.push(['trackEvent', 'hometab', 'header', 'remixPlugin'])} - target="__blank" - href="https://remix-plugin-docs.readthedocs.io/en/latest/" - > - - + */} _paq.push(['trackEvent', 'hometab', 'header', 'remixDesktop'])} target="__blank" - href="https://github.com/ethereum/remix-desktop/releases" + href="https://github.com/remix-project-org/remix-desktop-insiders" > diff --git a/libs/remix-ui/home-tab/src/lib/components/homeTablangOptions.tsx b/libs/remix-ui/home-tab/src/lib/components/homeTablangOptions.tsx index 226fdc17a5..0bd79445e9 100644 --- a/libs/remix-ui/home-tab/src/lib/components/homeTablangOptions.tsx +++ b/libs/remix-ui/home-tab/src/lib/components/homeTablangOptions.tsx @@ -2,6 +2,7 @@ import React, { useEffect, useState } from 'react' import { Dropdown, DropdownButton } from 'react-bootstrap' import DropdownItem from 'react-bootstrap/DropdownItem' import { localeLang } from './types/carouselTypes' +import { FormattedMessage } from 'react-intl' export function LanguageOptions({ plugin }: { plugin: any }) { const [langOptions, setLangOptions] = useState() @@ -24,7 +25,10 @@ export function LanguageOptions({ plugin }: { plugin: any }) { return ( <> -
+
+ {langOptions} diff --git a/libs/remix-ui/home-tab/src/lib/remix-ui-home-tab.css b/libs/remix-ui/home-tab/src/lib/remix-ui-home-tab.css index 4ceded21fc..efdb012c7d 100644 --- a/libs/remix-ui/home-tab/src/lib/remix-ui-home-tab.css +++ b/libs/remix-ui/home-tab/src/lib/remix-ui-home-tab.css @@ -76,7 +76,7 @@ text-align: left; } .remixui_home_cursorStyle { - cursor: pointer; + cursor: pointer; font-weight: 900; } .remixui_home_envButton { @@ -114,3 +114,36 @@ background-color: var(--body-bg); color: var(--text); } + +.remixui_recentworkspace { + height: 2.4rem; +} + +.remixui_carouselImage { + flex: 1; + height: 20rem; + width: 20rem; +} + +.remixui_carouselbox { + min-height: 25.12rem; +} + +.remix_ui-carousel-container { + container: remix_ui-carousel-container / inline-size; +} + +@container remix_ui-carousel-container (inline-size < 700px) { + .remix_ui-carouselbox { + min-height: 20rem; + margin-right: 10rem; + } + .remixui_carouselImage { + height: 12.5rem; + width: 12.5rem; + } + + .remixui_recentworkspace { + height: 0.2rem; + } +} diff --git a/libs/remix-ui/home-tab/src/lib/remix-ui-home-tab.tsx b/libs/remix-ui/home-tab/src/lib/remix-ui-home-tab.tsx index 2373659001..fac0ec5bab 100644 --- a/libs/remix-ui/home-tab/src/lib/remix-ui-home-tab.tsx +++ b/libs/remix-ui/home-tab/src/lib/remix-ui-home-tab.tsx @@ -32,6 +32,7 @@ export const RemixUiHomeTab = (props: RemixUiHomeTabProps) => { }>({ themeQuality: themes.light }) + const [carouselWidth, setCarouselWidth] = useState(65) useEffect(() => { plugin.call('theme', 'currentTheme').then((theme) => { @@ -54,23 +55,39 @@ export const RemixUiHomeTab = (props: RemixUiHomeTabProps) => { }) }, []) + useEffect(() => { + const checkResolution = () => { + const width = window.innerWidth + const height = window.innerHeight + + if (height < 781 && width < 1150) { + setCarouselWidth(75) + } + } + checkResolution() + + return () => { + checkResolution() + } + }, []) + + // border-right return ( -
+
-
-
+
+
+ {!(platform === appPlatformTypes.desktop) ? : } - + {/* */}
-
+
- -
diff --git a/libs/remix-ui/panel/src/index.ts b/libs/remix-ui/panel/src/index.ts index 11b5ef7c67..5cb90eecc4 100644 --- a/libs/remix-ui/panel/src/index.ts +++ b/libs/remix-ui/panel/src/index.ts @@ -1,4 +1,4 @@ export { default as RemixPluginPanel } from './lib/plugins/remix-ui-panel' export { default as RemixUIMainPanel } from './lib/main/main-panel' export { PluginRecord } from './lib/types' -export { default as RemixUIPanelHeader } from './lib/plugins/panel-header' \ No newline at end of file +export { default as RemixUIPanelHeader } from './lib/plugins/panel-header' diff --git a/libs/remix-ui/panel/src/lib/plugins/panel.css b/libs/remix-ui/panel/src/lib/plugins/panel.css index b872ff1ada..119b8cfa32 100644 --- a/libs/remix-ui/panel/src/lib/plugins/panel.css +++ b/libs/remix-ui/panel/src/lib/plugins/panel.css @@ -110,3 +110,7 @@ iframe { .highlight { animation: highlight 2s forwards; } + +.remixui_height { + height: 97vh; +} diff --git a/libs/remix-ui/panel/src/lib/types/index.ts b/libs/remix-ui/panel/src/lib/types/index.ts index c3913340cc..4deccc1dbd 100644 --- a/libs/remix-ui/panel/src/lib/types/index.ts +++ b/libs/remix-ui/panel/src/lib/types/index.ts @@ -1,4 +1,5 @@ import { Profile } from '@remixproject/plugin-utils' +import EventEmitter from 'events' export type PluginRecord = { profile: Profile @@ -8,3 +9,22 @@ export type PluginRecord = { class?: string minimized?: boolean } + +export interface PluginProfile { + name: string + displayName: string + description: string + keywords?: string[] + icon?: string + url?: string + methods?: string[] + events?: string[] + version?: string +} + +export interface StatusBarInterface extends Plugin { + htmlElement: HTMLDivElement + events: EventEmitter + dispatch: React.Dispatch + setDispatch(dispatch: React.Dispatch): void +} diff --git a/libs/remix-ui/statusbar/src/css/statusbar.css b/libs/remix-ui/statusbar/src/css/statusbar.css new file mode 100644 index 0000000000..15976801a2 --- /dev/null +++ b/libs/remix-ui/statusbar/src/css/statusbar.css @@ -0,0 +1,23 @@ + +remixui_statusbar:hover { + cursor: pointer; +} + +.remixui_statusbar_gitstatus +.remixui_statusbar_gitstatus:hover { + cursor: pointer; +} + +/** + * approximately same height with vscode statusbar + **/ +.remixui_statusbar_height { + height: 21px; +} + +.remixui_statusbar_activelink { + text-decoration: none; +} +.remixui_statusbar_activelink:active { + color: var(--danger); +} diff --git a/libs/remix-ui/statusbar/src/index.ts b/libs/remix-ui/statusbar/src/index.ts new file mode 100644 index 0000000000..9c8a70edde --- /dev/null +++ b/libs/remix-ui/statusbar/src/index.ts @@ -0,0 +1,2 @@ +export * from './lib/remixui-statusbar-panel' +export { StatusBarInterface } from './lib/types' diff --git a/libs/remix-ui/statusbar/src/lib/components/aiStatus.tsx b/libs/remix-ui/statusbar/src/lib/components/aiStatus.tsx new file mode 100644 index 0000000000..5490d5f9d9 --- /dev/null +++ b/libs/remix-ui/statusbar/src/lib/components/aiStatus.tsx @@ -0,0 +1,44 @@ +// eslint-disable-next-line @nrwl/nx/enforce-module-boundaries +import { StatusBar } from 'apps/remix-ide/src/app/components/status-bar' +import { CustomTooltip } from '@remix-ui/helper' +import React, { useEffect, useState } from 'react' + +interface AIStatusProps { + plugin: StatusBar + isAiActive: boolean + setIsAiActive: (isAiActive: boolean) => void + aiActive: () => Promise +} + +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) + }) + } + run() + }, [props.plugin.isAiActive, props.isAiActive]) + + useEffect(() => { + const run = async () => { + props.plugin.on('settings', 'copilotChoiceUpdated', async (isChecked) => { + await props.plugin.isAIActive() + setCopilotActive(isChecked) + }) + } + run() + }, [props.plugin.isAiActive]) + return ( + +
+ + Remix Copilot +
+
+ ) +} diff --git a/libs/remix-ui/statusbar/src/lib/components/gitStatus.tsx b/libs/remix-ui/statusbar/src/lib/components/gitStatus.tsx new file mode 100644 index 0000000000..4f579e2982 --- /dev/null +++ b/libs/remix-ui/statusbar/src/lib/components/gitStatus.tsx @@ -0,0 +1,88 @@ +import React, { useEffect, Dispatch } from 'react' +// eslint-disable-next-line @nrwl/nx/enforce-module-boundaries +import { StatusBar } from 'apps/remix-ide/src/app/components/status-bar' +import '../../css/statusbar.css' +import { CustomTooltip } from '@remix-ui/helper' + +export interface GitStatusProps { + plugin: StatusBar + gitBranchName: string + setGitBranchName: Dispatch> +} + +export default function GitStatus({ plugin, gitBranchName, setGitBranchName }: GitStatusProps) { + + useEffect(() => { + const run = async () => { + plugin.on('filePanel', 'setWorkspace', async (workspace) => { + const isGit = await plugin.call('fileManager', 'isGitRepo') + if (isGit) { + setGitBranchName(workspace.name) + } else { + setGitBranchName('Not a git repo') + } + }) + } + run() + }, [gitBranchName, plugin.isGitRepo]) + + useEffect(() => { + const run = async () => { + plugin.on('filePanel', 'workspaceInitializationCompleted', async () => { + const isGit = await plugin.call('fileManager', 'isGitRepo') + if (isGit) { + const workspace = localStorage.getItem('currentWorkspace') + setGitBranchName(workspace) + } else { + setGitBranchName('Not a git repo') + } + }) + } + run() + }, [gitBranchName, plugin.isGitRepo]) + + useEffect(() => { + const run = async () => { + plugin.on('dGitProvider', 'init', async () => { + const isGit = await plugin.call('fileManager', 'isGitRepo') + if (isGit) { + const workspace = localStorage.getItem('currentWorkspace') + setGitBranchName(workspace) + } + }) + } + run() + }, [gitBranchName, plugin.isGitRepo]) + + const lightDgitUp = async () => { + const isActive = await plugin.call('manager', 'isActive', 'dgit') + const isGit = await plugin.call('fileManager', 'isGitRepo') + if (!isActive) await plugin.call('manager', 'activatePlugin', 'dgit') + if (gitBranchName.length > 0 && isGit) { + plugin.verticalIcons.select('dgit') + } + } + + const initializeNewGitRepo = async () => { + await plugin.call('dGitProvider', 'init') + const isActive = await plugin.call('manager', 'isActive', 'dgit') + if (!isActive) await plugin.call('manager', 'activatePlugin', 'dgit') + // plugin.verticalIcons.select('dgit') + } + + return ( + +
await lightDgitUp()} + > + {gitBranchName.length > 0 && gitBranchName !== 'Not a git repo' ? + : Initialize as git repo} + {gitBranchName.length > 0 && gitBranchName !== 'Not a git repo' && {gitBranchName}} + {gitBranchName.length > 0 && gitBranchName !== 'Not a git repo' && } +
+
+ ) +} diff --git a/libs/remix-ui/statusbar/src/lib/components/scamAlertStatus.tsx b/libs/remix-ui/statusbar/src/lib/components/scamAlertStatus.tsx new file mode 100644 index 0000000000..2fe18b909f --- /dev/null +++ b/libs/remix-ui/statusbar/src/lib/components/scamAlertStatus.tsx @@ -0,0 +1,27 @@ +import React from 'react' +import { FormattedMessage } from 'react-intl' +import { ExtendedRefs, ReferenceType } from '@floating-ui/react' +import { CustomTooltip } from '@remix-ui/helper' + +export interface ScamAlertStatusProps { + refs: ExtendedRefs + getReferenceProps: (userProps?: React.HTMLProps | undefined) => Record +} + +export default function ScamAlertStatus ({ refs, getReferenceProps }: ScamAlertStatusProps) { + + return ( + <> + +
+ + + + +
+
+ + ) +} diff --git a/libs/remix-ui/statusbar/src/lib/components/scamDetails.tsx b/libs/remix-ui/statusbar/src/lib/components/scamDetails.tsx new file mode 100644 index 0000000000..1f971f72ac --- /dev/null +++ b/libs/remix-ui/statusbar/src/lib/components/scamDetails.tsx @@ -0,0 +1,48 @@ +import { ExtendedRefs, ReferenceType } from '@floating-ui/react' +import React, { CSSProperties } from 'react' +import { FormattedMessage } from 'react-intl' +import { ScamAlert } from '../remixui-statusbar-panel' +import '../../css/statusbar.css' + +const _paq = (window._paq = window._paq || []) // eslint-disable-line + +export interface ScamDetailsProps { + refs: ExtendedRefs + floatStyle: CSSProperties + getFloatingProps: (userProps?: React.HTMLProps | undefined) => Record + scamAlerts: ScamAlert[] +} + +export default function ScamDetails ({ refs, floatStyle, scamAlerts }: ScamDetailsProps) { + + return ( + + ) +} diff --git a/libs/remix-ui/statusbar/src/lib/remixui-statusbar-panel.tsx b/libs/remix-ui/statusbar/src/lib/remixui-statusbar-panel.tsx new file mode 100644 index 0000000000..77e8f3cc50 --- /dev/null +++ b/libs/remix-ui/statusbar/src/lib/remixui-statusbar-panel.tsx @@ -0,0 +1,86 @@ +import React, { useEffect, useState } from 'react' +import GitStatus from './components/gitStatus' +import AIStatus from './components/aiStatus' +import ScamAlertStatus from './components/scamAlertStatus' +import ScamDetails from './components/scamDetails' +import { FloatingFocusManager, autoUpdate, flip, offset, shift, size, useClick, useDismiss, useFloating, useInteractions, useRole } from '@floating-ui/react' +import axios from 'axios' +// eslint-disable-next-line @nrwl/nx/enforce-module-boundaries +import { StatusBar } from 'apps/remix-ide/src/app/components/status-bar' + +export interface RemixUIStatusBarProps { + statusBarPlugin: StatusBar +} + +export type ScamAlert = { + message: string + url: string +} + +export function RemixUIStatusBar({ statusBarPlugin }: RemixUIStatusBarProps) { + const [showScamDetails, setShowScamDetails] = useState(false) + const [scamAlerts, setScamAlerts] = useState([]) + const [gitBranchName, setGitBranchName] = useState('') + const [isAiActive, setIsAiActive] = useState(false) + const { refs, context, floatingStyles } = useFloating({ + open: showScamDetails, + onOpenChange: setShowScamDetails, + middleware: [offset(10), flip({ fallbackAxisSideDirection: 'end' }), shift({ + mainAxis: true, padding: 10 + }), size({ + apply({ availableWidth, availableHeight, elements, ...state }) { + console.log(state) + Object.assign(elements.floating.style, { + maxWidth: `${availableWidth}`, + maxHeight: `auto` + }) + } + })], + whileElementsMounted: autoUpdate, + }) + const click = useClick(context) + const dismiss = useDismiss(context) + const role = useRole(context) + const { getReferenceProps, getFloatingProps } = useInteractions([click, dismiss, role]) + + useEffect(() => { + const abortController = new AbortController() + const signal = abortController.signal + async function getScamAlerts() { + const response = await axios.get('https://raw.githubusercontent.com/remix-project-org/remix-dynamics/main/ide/scam-alerts.json', { signal }) + if (signal.aborted) return + setScamAlerts(response.data.alerts) + } + getScamAlerts() + return () => { + abortController.abort() + } + }, []) + + const lightAiUp = async () => { + const aiActive = await statusBarPlugin.call('settings', 'get', 'settings/copilot/suggest/activate') + if (!aiActive) return + setIsAiActive(aiActive) + return aiActive + } + + return ( + <> + {showScamDetails && ( + + + + )} +
+
+ +
+
+
+ + +
+
+ + ) +} diff --git a/libs/remix-ui/statusbar/src/lib/types/index.ts b/libs/remix-ui/statusbar/src/lib/types/index.ts new file mode 100644 index 0000000000..19a4db6163 --- /dev/null +++ b/libs/remix-ui/statusbar/src/lib/types/index.ts @@ -0,0 +1,27 @@ +import EventEmitter from 'events' +import { Plugin } from '@remixproject/engine' +import { FilePanelType } from '@remix-ui/workspace' +// eslint-disable-next-line @nrwl/nx/enforce-module-boundaries +import { VerticalIcons } from 'apps/remix-ide/src/app/components/vertical-icons' +export interface PluginProfile { + name: string + displayName: string + description: string + keywords?: string[] + icon?: string + url?: string + methods?: string[] + events?: string[] + version?: string +} + +export interface StatusBarInterface extends Plugin { + htmlElement: HTMLDivElement + events: EventEmitter + dispatch: React.Dispatch + filePanel: FilePanelType + verticalIcons: VerticalIcons + setDispatch(dispatch: React.Dispatch): void + getGitBranchName: () => Promise + currentWorkspaceName: string +} diff --git a/libs/remix-ui/terminal/src/lib/remix-ui-terminal.tsx b/libs/remix-ui/terminal/src/lib/remix-ui-terminal.tsx index 7936cda55e..9304f56d3d 100644 --- a/libs/remix-ui/terminal/src/lib/remix-ui-terminal.tsx +++ b/libs/remix-ui/terminal/src/lib/remix-ui-terminal.tsx @@ -597,7 +597,7 @@ export const RemixUiTerminal = (props: RemixUiTerminalProps) => { return ( ( props.visible && -
+
{handleAutoComplete()}
diff --git a/libs/remix-ui/toaster/src/lib/toaster.tsx b/libs/remix-ui/toaster/src/lib/toaster.tsx index 32a68e005e..baca48b9d2 100644 --- a/libs/remix-ui/toaster/src/lib/toaster.tsx +++ b/libs/remix-ui/toaster/src/lib/toaster.tsx @@ -131,7 +131,7 @@ export const Toaster = (props: ToasterProps) => { {!state.hide && (
diff --git a/libs/remix-ui/vertical-icons-panel/src/lib/remix-ui-vertical-icons-panel.css b/libs/remix-ui/vertical-icons-panel/src/lib/remix-ui-vertical-icons-panel.css index 6fbe1b6fd8..cdfacf1752 100644 --- a/libs/remix-ui/vertical-icons-panel/src/lib/remix-ui-vertical-icons-panel.css +++ b/libs/remix-ui/vertical-icons-panel/src/lib/remix-ui-vertical-icons-panel.css @@ -84,7 +84,7 @@ padding-left: 5px; padding-right: 5px; } - + .remixui_verticalIconContextcontainer { display: block; position: fixed; @@ -105,7 +105,7 @@ .remixui_liitem:hover { background-color: var(--secondary); } - + .remixui_scrollbar { overflow-y: scroll; scrollbar-width: none; /* Firefox hide scrollbar */ @@ -141,6 +141,10 @@ flex-basis: 50px; } + .remixui_icons_height { + height: 97vh; + } + #menuitems { list-style: none; margin: 0px; diff --git a/libs/remix-ui/vertical-icons-panel/src/lib/remix-ui-vertical-icons-panel.tsx b/libs/remix-ui/vertical-icons-panel/src/lib/remix-ui-vertical-icons-panel.tsx index ffb7d3bae5..108052d482 100644 --- a/libs/remix-ui/vertical-icons-panel/src/lib/remix-ui-vertical-icons-panel.tsx +++ b/libs/remix-ui/vertical-icons-panel/src/lib/remix-ui-vertical-icons-panel.tsx @@ -69,7 +69,7 @@ const RemixUiVerticalIconsPanel = ({ verticalIconsPlugin, icons }: RemixUiVertic return (
-
+