Archived
Hide Git panel outside repositories
This commit is contained in:
@@ -67,6 +67,7 @@ export function parseWorkspace(value: unknown): Workspace {
|
||||
label: requireString(record, "label"),
|
||||
...(branch === undefined ? {} : { branch }),
|
||||
isMain: requireBoolean(record, "isMain"),
|
||||
isGitRepo: requireBoolean(record, "isGitRepo"),
|
||||
isGitWorktree: requireBoolean(record, "isGitWorktree"),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ import { ProjectController } from "../controllers/projectController";
|
||||
import { SessionController } from "../controllers/sessionController";
|
||||
import { WorkspaceController } from "../controllers/workspaceController";
|
||||
import { KeyboardShortcutDispatcher } from "../keyboardShortcuts";
|
||||
import type { QualifiedContributionId, PluginRuntimeContext } from "../plugins/types";
|
||||
import type { QualifiedContributionId, QualifiedWorkspacePanelContribution, PluginRuntimeContext } from "../plugins/types";
|
||||
import { corePlugin } from "../plugins/core";
|
||||
import { examplePlugin } from "../plugins/example";
|
||||
import { PluginRegistry } from "../plugins/registry";
|
||||
@@ -179,7 +179,12 @@ export class PiWebApp extends LitElement {
|
||||
}
|
||||
|
||||
private renderWorkspacePanel() {
|
||||
return html`<workspace-panel .workspace=${this.state.selectedWorkspace} .tool=${this.state.workspaceTool} .panels=${this.plugins.getWorkspacePanels()} .fileTree=${this.state.fileTree} .expandedDirs=${this.state.expandedDirs} .selectedFilePath=${this.state.selectedFilePath} .selectedFileContent=${this.state.selectedFileContent} .fileTreeStale=${this.state.fileTreeStale} .gitStatus=${this.state.gitStatus} .selectedDiffPath=${this.state.selectedDiffPath} .selectedDiff=${this.state.selectedDiff} .selectedStagedDiff=${this.state.selectedStagedDiff} .gitStale=${this.state.gitStale} .onSelectTool=${(tool: QualifiedContributionId) => { this.selectWorkspaceTool(tool); }} .onRefreshFiles=${() => this.files.refreshFiles()} .onExpandDir=${(path: string) => this.files.expandDir(path)} .onSelectFile=${(path: string) => this.files.selectFile(path)} .onRefreshGit=${() => this.git.refreshGit()} .onSelectDiff=${(path: string) => this.git.selectDiff(path)}></workspace-panel>`;
|
||||
return html`<workspace-panel .workspace=${this.state.selectedWorkspace} .tool=${this.state.workspaceTool} .panels=${this.visibleWorkspacePanels()} .fileTree=${this.state.fileTree} .expandedDirs=${this.state.expandedDirs} .selectedFilePath=${this.state.selectedFilePath} .selectedFileContent=${this.state.selectedFileContent} .fileTreeStale=${this.state.fileTreeStale} .gitStatus=${this.state.gitStatus} .selectedDiffPath=${this.state.selectedDiffPath} .selectedDiff=${this.state.selectedDiff} .selectedStagedDiff=${this.state.selectedStagedDiff} .gitStale=${this.state.gitStale} .onSelectTool=${(tool: QualifiedContributionId) => { this.selectWorkspaceTool(tool); }} .onRefreshFiles=${() => this.files.refreshFiles()} .onExpandDir=${(path: string) => this.files.expandDir(path)} .onSelectFile=${(path: string) => this.files.selectFile(path)} .onRefreshGit=${() => this.git.refreshGit()} .onSelectDiff=${(path: string) => this.git.selectDiff(path)}></workspace-panel>`;
|
||||
}
|
||||
|
||||
private visibleWorkspacePanels(): QualifiedWorkspacePanelContribution[] {
|
||||
const workspace = this.state.selectedWorkspace;
|
||||
return this.plugins.getWorkspacePanels().filter((panel) => workspace === undefined || (panel.visible?.(workspace) ?? true));
|
||||
}
|
||||
|
||||
private getActions(): AppAction[] {
|
||||
@@ -223,7 +228,7 @@ export class PiWebApp extends LitElement {
|
||||
<main class=${state.mainView === "chat" ? "chat-view" : "workspace-view"}>
|
||||
<div class="mobile-tabs">
|
||||
<button class=${state.mainView === "chat" ? "selected" : ""} @click=${() => { this.selectMainView("chat"); }}>Chat</button>
|
||||
${this.plugins.getWorkspacePanels().map((panel) => html`
|
||||
${this.visibleWorkspacePanels().map((panel) => html`
|
||||
<button class=${state.mainView === panel.id ? "selected" : ""} @click=${() => { this.selectMainView(panel.id); }}>${panel.title}</button>
|
||||
`)}
|
||||
</div>
|
||||
|
||||
@@ -28,11 +28,12 @@ export class WorkspacePanel extends LitElement {
|
||||
|
||||
override render() {
|
||||
if (!this.workspace) return html`<section class="empty">Select a workspace.</section>`;
|
||||
const selectedPanel = this.panels.find((panel) => panel.id === this.tool) ?? this.panels[0];
|
||||
const visiblePanels = this.panels.filter((panel) => panel.visible?.(this.workspace as Workspace) ?? true);
|
||||
const selectedPanel = visiblePanels.find((panel) => panel.id === this.tool) ?? visiblePanels[0];
|
||||
return html`
|
||||
<header>
|
||||
<div class="tabs">
|
||||
${this.panels.map((panel) => html`
|
||||
${visiblePanels.map((panel) => html`
|
||||
<button class=${selectedPanel?.id === panel.id ? "selected" : ""} @click=${() => { this.onSelectTool(panel.id); }}>${panel.title}</button>
|
||||
`)}
|
||||
</div>
|
||||
|
||||
@@ -45,7 +45,7 @@ export function createCoreActions(): PluginAction[] {
|
||||
title: "Go to Git",
|
||||
shortcut: "mod+3",
|
||||
group: "Navigation",
|
||||
enabled: hasWorkspace,
|
||||
enabled: hasGitWorkspace,
|
||||
run: (context) => { context.selectMainView("core:workspace.git"); },
|
||||
},
|
||||
{
|
||||
@@ -61,7 +61,7 @@ export function createCoreActions(): PluginAction[] {
|
||||
title: "Refresh Git",
|
||||
shortcut: "mod+shift+g",
|
||||
group: "Workspace",
|
||||
enabled: hasWorkspace,
|
||||
enabled: hasGitWorkspace,
|
||||
run: (context) => context.refreshGit(),
|
||||
},
|
||||
{
|
||||
@@ -70,7 +70,7 @@ export function createCoreActions(): PluginAction[] {
|
||||
shortcut: "mod+shift+r",
|
||||
group: "Workspace",
|
||||
enabled: hasWorkspace,
|
||||
run: (context) => context.state.workspaceTool === "core:workspace.git" ? context.refreshGit() : context.refreshFiles(),
|
||||
run: (context) => context.state.workspaceTool === "core:workspace.git" && context.state.selectedWorkspace?.isGitRepo === true ? context.refreshGit() : context.refreshFiles(),
|
||||
},
|
||||
{
|
||||
id: "session.start",
|
||||
@@ -103,6 +103,10 @@ function hasWorkspace(context: { state: AppState }): boolean {
|
||||
return context.state.selectedWorkspace !== undefined;
|
||||
}
|
||||
|
||||
function hasGitWorkspace(context: { state: AppState }): boolean {
|
||||
return context.state.selectedWorkspace?.isGitRepo === true;
|
||||
}
|
||||
|
||||
function isActive(status: AppState["status"]): boolean {
|
||||
return status?.isStreaming === true || status?.isBashRunning === true || status?.isCompacting === true;
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ export function createCoreWorkspacePanels(): WorkspacePanelContribution[] {
|
||||
id: "workspace.git",
|
||||
title: "Git",
|
||||
order: 20,
|
||||
visible: (workspace) => workspace.isGitRepo,
|
||||
render: renderGit,
|
||||
},
|
||||
];
|
||||
|
||||
@@ -75,5 +75,5 @@ describe("PluginRegistry", () => {
|
||||
});
|
||||
|
||||
function testWorkspace(): AppState["selectedWorkspace"] {
|
||||
return { id: "w1", projectId: "p1", path: "/tmp/project", label: "main", isMain: true, isGitWorktree: false };
|
||||
return { id: "w1", projectId: "p1", path: "/tmp/project", label: "main", isMain: true, isGitRepo: true, isGitWorktree: false };
|
||||
}
|
||||
|
||||
@@ -74,6 +74,7 @@ export interface WorkspacePanelContribution {
|
||||
id: LocalContributionId;
|
||||
title: string;
|
||||
order?: number;
|
||||
visible?: (workspace: Workspace) => boolean;
|
||||
render: (context: WorkspacePanelContext) => TemplateResult;
|
||||
}
|
||||
|
||||
|
||||
@@ -7,12 +7,13 @@ const idFor = (value: string) => createHash("sha1").update(value).digest("hex").
|
||||
|
||||
export class WorkspaceService {
|
||||
async list(project: Project): Promise<Workspace[]> {
|
||||
if (!(await isGitRepository(project.path))) {
|
||||
return [this.single(project)];
|
||||
const isGitRepo = await isGitRepository(project.path);
|
||||
if (!isGitRepo) {
|
||||
return [this.single(project, false)];
|
||||
}
|
||||
|
||||
const worktrees = await discoverGitWorktrees(project.path);
|
||||
if (worktrees.length === 0) return [this.single(project)];
|
||||
if (worktrees.length === 0) return [this.single(project, true)];
|
||||
|
||||
return worktrees.map((worktree) => {
|
||||
const leafName = worktree.path.split("/").filter((part) => part !== "").at(-1);
|
||||
@@ -23,18 +24,20 @@ export class WorkspaceService {
|
||||
label: worktree.branch ?? (worktree.detached === true ? "detached" : leafName ?? worktree.path),
|
||||
...(worktree.branch === undefined ? {} : { branch: worktree.branch }),
|
||||
isMain: worktree.path === project.path,
|
||||
isGitRepo: true,
|
||||
isGitWorktree: true,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
private single(project: Project): Workspace {
|
||||
private single(project: Project, isGitRepo: boolean): Workspace {
|
||||
return {
|
||||
id: idFor(`${project.id}:${project.path}`),
|
||||
projectId: project.id,
|
||||
path: project.path,
|
||||
label: project.name,
|
||||
isMain: true,
|
||||
isGitRepo,
|
||||
isGitWorktree: false,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ export interface Workspace {
|
||||
label: string;
|
||||
branch?: string;
|
||||
isMain: boolean;
|
||||
isGitRepo: boolean;
|
||||
isGitWorktree: boolean;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user