Skip to content

Commit 58aea45

Browse files
committed
Adds repository picker
1 parent 413783e commit 58aea45

File tree

5 files changed

+53
-106
lines changed

5 files changed

+53
-106
lines changed

src/webviews/apps/plus/home/components/active-work.ts

Lines changed: 26 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,11 @@
11
import { consume } from '@lit/context';
22
import { SignalWatcher } from '@lit-labs/signals';
33
import { css, html, LitElement, nothing } from 'lit';
4-
import { customElement, property, state } from 'lit/decorators.js';
5-
import { repeat } from 'lit/directives/repeat.js';
4+
import { customElement, state } from 'lit/decorators.js';
65
import { when } from 'lit/directives/when.js';
76
import type { GitTrackingState } from '../../../../../git/models/branch';
8-
import type { GetOverviewBranch, RepositoryChoice, State } from '../../../../home/protocol';
7+
import type { GetOverviewBranch, State } from '../../../../home/protocol';
98
import { stateContext } from '../../../home/context';
10-
import { GlElement } from '../../../shared/components/element';
119
import { branchCardStyles, sectionHeadingStyles } from './branch-section';
1210
import type { Overview, OverviewState } from './overviewState';
1311
import { overviewStateContext } from './overviewState';
@@ -34,6 +32,15 @@ export class GlActiveWork extends SignalWatcher(LitElement) {
3432
`,
3533
branchCardStyles,
3634
sectionHeadingStyles,
35+
css`
36+
.is-end {
37+
margin-block-end: 0;
38+
}
39+
.section-heading-action {
40+
--button-padding: 0.1rem 0.2rem 0;
41+
margin-block: -1rem;
42+
}
43+
`,
3744
];
3845

3946
@consume<State>({ context: stateContext, subscribe: true })
@@ -80,7 +87,18 @@ export class GlActiveWork extends SignalWatcher(LitElement) {
8087
return html`
8188
<h3 class="section-heading section-heading--actions">
8289
<span>Active (${activeBranches.length})</span>
83-
${when(overview!.choices, () => html`<gl-change-repo .options=${overview!.choices}></gl-change-repo>`)}
90+
${when(
91+
this._homeState.repositories.openCount > 1,
92+
() =>
93+
html`<span
94+
><gl-button
95+
class="section-heading-action"
96+
appearance="toolbar"
97+
tooltip="Change Repository"
98+
@click=${(e: MouseEvent) => this.onChange(e)}
99+
><code-icon icon="chevron-down"></code-icon></gl-button
100+
></span>`,
101+
)}
84102
</h3>
85103
${activeBranches.map(branch => this.renderRepoBranchCard(overview!.repository.name, branch))}
86104
`;
@@ -99,7 +117,7 @@ export class GlActiveWork extends SignalWatcher(LitElement) {
99117
${when(state, () => this.renderBranchStateActions(state, upstream))}
100118
<p class="branch-item__main">
101119
<span class="branch-item__icon">
102-
<code-icon icon=${branch.worktree ? 'gl-repositories-view' : 'git-branch'}></code-icon>
120+
<code-icon icon=${branch.worktree ? 'gl-worktrees-view' : 'git-branch'}></code-icon>
103121
</span>
104122
<span class="branch-item__name">${name}</span>
105123
</p>
@@ -217,77 +235,14 @@ export class GlActiveWork extends SignalWatcher(LitElement) {
217235

218236
return nothing;
219237
}
220-
}
221-
222-
@customElement('gl-change-repo')
223-
export class GlChangeRepo extends GlElement {
224-
static override styles = [
225-
css`
226-
.popover::part(body) {
227-
padding: 0;
228-
font-size: var(--vscode-font-size);
229-
background-color: var(--vscode-menu-background);
230-
}
231-
.trigger {
232-
--button-padding: 0.1rem 0.2rem 0;
233-
margin-block: -1rem;
234-
}
235-
236-
.option {
237-
max-width: 20rem;
238-
white-space: nowrap;
239-
overflow: hidden;
240-
text-overflow: ellipsis;
241-
}
242-
243-
.option code-icon {
244-
color: var(--color-foreground--50);
245-
}
246-
`,
247-
];
248-
249-
@consume({ context: overviewStateContext })
250-
private _overviewState!: OverviewState;
251-
252-
@property({ type: Array }) options?: RepositoryChoice[];
253-
254-
protected getLabel(option: RepositoryChoice) {
255-
return option.name;
256-
}
257-
258-
protected onChange(option: RepositoryChoice) {
259-
void this.querySelector('gl-popover')?.hide();
260-
void this._overviewState.changeRepository(option.path);
261-
}
262238

263-
override render() {
264-
if (!this.options) {
265-
return;
266-
}
267-
return html`
268-
<gl-popover class="popover" placement="bottom-end" trigger="focus" .distance=${4} .arrow=${false}>
269-
<gl-button class="trigger" appearance="toolbar" slot="anchor"
270-
><code-icon icon="chevron-down"></code-icon
271-
></gl-button>
272-
<div slot="content">
273-
${repeat(this.options, item => {
274-
if (item.selected) {
275-
return nothing;
276-
}
277-
const label = this.getLabel(item);
278-
return html`<menu-item class="option" @click=${() => this.onChange(item)}
279-
><code-icon icon="repo"></code-icon> ${label}</menu-item
280-
>`;
281-
})}
282-
</div>
283-
</gl-popover>
284-
`;
239+
private onChange(_e: MouseEvent) {
240+
void this._overviewState.changeRepository();
285241
}
286242
}
287243

288244
declare global {
289245
interface HTMLElementTagNameMap {
290246
[activeWorkTagName]: GlActiveWork;
291-
'gl-change-repo': GlChangeRepo;
292247
}
293248
}

src/webviews/apps/plus/home/components/branch-section.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,7 @@ export class GlBranchCard extends LitElement {
200200
return html`<pr-icon state=${branch.pr.state}></pr-icon>`;
201201
}
202202
if (branch.worktree) {
203-
return html`<code-icon icon="gl-repositories-view"></code-icon>`;
203+
return html`<code-icon icon="gl-worktrees-view"></code-icon>`;
204204
}
205205
return html`<code-icon icon="git-branch"></code-icon>`;
206206
}

src/webviews/apps/plus/home/components/overviewState.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,8 @@ export class OverviewState extends AsyncComputedState<Overview> {
5656

5757
filter = signalObject<Partial<OverviewFilters>>({});
5858

59-
async changeRepository(repo: string) {
60-
await this._ipc.sendRequest(ChangeOverviewRepository, repo);
59+
async changeRepository() {
60+
await this._ipc.sendRequest(ChangeOverviewRepository, undefined);
6161
this.run(true);
6262
}
6363
}

src/webviews/home/homeWebview.ts

Lines changed: 23 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import type { ConfigurationChangeEvent } from 'vscode';
22
import { Disposable, workspace } from 'vscode';
33
import { getAvatarUriFromGravatarEmail } from '../../avatars';
4+
import { GlyphChars } from '../../constants';
45
import type { ContextKeys } from '../../constants.context';
56
import type { WebviewTelemetryContext } from '../../constants.telemetry';
67
import type { Container } from '../../container';
@@ -16,6 +17,7 @@ import { getOpenedWorktreesByBranch, groupWorktreesByBranch } from '../../git/mo
1617
import type { Subscription } from '../../plus/gk/account/subscription';
1718
import type { SubscriptionChangeEvent } from '../../plus/gk/account/subscriptionService';
1819
import { getLaunchpadSummary } from '../../plus/launchpad/utils';
20+
import { showRepositoryPicker } from '../../quickpicks/repositoryPicker';
1921
import { map } from '../../system/iterable';
2022
import { getSettledValue } from '../../system/promise';
2123
import { registerCommand } from '../../system/vscode/command';
@@ -33,7 +35,6 @@ import type {
3335
OverviewFilters,
3436
OverviewRecentThreshold,
3537
OverviewStaleThreshold,
36-
RepositoryChoice,
3738
State,
3839
} from './protocol';
3940
import {
@@ -155,9 +156,26 @@ export class HomeWebviewProvider implements WebviewProvider<State, State, HomeWe
155156

156157
return true;
157158
}
158-
private onOverviewRepositoryChanged(e: string) {
159-
this._repositoryChoices = undefined;
160-
this.selectRepository(e);
159+
160+
private async onChooseRepository() {
161+
const currentRepo = this.getSelectedRepository();
162+
// Ensure that the current repository is always last
163+
const repositories = this.container.git.openRepositories.sort(
164+
(a, b) =>
165+
(a === currentRepo ? 1 : -1) - (b === currentRepo ? 1 : -1) ||
166+
(a.starred ? -1 : 1) - (b.starred ? -1 : 1) ||
167+
a.index - b.index,
168+
);
169+
170+
const pick = await showRepositoryPicker(
171+
`Switch Repository ${GlyphChars.Dot} ${currentRepo?.name}`,
172+
'Choose a repository to switch to',
173+
repositories,
174+
);
175+
176+
if (pick == null || pick === currentRepo) return;
177+
178+
this.selectRepository(pick.path);
161179
}
162180

163181
private async onRepositoriesChanged() {
@@ -214,7 +232,7 @@ export class HomeWebviewProvider implements WebviewProvider<State, State, HomeWe
214232
void this.host.respond(GetOverviewFilterState, e, this._overviewBranchFilter);
215233
break;
216234
case ChangeOverviewRepository.is(e):
217-
this.onOverviewRepositoryChanged(e.params);
235+
await this.onChooseRepository();
218236
void this.host.respond(ChangeOverviewRepository, e, undefined);
219237
break;
220238
}
@@ -354,7 +372,6 @@ export class HomeWebviewProvider implements WebviewProvider<State, State, HomeWe
354372
if (overviewBranches == null) return undefined;
355373

356374
const result: GetOverviewResponse = {
357-
choices: this.getRepositoryChoices(),
358375
repository: {
359376
name: repo.name,
360377
branches: overviewBranches,
@@ -364,23 +381,6 @@ export class HomeWebviewProvider implements WebviewProvider<State, State, HomeWe
364381
return result;
365382
}
366383

367-
private _repositoryChoices: RepositoryChoice[] | undefined;
368-
private getRepositoryChoices() {
369-
if (this._repositoryChoices == null) {
370-
const selectedRepo = this.getSelectedRepository()?.path;
371-
this._repositoryChoices = this.container.git.openRepositories.map(r => ({
372-
name: r.name,
373-
path: r.path,
374-
selected: r.path === selectedRepo,
375-
}));
376-
}
377-
if (this._repositoryChoices.length < 2) {
378-
return undefined;
379-
}
380-
381-
return this._repositoryChoices;
382-
}
383-
384384
private _repositorySubscription: RepositorySubscription | undefined;
385385
private selectRepository(repoPath?: string) {
386386
let repo: Repository | undefined;
@@ -483,7 +483,6 @@ export class HomeWebviewProvider implements WebviewProvider<State, State, HomeWe
483483
}
484484

485485
private notifyDidChangeRepositories() {
486-
this._repositoryChoices = undefined;
487486
void this.host.notify(DidChangeRepositories, this.getRepositoriesState());
488487
}
489488

src/webviews/home/protocol.ts

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -109,15 +109,8 @@ export interface GetOverviewBranches {
109109
stale: GetOverviewBranch[];
110110
}
111111

112-
export interface RepositoryChoice {
113-
name: string;
114-
path: string;
115-
selected: boolean;
116-
}
117-
118112
export type GetOverviewResponse =
119113
| {
120-
choices: RepositoryChoice[] | undefined;
121114
repository: {
122115
name: string;
123116
branches: GetOverviewBranches;
@@ -129,7 +122,7 @@ export const GetOverview = new IpcRequest<GetOverviewRequest, GetOverviewRespons
129122
export type GetOverviewFilterStateResponse = OverviewFilters;
130123
export const GetOverviewFilterState = new IpcRequest<void, GetOverviewFilterStateResponse>(scope, 'overviewFilter');
131124

132-
export const ChangeOverviewRepository = new IpcRequest<string, undefined>(scope, 'overview/repository/change');
125+
export const ChangeOverviewRepository = new IpcRequest<undefined, undefined>(scope, 'overview/repository/change');
133126

134127
// COMMANDS
135128

0 commit comments

Comments
 (0)