Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 51 additions & 0 deletions apps/remix-ide-e2e/src/tests/pinned_plugin.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
'use strict'
import { NightwatchBrowser } from 'nightwatch'
import init from '../helpers/init'

module.exports = {
'@disabled': true,
before: function (browser: NightwatchBrowser, done: VoidFunction) {
init(browser, done)
},

'Check if RemixAI plugin is pinned #group1': function (browser: NightwatchBrowser) {
browser
.waitForElementVisible('*[data-id="movePluginToLeft"]')
.waitForElementVisible('*[data-id="remix-ai-assistant-starter-0"]')
.click('*[data-id="movePluginToLeft"]')
.waitForElementVisible('*[data-pinnedPlugin="movePluginToRight-remixaiassistant"]')
},
'Pin Solidity Compiler plugin #group1': function (browser: NightwatchBrowser) {
browser
.clickLaunchIcon('solidity')
.pause(2000)
.waitForElementVisible('*[data-id="movePluginToRight"]')
.click('*[data-id="movePluginToRight"]')
.waitForElementVisible('*[data-pinnedPlugin="movePluginToLeft-solidity"]')
.clickLaunchIcon('filePanel')
},
'Close Solidity Compiler Plugin and restore it #group1': function (browser: NightwatchBrowser) {
browser
.waitForElementVisible('*[data-id="closePinnedPlugin"]')
.click('*[data-id="closePinnedPlugin"]')
.waitForElementNotVisible('*[data-pinnedplugin="movePluginToLeft-solidity"]')
.waitForElementVisible('*[data-id="restoreClosedPlugin"')
.click('*[data-id="restoreClosedPlugin"]')
.waitForElementVisible('*[data-pinnedplugin="movePluginToLeft-solidity"]')
},
'Swap pinned Solidity Compiler Plugin with RemixAI Assistant when pinned plugin is closed #group1': function (browser: NightwatchBrowser) {
browser
.refreshPage()
.waitForElementVisible('*[data-pinnedplugin="movePluginToLeft-solidity"]')
.waitForElementVisible('*[data-id="closePinnedPlugin"]')
.click('*[data-id="closePinnedPlugin"]')
.waitForElementVisible('*[data-id="restoreClosedPlugin"]')
.clickLaunchIcon('udapp')
.waitForElementVisible('*[data-pinnedplugin="movePluginToRight-udapp"]')
.click('*[data-id="movePluginToRight"]')
.waitForElementVisible('*[data-pinnedplugin="movePluginToLeft-udapp"]')
.waitForElementVisible('*[data-id="movePluginToRight"]')
.click('*[data-pinnedplugin="movePluginToLeft-udapp"]')
.end()
}
}
31 changes: 29 additions & 2 deletions apps/remix-ide/src/app/components/pinned-panel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,17 @@ const pinnedPanel = {
displayName: 'Pinned Panel',
description: 'Remix IDE pinned panel',
version: packageJson.version,
methods: ['addView', 'removeView', 'currentFocus', 'pinView', 'unPinView', 'highlight']
methods: ['addView', 'removeView', 'currentFocus', 'pinView', 'unPinView', 'highlight', 'closePlugin', 'maximizePlugin',
'getClosedPlugin'
],
events: ['pluginClosed', 'pluginMaximized']
}

export class PinnedPanel extends AbstractPanel {
dispatch: React.Dispatch<any> = () => {}
loggedState: Record<string, any>
highlightStamp: number
closedPlugin: any

constructor() {
super(pinnedPanel)
Expand All @@ -35,6 +39,9 @@ export class PinnedPanel extends AbstractPanel {
}

async pinView (profile, view) {
if (this.closedPlugin) {
this.maximizePlugin(this.closedPlugin)
}
const activePlugin = this.currentFocus()

if (activePlugin === profile.name) throw new Error(`Plugin ${profile.name} already pinned`)
Expand Down Expand Up @@ -62,6 +69,26 @@ export class PinnedPanel extends AbstractPanel {
this.emit('unPinnedPlugin', profile)
}

getClosedPlugin() {
return this.closedPlugin
}

async closePlugin (profile) {
const pinnedPanel = document.querySelector('#pinned-panel')
pinnedPanel.classList.add('d-none')
this.closedPlugin = profile
this.events.emit('pluginClosed', profile)
this.emit('pluginClosed', profile)
}

async maximizePlugin (profile) {
const pinnedPanel = document.querySelector('#pinned-panel')
pinnedPanel.classList.remove('d-none')
this.closedPlugin = null
this.events.emit('pluginMaximized', profile)
this.emit('pluginMaximized', profile)
}

highlight () {
this.highlightStamp = Date.now()
this.renderComponent()
Expand All @@ -78,7 +105,7 @@ export class PinnedPanel extends AbstractPanel {
}

updateComponent(state: any) {
return <RemixPluginPanel header={<RemixUIPanelHeader plugins={state.plugins} pinView={this.pinView.bind(this)} unPinView={this.unPinView.bind(this)}></RemixUIPanelHeader>} { ...state } />
return <RemixPluginPanel header={<RemixUIPanelHeader plugins={state.plugins} pinView={this.pinView.bind(this)} unPinView={this.unPinView.bind(this)} closePlugin={this.closePlugin.bind(this)} maximizePlugin={this.maximizePlugin.bind(this)}></RemixUIPanelHeader>} { ...state } />
}

renderComponent() {
Expand Down
4 changes: 0 additions & 4 deletions apps/remix-ide/src/app/components/side-panel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -100,10 +100,6 @@ export class SidePanel extends AbstractPanel {
*/
async showContent(name) {
super.showContent(name)
if (name === 'remixaiassistant') {
await this.call('sidePanel', 'pinView', this.plugins[name].profile)
return
}
this.emit('focusChanged', name)
this.renderComponent()
}
Expand Down
27 changes: 8 additions & 19 deletions apps/remix-ide/src/app/components/top-bar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export class Topbar extends Plugin {
dispatch: React.Dispatch<any> = () => { }
appStateDispatch: React.Dispatch<AppAction> = () => { }
htmlElement: HTMLDivElement
events: EventEmitter
event: EventEmitter
topbarExpandPath: string
filePanel: FilePanel
git: GitPlugin
Expand All @@ -44,6 +44,7 @@ export class Topbar extends Plugin {
super(TopBarProfile)
this.filePanel = filePanel
this.registry = Registry.getInstance()
this.event = new EventEmitter()
this.fileProviders = this.registry.get('fileproviders').api
this.fileManager = this.registry.get('filemanager').api
this.git = git
Expand All @@ -52,6 +53,12 @@ export class Topbar extends Plugin {
}

onActivation(): void {
this.on('pinnedPanel', 'pluginClosed', (profile) => {
this.event.emit('pluginIsClosed', profile)
})
this.on('pinnedPanel', 'pluginMaximized', (profile) => {
this.event.emit('pluginIsMaximized', profile)
})
this.renderComponent()
}

Expand All @@ -69,12 +76,6 @@ export class Topbar extends Plugin {
}

async createWorkspace(workspaceName, workspaceTemplateName, isEmpty) {
// return new Promise((resolve, reject) => {
// this.emit('createWorkspaceReducerEvent', workspaceName, workspaceTemplateName, isEmpty, (err, data) => {
// if (err) reject(err)
// else resolve(data || true)
// })
// })
try {
await createWorkspace(workspaceName, workspaceTemplateName, isEmpty)
this.emit('workspaceCreated', workspaceName, workspaceTemplateName, isEmpty)
Expand All @@ -84,12 +85,6 @@ export class Topbar extends Plugin {
}

async renameWorkspace(oldName, workspaceName) {
// return new Promise((resolve, reject) => {
// this.emit('renameWorkspaceReducerEvent', oldName, workspaceName, (err, data) => {
// if (err) reject(err)
// else resolve(data || true)
// })
// })
try {
await renameWorkspace(oldName, workspaceName)
this.emit('workspaceRenamed', oldName, workspaceName)
Expand All @@ -99,12 +94,6 @@ export class Topbar extends Plugin {
}

async deleteWorkspace(workspaceName) {
// return new Promise((resolve, reject) => {
// this.emit('deleteWorkspaceReducerEvent', workspaceName, (err, data) => {
// if (err) reject(err)
// else resolve(data || true)
// })
// })
try {
await deleteWorkspace(workspaceName)
this.emit('workspaceDeleted', workspaceName)
Expand Down
9 changes: 9 additions & 0 deletions apps/remix-ide/src/app/panels/tab-proxy.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ export default class TabProxy extends Plugin {
this.loadedTabs = []
this.dispatch = null
this.themeQuality = 'dark'
this.maximize = false
}

async onActivation () {
Expand All @@ -31,6 +32,13 @@ export default class TabProxy extends Plugin {
this.renderComponent()
})

this.on('pinnedPanel', 'pluginClosed', (profile) => {
this.event.emit('pluginIsClosed', profile)
})
this.on('pinnedPanel', 'pluginMaximized', (profile) => {
this.event.emit('pluginIsMaximized', profile)
})

this.on('fileManager', 'filesAllClosed', () => {
this.call('manager', 'activatePlugin', 'home')
this.focus('home')
Expand Down Expand Up @@ -357,6 +365,7 @@ export default class TabProxy extends Plugin {
onZoomOut={state.onZoomOut}
onReady={state.onReady}
themeQuality={state.themeQuality}
maximize={this.maximize}
/>
}

Expand Down
1 change: 1 addition & 0 deletions apps/remix-ide/src/remixAppManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ export function isNative(name) {
'foundry-provider',
'basic-http-provider',
'tabs',
'pinnedPanel',
'doc-gen',
'doc-viewer',
'circuit-compiler',
Expand Down
34 changes: 21 additions & 13 deletions libs/remix-ui/panel/src/lib/plugins/panel-header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ const _paq = (window._paq = window._paq || [])
export interface RemixPanelProps {
plugins: Record<string, PluginRecord>,
pinView?: (profile: PluginRecord['profile'], view: PluginRecord['view']) => void,
unPinView?: (profile: PluginRecord['profile']) => void
unPinView?: (profile: PluginRecord['profile']) => void,
closePlugin?: (profile: PluginRecord['profile']) => void,
maximizePlugin?: (profile: PluginRecord['profile']) => void
}
const RemixUIPanelHeader = (props: RemixPanelProps) => {
const [plugin, setPlugin] = useState<PluginRecord>()
Expand Down Expand Up @@ -38,6 +40,10 @@ const RemixUIPanelHeader = (props: RemixPanelProps) => {
_paq.push(['trackEvent', 'PluginPanel', 'pinToLeft', plugin.profile.name])
}

const closePlugin = async () => {
props.closePlugin && props.closePlugin(plugin.profile)
}

const tooltipChild = <i className={`px-1 ms-2 pt-1 pb-2 ${!toggleExpander ? 'fas fa-angle-right' : 'fas fa-angle-down bg-light'}`} aria-hidden="true"></i>

return (
Expand Down Expand Up @@ -71,14 +77,23 @@ const RemixUIPanelHeader = (props: RemixPanelProps) => {
<RenderIfNot condition={plugin.profile.name === 'filePanel'}>
<>
<RenderIf condition={plugin.pinned}>
<div className='d-flex' data-id="movePluginToLeft" onClick={unPinPlugin}>
<CustomTooltip placement="auto-end" tooltipId="unPinnedMsg" tooltipClasses="text-nowrap" tooltipText={<FormattedMessage id="panel.unPinnedMsg" />}>
<i aria-hidden="true" className="mt-1 px-2 fak fa-fa-dock-l"></i>
<>
<div className='d-flex' data-id="movePluginToLeft" data-pinnedplugin={`movePluginToLeft-${plugin.profile.name}`} onClick={unPinPlugin}>
<CustomTooltip placement="auto-end" tooltipId="unPinnedMsg" tooltipClasses="text-nowrap" tooltipText={<FormattedMessage id="panel.unPinnedMsg" />}>
<i aria-hidden="true" className="mt-1 px-2 fak fa-fa-dock-l"></i>
</CustomTooltip>
</div>
<CustomTooltip placement="bottom-end" tooltipText="Hide pinned Plugin">
<i
className="fa-solid fa-compress ms-2 fs-5"
onClick={closePlugin}
data-id="closePinnedPlugin"
></i>
</CustomTooltip>
</div>
</>
</RenderIf>
<RenderIfNot condition={plugin.pinned}>
<div className='d-flex' data-id="movePluginToRight" onClick={pinPlugin}>
<div className='d-flex' data-id="movePluginToRight" data-pinnedplugin={`movePluginToRight-${plugin.profile.name}`} onClick={pinPlugin}>
<CustomTooltip placement="auto-end" tooltipId="pinnedMsg" tooltipClasses="text-nowrap" tooltipText={<FormattedMessage id="panel.pinnedMsg" />}>
<i aria-hidden="true" className="mt-1 px-1 ps-2 fak fa-fa-dock-r"></i>
</CustomTooltip>
Expand Down Expand Up @@ -121,13 +136,6 @@ const RemixUIPanelHeader = (props: RemixPanelProps) => {
</a>
</span>
)}

{plugin?.profile?.documentation && (
<a href={plugin.profile.documentation} target="_blank" rel="noreferrer" className="btn btn-secondary w-100 d-flex align-items-center justify-content-center text-decoration-none">
<i className="fas fa-book me-2"></i>
<FormattedMessage id="panel.openDocumentation" defaultMessage="Open documentation" />
</a>
)}
</div>
</div>

Expand Down
24 changes: 21 additions & 3 deletions libs/remix-ui/tabs/src/lib/remix-ui-tabs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,22 @@ import { values } from 'lodash'
import { AppContext } from '@remix-ui/app'
import { desktopConnectionType } from '@remix-api'
import { CompileDropdown, RunScriptDropdown } from '@remix-ui/tabs'
// eslint-disable-next-line @nrwl/nx/enforce-module-boundaries
import TabProxy from 'apps/remix-ide/src/app/panels/tab-proxy'

const _paq = (window._paq = window._paq || [])

/* eslint-disable-next-line */
export interface TabsUIProps {
tabs: Array<Tab>
plugin: Plugin
plugin: TabProxy
onSelect: (index: number) => void
onClose: (index: number) => void
onZoomOut: () => void
onZoomIn: () => void
onReady: (api: any) => void
themeQuality: string
maximize: boolean
}

export interface Tab {
Expand Down Expand Up @@ -86,6 +89,8 @@ export const TabsUI = (props: TabsUIProps) => {
const compileSeq = useRef(0)
const compileWatchdog = useRef<number | null>(null)
const settledSeqRef = useRef<number>(0)
const [maximized, setMaximized] = useState<boolean>(false)
const [closedPlugin, setClosedPlugin] = useState<any>(null)

const [compileState, setCompileState] = useState<'idle' | 'compiling' | 'compiled'>('idle')

Expand All @@ -98,6 +103,19 @@ export const TabsUI = (props: TabsUIProps) => {
}
}, [tabsState.selectedIndex])

useEffect(() => {
props.plugin.event.on('pluginIsClosed', (profile) => {
setClosedPlugin(profile)
if (maximized) {
setMaximized(false)
}
})
props.plugin.event.on('pluginIsMaximized', () => {
setClosedPlugin(null)
setMaximized(true)
})
}, [])

// Toggle the copilot in editor when clicked to update in status bar
useEffect(() => {
const run = async () => {
Expand Down Expand Up @@ -490,7 +508,7 @@ export const TabsUI = (props: TabsUIProps) => {

return (
<div
className={`remix-ui-tabs justify-content-between border-0 header nav-tabs ${
className={`remix-ui-tabs justify-content-between border-0 header nav-tabs ${
appContext.appState.connectedToDesktop === desktopConnectionType .disabled ? 'd-flex' : 'd-none'
}`}
data-id="tabs-component"
Expand Down Expand Up @@ -606,8 +624,8 @@ export const TabsUI = (props: TabsUIProps) => {
<TabPanel key={tab.name}></TabPanel>
))}
</Tabs>
</div>

</div>
</div>
)
}
Expand Down
Loading