Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 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
7 changes: 6 additions & 1 deletion apps/remix-ide/src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ import Editor from './app/editor/editor'
import Terminal from './app/panels/terminal'
import TabProxy from './app/panels/tab-proxy.js'
import { Plugin } from '@remixproject/engine'
import BottomBarPanel from './app/components/bottom-bar-panel'

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

Expand Down Expand Up @@ -526,7 +527,9 @@ class AppComponent {
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, this.statusBar, this.topBar, filePanel, pluginManagerComponent, this.settings, this.pinnedPanel, this.popupPanel])
const bottomBarPanel = new BottomBarPanel()

this.engine.register([this.menuicons, landingPage, this.hiddenPanel, this.sidePanel, this.statusBar, this.topBar, filePanel, pluginManagerComponent, this.settings, this.pinnedPanel, this.popupPanel, bottomBarPanel])

// CONTENT VIEWS & DEFAULT PLUGINS
const openZeppelinProxy = new OpenZeppelinProxy(blockchain)
Expand Down Expand Up @@ -573,6 +576,7 @@ class AppComponent {
tabs: { plugin: tabProxy, active: true },
editor: { plugin: editor, active: true },
main: { plugin: appPanel, active: false },
bottomBar: { plugin: bottomBarPanel, active: true },
terminal: { plugin: terminal, active: true, minimized: false }
}
}
Expand Down Expand Up @@ -607,6 +611,7 @@ class AppComponent {
await this.appManager.activatePlugin(['mainPanel', 'menuicons', 'tabs'])
await this.appManager.activatePlugin(['topbar'])
await this.appManager.activatePlugin(['statusBar'])
await this.appManager.activatePlugin(['bottomBar'])
await this.appManager.activatePlugin(['sidePanel']) // activating host plugin separately
await this.appManager.activatePlugin(['pinnedPanel'])
await this.appManager.activatePlugin(['popupPanel'])
Expand Down
47 changes: 47 additions & 0 deletions apps/remix-ide/src/app/components/bottom-bar-panel.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import React from 'react'
import { Plugin } from '@remixproject/engine'
import { PluginViewWrapper } from '@remix-ui/helper'
import * as packageJson from '../../../../../package.json'
import BottomBar from './bottom-bar'

const profile = {
displayName: 'Bottom Bar',
name: 'bottomBar',
methods: [],
events: [],
description: 'Editor bottom bar (renders above dragbar-terminal)',
version: packageJson.version,
kind: 'system'
}

export default class BottomBarPanel extends Plugin {
private dispatch: ((state: any) => void) | null = null

constructor() {
super(profile)
}

setDispatch = (dispatch) => {
this.dispatch = dispatch
}

onActivation() {
this.renderComponent()
}

render() {
return (
<div className="panel" data-id="bottomBarPanelView">
<PluginViewWrapper plugin={this} />
</div>
)
}

updateComponent() {
return <BottomBar plugin={this} />
}

renderComponent() {
this.dispatch && this.dispatch({})
}
}
26 changes: 12 additions & 14 deletions apps/remix-ide/src/app/components/bottom-bar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,7 @@ export const BottomBar = ({ plugin }: BottomBarProps) => {
setCurrentFilePath(path)
const ext = path?.split('.').pop()?.toLowerCase() || ''
setCurrentExt(ext)
} catch (err) {
console.info('No current file selected.')
} catch {
setCurrentFilePath('')
setCurrentExt('')
}
Expand All @@ -38,32 +37,30 @@ export const BottomBar = ({ plugin }: BottomBarProps) => {
getAI()
getCurrentExt()

plugin.on('settings', 'copilotChoiceUpdated', (isChecked) => {
setAiSwitch(isChecked)
})
const onCopilot = (isChecked: boolean) => setAiSwitch(!!isChecked)

plugin.on('settings', 'copilotChoiceUpdated', onCopilot)
plugin.on('fileManager', 'currentFileChanged', getCurrentExt)

return () => {
plugin.off('settings', 'copilotChoiceUpdated')
plugin.off('fileManager', 'currentFileChanged')
}

}, [plugin])

const handleExplain = async () => {
if (!currentFilePath) {
plugin.call('notification', 'toast', 'No file selected to explain.');
plugin.call('notification', 'toast', 'No file selected to explain.')
return
}
setExplaining(true)
try {
await plugin.call('menuicons', 'select', 'remixaiassistant')
await new Promise(resolve => setTimeout(resolve, 500))
await new Promise((resolve) => setTimeout(resolve, 500))
const content = await plugin.call('fileManager', 'readFile', currentFilePath)
await plugin.call('remixAI', 'chatPipe', 'code_explaining', content)

} catch (err) {
console.error("Explain failed:", err)
console.error('Explain failed:', err)
}
setExplaining(false)
}
Expand All @@ -84,21 +81,22 @@ export const BottomBar = ({ plugin }: BottomBarProps) => {
}

return (
<div className="bottom-bar border-top border-bottom">
<div className="bottom-bar border-top border-bottom" data-id="bottomBarPanel">
{getExplainLabel() && (
<button
className="btn btn-ai"
onClick={handleExplain}
disabled={explaining || !currentFilePath}
data-id="bottomBarExplainBtn"
>
<img src="assets/img/remixAI_small.svg" alt="Remix AI" className="explain-icon" />
<span>{getExplainLabel()}</span>
</button>
)}
<div className="copilot-toggle">
<span className={aiSwitch ? "on" : ""}>AI copilot</span>
<label className="switch" data-id="copilot_toggle" >
<input type="checkbox" checked={aiSwitch} onChange={toggleAI}/>
<span className={aiSwitch ? 'on' : ''}>AI copilot</span>
<label className="switch" data-id="copilot_toggle">
<input type="checkbox" checked={aiSwitch} onChange={toggleAI} />
<span className="slider"></span>
</label>
</div>
Expand Down
24 changes: 14 additions & 10 deletions apps/remix-ide/src/app/components/styles/bottom-bar.css
Original file line number Diff line number Diff line change
@@ -1,17 +1,21 @@
.bottom-bar {
display: flex;
flex: 0 0 auto;
align-items: center;
padding: 4px 16px;
background-color: var(--bs-light) !important;
height: 32px;
position: sticky;
top: 0;
z-index: 10;
}

.explain-icon {
.bottom-bar .explain-icon {
width: 12px;
height: 12px;
}

.copilot-toggle {
.bottom-bar .copilot-toggle {
margin-left: auto;
display: flex;
align-items: center;
Expand All @@ -22,32 +26,32 @@
line-height: 1;
}

.copilot-toggle span {
.bottom-bar .copilot-toggle span {
font-family: 'Nunito Sans', sans-serif;
font-size: 12px;
font-weight: 700;
color: var(--text-muted);
transition: color 0.3s;
}

.copilot-toggle span.on {
.bottom-bar .copilot-toggle span.on {
color: var(--text-bright);
}

.switch {
.bottom-bar .switch {
position: relative;
display: inline-block;
width: 18px;
height: 10px;
}

.switch input {
.bottom-bar .switch input {
opacity: 0;
width: 0;
height: 0;
}

.slider {
.bottom-bar .slider {
position: absolute;
cursor: pointer;
top: 0; left: 0; right: 0; bottom: 0;
Expand All @@ -57,7 +61,7 @@
padding: 1px;
}

.slider:before {
.bottom-bar .slider:before {
position: absolute;
content: "";
height: 8px;
Expand All @@ -69,10 +73,10 @@
border-radius: 50%;
}

.switch input:checked + .slider {
.bottom-bar .switch input:checked + .slider {
background-color: var(--custom-ai-color);
}

.switch input:checked + .slider:before {
.bottom-bar .switch input:checked + .slider:before {
transform: translateX(8px);
}
1 change: 1 addition & 0 deletions apps/remix-ide/src/app/panels/layout.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ interface panels {
tabs: panelState
editor: panelState
main: panelState
bottomBar: panelState
terminal: panelState
}

Expand Down
2 changes: 0 additions & 2 deletions apps/remix-ide/src/app/panels/terminal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import EventManager from '../../lib/events'

import { CompilerImports } from '@remix-project/core-plugin' // eslint-disable-line
import { RemixUiXterminals } from '@remix-ui/xterm'
import { BottomBar } from '../components/bottom-bar'

const KONSOLES = []

Expand Down Expand Up @@ -143,7 +142,6 @@ export default class Terminal extends Plugin {
updateComponent(state) {
return (
<>
<BottomBar plugin={this} />
<RemixUITerminalWrapper
plugin={state.plugin}
onReady={state.onReady}
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 @@ -35,6 +35,7 @@ let requiredModules = [
'menuicons',
'filePanel',
'terminal',
'bottomBar',
'statusBar',
'settings',
'pluginManager',
Expand Down
34 changes: 32 additions & 2 deletions libs/remix-ui/panel/src/lib/main/main-panel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ const RemixUIMainPanel = (props: RemixUIMainPanelProps) => {
const mainPanelRef = useRef<HTMLDivElement>(null)
const tabsRef = useRef<HTMLDivElement>(null)
const terminalRef = useRef<HTMLDivElement>(null)
const bottomBarRef = useRef<HTMLDivElement>(null)

const refs = [tabsRef, editorRef, mainPanelRef, terminalRef]

Expand Down Expand Up @@ -56,18 +57,47 @@ const RemixUIMainPanel = (props: RemixUIMainPanelProps) => {
}

const resize = (height: number) => {
syncBottomBarPosition()
layout.emit('resize', height)
}

const syncBottomBarPosition = () => {
if (terminalRef.current && bottomBarRef.current && mainPanelRef.current && !layout.panels.terminal.minimized) {
const bottomBarElement = bottomBarRef.current
const terminalElement = terminalRef.current
const mainPanelElement = mainPanelRef.current

const bottomBarHeight = bottomBarElement.offsetHeight;

if (editorRef.current) {
const dragBarHeight = 8
const newEditorHeight = mainPanelElement.offsetHeight - terminalElement.offsetHeight - bottomBarHeight - dragBarHeight
editorRef.current.style.height = `${newEditorHeight}px`
}
} else if (bottomBarRef.current) {
bottomBarRef.current.style.visibility = 'hidden'
if (editorRef.current && mainPanelRef.current && bottomBarRef.current) {
editorRef.current.style.height = `${mainPanelRef.current.offsetHeight - bottomBarRef.current.offsetHeight}px`
}
}
}

return (
<div className="mainview">
<div className="mainview" ref={mainPanelRef}>
{Object.values(plugins).map((pluginRecord, i) => {
let panelRef = refs[i]
if (pluginRecord.profile.name === 'terminal') {
panelRef = terminalRef
} else if (pluginRecord.profile.name === 'bottomBar') {
panelRef = bottomBarRef
}

return (
<React.Fragment key={`mainView${i}`}>
{pluginRecord.profile.name === 'terminal' ? (
<DragBar key="dragbar-terminal" onResize={resize} hidden={pluginRecord.minimized || false} setHideStatus={showTerminal} refObject={terminalRef}></DragBar>
) : null}
<RemixUIPanelPlugin ref={refs[i]} key={pluginRecord.profile.name} pluginRecord={pluginRecord} />
<RemixUIPanelPlugin ref={panelRef} key={pluginRecord.profile.name} pluginRecord={pluginRecord} />
</React.Fragment>
)
})}
Expand Down