Archived
fix: reduce repeated workspace context
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@jmfederico/pi-web": patch
|
||||
---
|
||||
|
||||
Reduce repeated workspace details in the chat status bar and workspace tool header so workspace context stays in the workspace chip.
|
||||
@@ -726,7 +726,6 @@ export class PiWebApp extends LitElement {
|
||||
private renderWorkspacePanel() {
|
||||
const workspace = this.state.selectedWorkspace;
|
||||
const panelContext = workspace === undefined ? undefined : this.createWorkspacePanelContext(workspace);
|
||||
const workspaceLabelItems = workspace === undefined ? [] : this.workspaceLabelItems(workspace);
|
||||
const emptyState = workspace === undefined ? this.workspacePanelEmptyState() : undefined;
|
||||
return html`
|
||||
<workspace-panel
|
||||
@@ -736,7 +735,6 @@ export class PiWebApp extends LitElement {
|
||||
.emptyState=${emptyState}
|
||||
.tool=${this.state.workspaceTool}
|
||||
.panels=${this.visibleWorkspacePanels()}
|
||||
.workspaceLabelItems=${workspaceLabelItems}
|
||||
.onSelectTool=${(tool: QualifiedContributionId) => { this.openWorkspaceTool(tool); }}
|
||||
></workspace-panel>
|
||||
`;
|
||||
@@ -1384,7 +1382,7 @@ export class PiWebApp extends LitElement {
|
||||
${state.selectedSession ? html`
|
||||
<chat-view .sessionId=${state.selectedSession.id} .messages=${state.messages} .messageStart=${state.messagePageStart} .messageEnd=${state.messagePageEnd} .messageTotal=${state.messagePageTotal} .hasMore=${state.messagePageStart > 0} .loadingMore=${state.isLoadingEarlierMessages} .isReceivingPartialStream=${state.isReceivingPartialStream} .isCompacting=${state.status?.isCompacting === true} .pendingMessageCount=${state.status?.pendingMessageCount ?? 0} .status=${state.status} .activity=${state.activity} .onLoadMore=${() => this.withChatPrependTransition(() => this.sessions.loadEarlierMessages())}></chat-view>
|
||||
<prompt-editor .sessionId=${state.selectedSession.id} .cwd=${state.selectedWorkspace?.path} .machineId=${selectedMachineId(state)} .disabled=${state.selectedSession.archived === true} .canSteer=${state.status?.isStreaming === true} .isCompacting=${state.status?.isCompacting === true} .canStop=${state.status?.isStreaming === true || state.status?.isBashRunning === true || state.status?.isCompacting === true || (state.status?.pendingMessageCount ?? 0) > 0} .status=${state.status} .onSend=${(text: string, streamingBehavior?: "steer" | "followUp") => { this.sendPrompt(text, streamingBehavior); }} .onStop=${() => this.sessions.stopActiveWork()} .onSelectModel=${() => { void this.openModelDialog(); }} .onSelectThinking=${() => { void this.openThinkingDialog(); }}></prompt-editor>
|
||||
<status-bar .status=${state.status} .machine=${state.selectedMachine} .workspace=${state.selectedWorkspace} .workspaceLabelItems=${state.selectedWorkspace === undefined ? [] : this.workspaceLabelItems(state.selectedWorkspace)}></status-bar>
|
||||
<status-bar .status=${state.status} .machine=${state.selectedMachine}></status-bar>
|
||||
${state.commandDialog !== undefined ? html`<command-picker .title=${state.commandDialog.title} .options=${state.commandDialog.options} .onPick=${(value: string) => this.sessions.respondToCommand(state.commandDialog?.requestId ?? "", value)} .onCancel=${() => { this.sessions.cancelCommand(); }}></command-picker>` : null}
|
||||
${state.modelDialog !== undefined ? html`<command-picker title=${state.modelDialog.title} .searchable=${true} .options=${state.modelDialog.options} .selectedValue=${state.modelDialog.selectedValue} .onPick=${(value: string) => { void this.pickModel(value); }} .onCancel=${() => { this.setState({ modelDialog: undefined }); }}></command-picker>` : null}
|
||||
${state.thinkingDialog !== undefined ? html`<command-picker title=${state.thinkingDialog.title} .options=${state.thinkingDialog.options} .selectedValue=${state.thinkingDialog.selectedValue} .onPick=${(value: string) => { void this.pickThinking(value); }} .onCancel=${() => { this.setState({ thinkingDialog: undefined }); }}></command-picker>` : null}
|
||||
|
||||
@@ -1,17 +1,13 @@
|
||||
import { LitElement, html } from "lit";
|
||||
import { customElement, property } from "lit/decorators.js";
|
||||
import type { Machine, SessionStatus, Workspace } from "../api";
|
||||
import type { WorkspaceLabelItem } from "../plugins/types";
|
||||
import type { Machine, SessionStatus } from "../api";
|
||||
import { formatCost, formatTokenCount } from "../utils/format";
|
||||
import { statusBarStyles } from "./shared";
|
||||
import { renderWorkspaceLabel } from "./workspaceLabel";
|
||||
|
||||
@customElement("status-bar")
|
||||
export class StatusBar extends LitElement {
|
||||
@property({ attribute: false }) status?: SessionStatus;
|
||||
@property({ attribute: false }) machine?: Machine;
|
||||
@property({ attribute: false }) workspace?: Workspace;
|
||||
@property({ attribute: false }) workspaceLabelItems: WorkspaceLabelItem[] = [];
|
||||
|
||||
override render() {
|
||||
const status = this.status;
|
||||
@@ -26,7 +22,6 @@ export class StatusBar extends LitElement {
|
||||
return html`
|
||||
<div class="bar">
|
||||
<span>${this.machine?.name ?? "Local"}</span>
|
||||
<span>${renderWorkspaceLabel(this.workspace?.label ?? "workspace", this.workspaceLabelItems, this.workspace?.path)}</span>
|
||||
<span>↑${formatTokenCount(tokens.input)}</span>
|
||||
<span>↓${formatTokenCount(tokens.output)}</span>
|
||||
<span>${contextText}</span>
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
import { LitElement, html, type TemplateResult } from "lit";
|
||||
import { customElement, property, query, state } from "lit/decorators.js";
|
||||
import type { Workspace } from "../api";
|
||||
import type { QualifiedContributionId, QualifiedWorkspacePanelContribution, WorkspaceLabelItem, WorkspacePanelContext } from "../plugins/types";
|
||||
import type { QualifiedContributionId, QualifiedWorkspacePanelContribution, WorkspacePanelContext } from "../plugins/types";
|
||||
import { workspacePanelStyles } from "./shared";
|
||||
import { renderWorkspaceLabel } from "./workspaceLabel";
|
||||
|
||||
export interface WorkspacePanelEmptyState {
|
||||
title: string;
|
||||
@@ -19,7 +18,6 @@ export class WorkspacePanel extends LitElement {
|
||||
@property({ attribute: false }) emptyState: WorkspacePanelEmptyState | undefined;
|
||||
@property() tool: QualifiedContributionId = "core:workspace.files";
|
||||
@property({ attribute: false }) panels: QualifiedWorkspacePanelContribution[] = [];
|
||||
@property({ attribute: false }) workspaceLabelItems: WorkspaceLabelItem[] = [];
|
||||
@property({ type: Boolean }) hideToolTabs = false;
|
||||
@property({ attribute: false }) onSelectTool: (tool: QualifiedContributionId) => void = () => undefined;
|
||||
@query(".workspace-header-strip") private workspaceHeaderStrip?: HTMLElement | null;
|
||||
@@ -63,10 +61,10 @@ export class WorkspacePanel extends LitElement {
|
||||
const visiblePanels = this.panels;
|
||||
const selectedPanel = visiblePanels.find((panel) => panel.id === this.tool) ?? visiblePanels[0];
|
||||
return html`
|
||||
<header>
|
||||
<div class=${this.workspaceHeaderFrameClass()}>
|
||||
<div class="workspace-header-strip" @scroll=${this.onWorkspaceHeaderScroll}>
|
||||
${this.hideToolTabs ? null : html`
|
||||
${this.hideToolTabs ? null : html`
|
||||
<header>
|
||||
<div class=${this.workspaceHeaderFrameClass()}>
|
||||
<div class="workspace-header-strip" @scroll=${this.onWorkspaceHeaderScroll}>
|
||||
<div class="tabs">
|
||||
${visiblePanels.map((panel) => {
|
||||
const selected = selectedPanel?.id === panel.id;
|
||||
@@ -79,11 +77,10 @@ export class WorkspacePanel extends LitElement {
|
||||
`;
|
||||
})}
|
||||
</div>
|
||||
`}
|
||||
<small>${renderWorkspaceLabel(workspace.label, this.workspaceLabelItems, workspace.path)}</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
</header>
|
||||
`}
|
||||
${selectedPanel === undefined ? this.renderEmptyState({
|
||||
title: "No workspace tools available",
|
||||
body: "No tools are available for this workspace.",
|
||||
|
||||
@@ -186,10 +186,7 @@ export const workspacePanelStyles = css`
|
||||
.empty-state h2 { margin: 0; color: var(--pi-text); font-size: 15px; line-height: 1.3; }
|
||||
.empty-state p { margin: 0; line-height: 1.45; }
|
||||
small, .muted { color: var(--pi-muted); }
|
||||
header small { flex: 0 0 auto; min-width: max-content; overflow: visible; text-overflow: clip; white-space: nowrap; }
|
||||
header .workspace-label { width: max-content; max-width: none; overflow: visible; }
|
||||
header .workspace-label-base, header .workspace-label-item, header .workspace-label-render { overflow: visible; text-overflow: clip; }
|
||||
@media (max-width: 1180px) { .tabs { display: none; } }
|
||||
@media (max-width: 1180px) { header { display: none; } }
|
||||
.workspace-label { min-width: 0; display: inline-flex; align-items: baseline; gap: 5px; max-width: 100%; overflow: hidden; white-space: nowrap; }
|
||||
.workspace-label-base, .workspace-label-item, .workspace-label-render { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
|
||||
.workspace-label-item, .workspace-label-render, .workspace-label-separator { color: var(--pi-muted); }
|
||||
@@ -395,11 +392,6 @@ export const statusBarStyles = css`
|
||||
:host { display: block; color: var(--pi-muted); font: 12px system-ui, sans-serif; }
|
||||
.bar { display: flex; gap: 12px; align-items: center; min-width: 0; padding: 7px 12px; border-top: 1px solid var(--pi-border); background: var(--pi-bg); white-space: nowrap; overflow: hidden; }
|
||||
span { overflow: hidden; text-overflow: ellipsis; }
|
||||
.workspace-label { min-width: 0; display: inline-flex; align-items: baseline; gap: 5px; max-width: 100%; overflow: hidden; white-space: nowrap; }
|
||||
.workspace-label-base, .workspace-label-item, .workspace-label-render { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
|
||||
.workspace-label-item, .workspace-label-render, .workspace-label-separator { color: var(--pi-muted); }
|
||||
.workspace-label-link { color: var(--pi-accent); text-decoration: none; }
|
||||
.workspace-label-link:hover, .workspace-label-link:focus { text-decoration: underline; }
|
||||
.bar > span:first-child { flex: 1 1 auto; min-width: 80px; }
|
||||
.activity { display: inline-flex; align-items: center; gap: 6px; color: var(--pi-muted); }
|
||||
.activity.active { color: var(--pi-success); }
|
||||
|
||||
Reference in New Issue
Block a user