mirror of
https://github.com/voideditor/void
synced 2026-05-24 09:58:23 +00:00
command bar decent
This commit is contained in:
parent
e894be803b
commit
4dff3e216a
2 changed files with 79 additions and 63 deletions
|
|
@ -12,7 +12,7 @@ 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 const VoidCommandBarMain = ({ uri, editor, onChangeHeight }: VoidCommandBarProps) => {
|
||||
export const VoidCommandBarMain = ({ uri, editor }: VoidCommandBarProps) => {
|
||||
const isDark = useIsDark()
|
||||
|
||||
if (uri?.scheme !== 'file') return null // don't show in editors that we made, they must be files
|
||||
|
|
@ -20,7 +20,7 @@ export const VoidCommandBarMain = ({ uri, editor, onChangeHeight }: VoidCommandB
|
|||
return <div
|
||||
className={`@@void-scope ${isDark ? 'dark' : ''}`}
|
||||
>
|
||||
<VoidCommandBar uri={uri} editor={editor} onChangeHeight={onChangeHeight} />
|
||||
<VoidCommandBar uri={uri} editor={editor} />
|
||||
</div>
|
||||
}
|
||||
|
||||
|
|
@ -32,11 +32,9 @@ 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, onChangeHeight }: VoidCommandBarProps) => {
|
||||
const VoidCommandBar = ({ uri, editor }: VoidCommandBarProps) => {
|
||||
const accessor = useAccessor()
|
||||
const editCodeService = accessor.get('IEditCodeService')
|
||||
const editorService = accessor.get('ICodeEditorService')
|
||||
|
|
@ -46,28 +44,11 @@ const VoidCommandBar = ({ uri, editor, onChangeHeight }: VoidCommandBarProps) =>
|
|||
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)
|
||||
const [currUriHasChanges, setCurrUriHasChanges] = useState(false)
|
||||
const anyUriHasChanges = sortedCommandBarURIs.length !== 0
|
||||
useEffect(() => {
|
||||
const i = sortedCommandBarURIs.findIndex(e => e.fsPath === uri?.fsPath)
|
||||
if (i !== -1) {
|
||||
|
|
@ -137,19 +118,26 @@ const VoidCommandBar = ({ uri, editor, onChangeHeight }: VoidCommandBarProps) =>
|
|||
|
||||
|
||||
const currDiffIdx = uri ? commandBarState[uri.fsPath]?.diffIdx ?? null : null
|
||||
const sortedDiffIds = uri ? commandBarState[uri.fsPath]?.sortedDiffIds ?? null : null
|
||||
const sortedDiffIds = uri ? commandBarState[uri.fsPath]?.sortedDiffIds ?? [] : []
|
||||
const sortedDiffZoneIds = uri ? commandBarState[uri.fsPath]?.sortedDiffZoneIds ?? [] : []
|
||||
|
||||
|
||||
const nextDiffIdx = getNextDiffIdx(1)
|
||||
const prevDiffIdx = getNextDiffIdx(-1)
|
||||
const nextURIIdx = getNextUriIdx(1)
|
||||
const prevURIIdx = getNextUriIdx(-1)
|
||||
|
||||
const isAChangeInThisFile = sortedDiffIds.length !== 0
|
||||
const isADiffZoneInThisFile = sortedDiffZoneIds.length !== 0
|
||||
const isADiffZoneInAnyFile = sortedCommandBarURIs.length !== 0
|
||||
|
||||
|
||||
// if there are *any* changes at all
|
||||
const navPanel = anyUriHasChanges && <div
|
||||
className="flex items-center gap-1"
|
||||
>
|
||||
if (!isADiffZoneInAnyFile) { // no changes for the user to accept
|
||||
return null
|
||||
}
|
||||
|
||||
|
||||
const buttonsHTML = <>
|
||||
<button
|
||||
className={`
|
||||
size-4 rounded hover:bg-void-bg-1-alt cursor-pointer
|
||||
|
|
@ -217,16 +205,26 @@ const VoidCommandBar = ({ uri, editor, onChangeHeight }: VoidCommandBarProps) =>
|
|||
}}
|
||||
title="Next file"
|
||||
>→</button>
|
||||
</>
|
||||
|
||||
<div className="text-[var(--vscode-editor-foreground)] text-xs flex gap-4">
|
||||
|
||||
const descriptionHTML = isADiffZoneInThisFile ?
|
||||
<>
|
||||
{currUriIdx !== null && sortedCommandBarURIs.length && <div>
|
||||
File {currUriIdx + 1} of {sortedCommandBarURIs.length}
|
||||
{`File ${currUriIdx + 1} of ${sortedCommandBarURIs.length}`}
|
||||
</div>}
|
||||
{currDiffIdx !== null && sortedDiffIds?.length && <div>
|
||||
Diff {currDiffIdx + 1} of {sortedDiffIds?.length ?? 0}
|
||||
</div>}
|
||||
</div>
|
||||
</div >
|
||||
{/* <div>
|
||||
{!isAChangeInThisFile ?
|
||||
`(No changes)`
|
||||
: `Diff ${(currDiffIdx ?? 0) + 1} of ${sortedDiffIds.length}`
|
||||
}
|
||||
</div> */}
|
||||
</>
|
||||
: <>
|
||||
{`${sortedCommandBarURIs.length} file${sortedCommandBarURIs.length === 1 ? '' : 's'}`}
|
||||
</>
|
||||
|
||||
|
||||
|
||||
|
||||
// accept/reject if current URI has changes
|
||||
|
|
@ -276,13 +274,48 @@ const VoidCommandBar = ({ uri, editor, onChangeHeight }: VoidCommandBarProps) =>
|
|||
</button>
|
||||
|
||||
|
||||
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'>
|
||||
// const closeCommandBar = useCallback(() => {
|
||||
// commandService.executeCommand('void.hideCommandBar');
|
||||
// }, [commandService]);
|
||||
|
||||
// const hideButton = <button
|
||||
// className='ml-auto pointer-events-auto'
|
||||
// onClick={closeCommandBar}
|
||||
// style={{
|
||||
// color: buttonTextColor,
|
||||
// fontSize: buttonFontSize,
|
||||
// padding: '2px 4px',
|
||||
// borderRadius: '6px',
|
||||
// cursor: 'pointer'
|
||||
// }}
|
||||
// title="Close command bar"
|
||||
// >x
|
||||
// </button>
|
||||
|
||||
// const actionButtons = currUriHasChanges && (
|
||||
// <div className="flex gap-2 items-center w-full">
|
||||
// {acceptAllButton}
|
||||
// {rejectAllButton}
|
||||
// {hideButton}
|
||||
// </div>
|
||||
// );
|
||||
|
||||
|
||||
// dummy container due to annoyances with VS Code mounting the widget
|
||||
return <div className='px-2 pt-1 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}
|
||||
{rejectAllButton}
|
||||
</div>
|
||||
</>}
|
||||
{navPanel}
|
||||
<div className="flex gap-1">
|
||||
<div className="flex gap-1">
|
||||
{buttonsHTML}
|
||||
</div>
|
||||
<div className="text-xs flex flex-col">
|
||||
{descriptionHTML}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
|
|
|||
|
|
@ -352,7 +352,6 @@ registerSingleton(IVoidCommandBarService, VoidCommandBarService, InstantiationTy
|
|||
export type VoidCommandBarProps = {
|
||||
uri: URI | null;
|
||||
editor: ICodeEditor;
|
||||
onChangeHeight: (height: number) => void;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -376,33 +375,17 @@ class AcceptRejectAllFloatingWidget extends Widget implements IOverlayWidget {
|
|||
const { root } = dom.h('div@root');
|
||||
|
||||
// Style the container
|
||||
// root.style.backgroundColor = 'rgb(248 113 113)';
|
||||
root.style.height = '16rem'; // make a fixed size, and all contents go on the bottom right. this fixes annoying VS Code mounting issues
|
||||
root.style.width = '16rem';
|
||||
root.style.flexDirection = 'column';
|
||||
root.style.justifyContent = 'flex-end';
|
||||
root.style.alignItems = 'flex-end';
|
||||
root.style.zIndex = '2';
|
||||
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
|
||||
// })
|
||||
// )
|
||||
|
||||
|
||||
root.style.display = 'flex';
|
||||
root.style.overflow = 'hidden';
|
||||
|
||||
|
||||
this._domNode = root;
|
||||
|
|
@ -412,14 +395,14 @@ class AcceptRejectAllFloatingWidget extends Widget implements IOverlayWidget {
|
|||
|
||||
const uri = editor.getModel()?.uri || null
|
||||
|
||||
const res = mountVoidCommandBar(root, accessor, { uri, editor, onChangeHeight } satisfies VoidCommandBarProps)
|
||||
const res = mountVoidCommandBar(root, accessor, { uri, editor } satisfies VoidCommandBarProps)
|
||||
if (!res) return
|
||||
|
||||
this._register(toDisposable(() => res.dispose?.()))
|
||||
|
||||
this._register(editor.onDidChangeModel((model) => {
|
||||
const uri = model.newModelUrl
|
||||
res.rerender({ uri, editor, onChangeHeight })
|
||||
res.rerender({ uri, editor })
|
||||
}))
|
||||
|
||||
});
|
||||
|
|
|
|||
Loading…
Reference in a new issue