resizes the col widths on app resize
This commit is contained in:
@@ -130,12 +130,22 @@ export function App(): React.ReactElement {
|
|||||||
toast('Discarded changes', path)
|
toast('Discarded changes', path)
|
||||||
}
|
}
|
||||||
|
|
||||||
const [gitW, setGitW] = useState(() => loadNum('helder.gitW', 232))
|
// Columns are proportional — Source Control 10%, Explorer 10%, Editor 40%
|
||||||
const [treeW, setTreeW] = useState(() => loadNum('helder.treeW', 244))
|
// (flex:1, takes the remainder), Right column 40% — and re-apply on resize.
|
||||||
const [rightW, setRightW] = useState(() => loadNum('helder.rightW', 444))
|
// Dragging a splitter still adjusts them until the next window resize.
|
||||||
useEffect(() => saveNum('helder.gitW', gitW), [gitW])
|
const [gitW, setGitW] = useState(() => Math.round(window.innerWidth * 0.1))
|
||||||
useEffect(() => saveNum('helder.treeW', treeW), [treeW])
|
const [treeW, setTreeW] = useState(() => Math.round(window.innerWidth * 0.1))
|
||||||
useEffect(() => saveNum('helder.rightW', rightW), [rightW])
|
const [rightW, setRightW] = useState(() => Math.round(window.innerWidth * 0.4))
|
||||||
|
useEffect(() => {
|
||||||
|
function applyProportions(): void {
|
||||||
|
const w = window.innerWidth
|
||||||
|
setGitW(Math.round(w * 0.1))
|
||||||
|
setTreeW(Math.round(w * 0.1))
|
||||||
|
setRightW(Math.round(w * 0.4))
|
||||||
|
}
|
||||||
|
window.addEventListener('resize', applyProportions)
|
||||||
|
return () => window.removeEventListener('resize', applyProportions)
|
||||||
|
}, [])
|
||||||
|
|
||||||
// Seed explorer expansion from the tree's `open` flags once per opened project.
|
// Seed explorer expansion from the tree's `open` flags once per opened project.
|
||||||
const seededRoot = useRef<string | null | undefined>(undefined)
|
const seededRoot = useRef<string | null | undefined>(undefined)
|
||||||
@@ -373,7 +383,11 @@ export function App(): React.ReactElement {
|
|||||||
cursor={cursor} selection={selection} setCursor={setCursor} setSelection={setSelection}
|
cursor={cursor} selection={selection} setCursor={setCursor} setSelection={setSelection}
|
||||||
bufferText={bufferText(active)} onEdit={onEdit} />
|
bufferText={bufferText(active)} onEdit={onEdit} />
|
||||||
</div>
|
</div>
|
||||||
<Splitter onDelta={(dx) => setRightW((w) => clamp(w - dx, 280, 780))} />
|
<Splitter onDelta={(dx) => setRightW((w) => {
|
||||||
|
// grow until the editor would drop below ~280px (rather than a fixed cap)
|
||||||
|
const max = Math.max(280, window.innerWidth - gitW - treeW - 280)
|
||||||
|
return clamp(w - dx, 280, max)
|
||||||
|
})} />
|
||||||
|
|
||||||
{/* keyed by root so the PTYs respawn in the new cwd when the project switches */}
|
{/* keyed by root so the PTYs respawn in the new cwd when the project switches */}
|
||||||
{proj.ready && <RightColumn key={proj.root ?? 'none'} width={rightW} />}
|
{proj.ready && <RightColumn key={proj.root ?? 'none'} width={rightW} />}
|
||||||
|
|||||||
@@ -114,13 +114,9 @@ export function GitPanel({ branch, changes, staged, committed, commitMsg, setCom
|
|||||||
|
|
||||||
<div className="commit-box">
|
<div className="commit-box">
|
||||||
<textarea className="commit-input" rows={1} value={commitMsg} spellCheck={false}
|
<textarea className="commit-input" rows={1} value={commitMsg} spellCheck={false}
|
||||||
placeholder="Message (⌘↵ to commit)"
|
placeholder={stagedList.length ? `Message — ⇧↵ to commit ${stagedList.length}` : 'Message (stage a file to commit)'}
|
||||||
onChange={(e) => setCommitMsg(e.target.value)}
|
onChange={(e) => setCommitMsg(e.target.value)}
|
||||||
onKeyDown={(e) => { if ((e.metaKey || e.ctrlKey) && e.key === 'Enter' && canCommit) { e.preventDefault(); onCommit() } }} />
|
onKeyDown={(e) => { if (e.key === 'Enter' && (e.shiftKey || e.metaKey || e.ctrlKey) && canCommit) { e.preventDefault(); onCommit() } }} />
|
||||||
<button className="commit-btn" disabled={!canCommit} onClick={onCommit}
|
|
||||||
title={canCommit ? 'Commit staged changes' : 'Stage files and write a message to commit'}>
|
|
||||||
{Icon.check()}<span>Commit{stagedList.length ? ' ' + stagedList.length : ''}</span>
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="git-body">
|
<div className="git-body">
|
||||||
|
|||||||
@@ -65,25 +65,19 @@ describe('Pass on to Agent', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
describe('Stage + commit', () => {
|
describe('Stage + commit', () => {
|
||||||
it('stages a file, commits with a message, and toasts', async () => {
|
it('stages a file and commits via Shift+Enter (no commit button)', async () => {
|
||||||
const c = renderApp()
|
const c = renderApp()
|
||||||
const row = await waitFor(() => {
|
const row = await waitFor(() => {
|
||||||
const r = find(c, '.git-row', 'UserController.php')
|
const r = find(c, '.git-row', 'UserController.php')
|
||||||
if (!r) throw new Error('git not ready')
|
if (!r) throw new Error('git not ready')
|
||||||
return r
|
return r
|
||||||
})
|
})
|
||||||
const stageBtn = row.querySelector<HTMLButtonElement>('button[title="Stage changes"]')!
|
fireEvent.click(row.querySelector<HTMLButtonElement>('button[title="Stage changes"]')!)
|
||||||
fireEvent.click(stageBtn)
|
// the commit button is intentionally gone — committing is keyboard-only
|
||||||
|
expect(c.querySelector('.commit-btn')).toBeNull()
|
||||||
// commit button reflects the staged count once a file is staged
|
|
||||||
await waitFor(() => expect(find(c, '.commit-btn', 'Commit')?.textContent).toMatch(/Commit\s*\d/))
|
|
||||||
|
|
||||||
const msg = c.querySelector<HTMLTextAreaElement>('.commit-input')!
|
const msg = c.querySelector<HTMLTextAreaElement>('.commit-input')!
|
||||||
fireEvent.change(msg, { target: { value: 'wire up balance' } })
|
fireEvent.change(msg, { target: { value: 'wire up balance' } })
|
||||||
const commitBtn = find(c, '.commit-btn', 'Commit') as HTMLButtonElement
|
fireEvent.keyDown(msg, { key: 'Enter', shiftKey: true })
|
||||||
expect(commitBtn.disabled).toBe(false)
|
|
||||||
fireEvent.click(commitBtn)
|
|
||||||
|
|
||||||
await waitFor(() => expect(find(c, '.toast', 'Committed')).toBeTruthy())
|
await waitFor(() => expect(find(c, '.toast', 'Committed')).toBeTruthy())
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user