diff --git a/src/web/public/git-status-ui.js b/src/web/public/git-status-ui.js index adcd8f0b..185e94b9 100644 --- a/src/web/public/git-status-ui.js +++ b/src/web/public/git-status-ui.js @@ -344,13 +344,19 @@ Object.assign(CodemanApp.prototype, { } }, - /** One repository of several: a collapsible section, open when it has something outstanding. */ + /** + * One repository of several: a collapsible section, collapsed by default (the summary line already + * shows what is outstanding). Which ones the user opened stay open across the 15 s re-render. + */ _gitRepoSection(r) { const el = (tag, cls, text) => this._gitEl(tag, cls, text); const d = r.status; const section = el('details', 'git-status-repo'); const outstanding = d.counts.uncommitted > 0 || d.unpushedCount > 0; - section.open = outstanding; + const openRepos = (this._gitTreeOpen = this._gitTreeOpen || new Set()); + const repoKey = `repo|${d.repoRoot || r.path}`; + section.open = openRepos.has(repoKey); + section.addEventListener('toggle', () => (section.open ? openRepos.add(repoKey) : openRepos.delete(repoKey))); const summary = el('summary', 'git-status-repo-summary'); summary.append(el('span', 'git-status-repo-name', r.name)); if (r.path !== r.name) summary.append(el('span', 'git-status-repo-path', r.path)); diff --git a/test/git-status.browser.test.ts b/test/git-status.browser.test.ts index 0abe6a3a..f62621c4 100644 --- a/test/git-status.browser.test.ts +++ b/test/git-status.browser.test.ts @@ -330,7 +330,13 @@ describe('Git status indicator in a real browser', () => { expect(await page.getAttribute('#gitStatusBtn', 'title')).toMatch(/Git \(2 repositories\)/); const names = await page.$$eval('.git-status-repo-name', (els) => els.map((e) => e.textContent)); expect(names).toEqual(['api', 'web']); - // The one with something outstanding is open; the clean one is collapsed. + // Every repository starts collapsed (the summary line shows what is outstanding); one the user + // opens stays open when a refresh re-renders the panel. + const allClosed = await page.$$eval('.git-status-repo', (els) => els.map((e) => (e as HTMLDetailsElement).open)); + expect(allClosed).toEqual([false, false]); + await page.click('.git-status-repo:nth-of-type(1) > summary'); + await refresh(); + await page.waitForSelector('.git-status-repo[open]'); const open = await page.$$eval('.git-status-repo', (els) => els.map((e) => (e as HTMLDetailsElement).open)); expect(open).toEqual([true, false]); const apiBody = (await page.textContent('.git-status-repo:nth-of-type(1)')) ?? '';