command bar draft

This commit is contained in:
Mathew Pareles 2025-03-20 22:10:45 -07:00
parent 07e995fc2f
commit e894be803b
2 changed files with 69 additions and 26 deletions

View file

@ -7,18 +7,12 @@
import { useAccessor, useCommandBarState, useIsDark } from '../util/services.js';
import '../styles.css'
import { useCallback, useEffect, useState } from 'react';
import { URI } from '../../../../../../../base/common/uri.js';
import { ICodeEditor } from '../../../../../../../editor/browser/editorBrowser.js';
import { useCallback, useEffect, useState, useRef } from 'react';
import { ScrollType } from '../../../../../../../editor/common/editorCommon.js';
import { acceptAllBg, acceptBorder, buttonFontSize, buttonTextColor, rejectAllBg, rejectBorder } from '../../../../common/helpers/colors.js';
import { VoidCommandBarProps } from '../../../voidCommandBarService.js';
export type VoidCommandBarProps = {
uri: URI | null;
editor: ICodeEditor;
}
export const VoidCommandBarMain = ({ uri, editor }: VoidCommandBarProps) => {
export const VoidCommandBarMain = ({ uri, editor, onChangeHeight }: VoidCommandBarProps) => {
const isDark = useIsDark()
if (uri?.scheme !== 'file') return null // don't show in editors that we made, they must be files
@ -26,7 +20,7 @@ export const VoidCommandBarMain = ({ uri, editor }: VoidCommandBarProps) => {
return <div
className={`@@void-scope ${isDark ? 'dark' : ''}`}
>
<VoidCommandBar uri={uri} editor={editor} />
<VoidCommandBar uri={uri} editor={editor} onChangeHeight={onChangeHeight} />
</div>
}
@ -38,9 +32,11 @@ const stepIdx = (currIdx: number | null, len: number, step: -1 | 1) => {
return ((currIdx ?? 0) + step + len) % len // for some reason, small negatives are kept negative. just add len to offset
}
const DummyContainer = ()=>{
}
const VoidCommandBar = ({ uri, editor }: { uri: URI | null, editor: ICodeEditor }) => {
const VoidCommandBar = ({ uri, editor, onChangeHeight }: VoidCommandBarProps) => {
const accessor = useAccessor()
const editCodeService = accessor.get('IEditCodeService')
const editorService = accessor.get('ICodeEditorService')
@ -50,6 +46,23 @@ const VoidCommandBar = ({ uri, editor }: { uri: URI | null, editor: ICodeEditor
const voidModelService = accessor.get('IVoidModelService')
const { state: commandBarState, sortedURIs: sortedCommandBarURIs } = useCommandBarState()
// Add a reference to the container for resize observer
const sizerRef = useRef<HTMLDivElement | null>(null)
// Add the resize observer effect
useEffect(() => {
const inputContainer = sizerRef.current
if (!inputContainer) return;
// only observing 1 element
let resizeObserver: ResizeObserver | undefined
resizeObserver = new ResizeObserver((entries) => {
const height = entries[0].borderBoxSize[0].blockSize
onChangeHeight(height)
})
resizeObserver.observe(inputContainer);
return () => { resizeObserver?.disconnect(); };
}, [onChangeHeight]);
// changes if the user clicks left/right or if the user goes on a uri with changes
const [currUriIdx, setUriIdx] = useState<number | null>(null)
@ -263,7 +276,7 @@ const VoidCommandBar = ({ uri, editor }: { uri: URI | null, editor: ICodeEditor
</button>
return <div className='px-2 pt-1.5 pb-1 gap-1 pointer-events-auto flex flex-col items-start bg-void-bg-1 rounded shadow-md border border-void-border-1'>
return <div ref={sizerRef} className='px-2 pt-1.5 pb-1 gap-1 pointer-events-auto flex flex-col items-start bg-void-bg-1 rounded shadow-md border border-void-border-1'>
{currUriHasChanges && <>
<div className="flex gap-2">
{acceptAllButton}

View file

@ -17,6 +17,7 @@ import { InstantiationType, registerSingleton } from '../../../../platform/insta
import { IEditCodeService } from './editCodeServiceInterface.js';
import { ITextModel } from '../../../../editor/common/model.js';
import { IModelService } from '../../../../editor/common/services/model.js';
import { generateUuid } from '../../../../base/common/uuid.js';
@ -112,6 +113,8 @@ export class VoidCommandBarService extends Disposable implements IVoidCommandBar
const onCodeEditorAdd = (editor: ICodeEditor) => {
const id = editor.getId();
disposablesOfEditorId[id] = [];
// mount the command bar
const d1 = this._instantiationService.createInstance(AcceptRejectAllFloatingWidget, { editor });
disposablesOfEditorId[id].push(d1);
const d2 = editor.onDidChangeModel((e) => { if (e?.newModelUrl?.scheme === 'file') updateActiveURI() })
@ -346,6 +349,12 @@ registerSingleton(IVoidCommandBarService, VoidCommandBarService, InstantiationTy
// registerWorkbenchContribution2(VoidCommandBarService.ID, VoidCommandBarService, WorkbenchPhase.BlockRestore);
export type VoidCommandBarProps = {
uri: URI | null;
editor: ICodeEditor;
onChangeHeight: (height: number) => void;
}
@ -354,14 +363,15 @@ class AcceptRejectAllFloatingWidget extends Widget implements IOverlayWidget {
private readonly editor: ICodeEditor;
private readonly ID: string;
_height = 0
constructor({ editor }: { editor: ICodeEditor, },
@IInstantiationService private readonly instantiationService: IInstantiationService,
) {
super();
this.ID = editor.getId() + '-voidfloatingwidget';
this.ID = generateUuid();
this.editor = editor;
// Create container div
const { root } = dom.h('div@root');
@ -370,30 +380,50 @@ class AcceptRejectAllFloatingWidget extends Widget implements IOverlayWidget {
root.style.padding = '4px';
root.style.alignItems = 'center';
root.style.pointerEvents = 'none';
// Mount command bar using mountVoidCommandBar
// this.editor.getDomNode()?.appendChild(root)
const onChangeHeight = (height: number) => {
if (height === 0) return;
this._height = height
// editor.layoutOverlayWidget(this)
// stupid hack because layoutOverlayWidget doesn't work
editor.removeOverlayWidget(this)
editor.addOverlayWidget(this)
}
// alternative to mount VoidCommandBar without the stupid widget
// editor.getLayoutInfo()
// this._register(
// editor.onDidLayoutChange(e => {
// // e.height
// // e.width
// })
// )
this._domNode = root;
editor.addOverlayWidget(this);
this.instantiationService.invokeFunction(accessor => {
type Props = { uri: URI | null, editor: ICodeEditor }
const uri = editor.getModel()?.uri || null
const res = mountVoidCommandBar(root, accessor, { uri, editor } satisfies Props)
const res = mountVoidCommandBar(root, accessor, { uri, editor, onChangeHeight } satisfies VoidCommandBarProps)
if (!res) return
const dispose = res.dispose
const rerender: (o: Props) => void = res.rerender
this._register(toDisposable(() => dispose?.()))
this._register(toDisposable(() => res.dispose?.()))
this._register(editor.onDidChangeModel((model) => {
const uri = model.newModelUrl
rerender({ uri, editor })
res.rerender({ uri, editor, onChangeHeight })
}))
});
this._domNode = root;
// Mount the widget
editor.addOverlayWidget(this);
}
@ -407,7 +437,7 @@ class AcceptRejectAllFloatingWidget extends Widget implements IOverlayWidget {
public getPosition() {
return {
preference: OverlayWidgetPositionPreference.BOTTOM_RIGHT_CORNER,
preference: OverlayWidgetPositionPreference.BOTTOM_RIGHT_CORNER
}
}