F10 SLICE-3: ProposalController.listProposals + onDidChangeProposals + keyFor (#29)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -18,6 +18,7 @@ import { addProposal, removeProposal } from "./proposalModel";
|
||||
import type { AttributionController } from "./attributionController";
|
||||
import type { VersionGuard } from "./versionGuard";
|
||||
import { isAuthorable } from "./workspacePath";
|
||||
import type { ProposalView } from "./trackChangesModel";
|
||||
|
||||
/** Test-facing snapshot of what is currently rendered for a document. */
|
||||
export interface RenderedProposal {
|
||||
@@ -44,6 +45,9 @@ export class ProposalController implements vscode.Disposable {
|
||||
private readonly disposables: vscode.Disposable[] = [];
|
||||
private readonly docs = new Map<string, DocState>(); // keyed by docPath
|
||||
private readonly statusItem = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Right, 89);
|
||||
private readonly onDidChangeProposalsEmitter = new vscode.EventEmitter<{ uri: string }>();
|
||||
/** Fires on propose / accept / reject / external sidecar change (F10). */
|
||||
readonly onDidChangeProposals = this.onDidChangeProposalsEmitter.event;
|
||||
|
||||
constructor(
|
||||
private readonly store: SidecarRouter,
|
||||
@@ -52,11 +56,16 @@ export class ProposalController implements vscode.Disposable {
|
||||
private readonly guard: VersionGuard,
|
||||
) {
|
||||
this.disposables.push(this.statusItem);
|
||||
this.disposables.push(this.onDidChangeProposalsEmitter);
|
||||
this.disposables.push(
|
||||
vscode.workspace.onDidChangeTextDocument((e) => this.onDidChange(e)),
|
||||
);
|
||||
}
|
||||
|
||||
private fireChanged(document: vscode.TextDocument): void {
|
||||
this.onDidChangeProposalsEmitter.fire({ uri: document.uri.toString() });
|
||||
}
|
||||
|
||||
private isTracked(document: vscode.TextDocument): boolean {
|
||||
return isAuthorable(document.uri.scheme);
|
||||
}
|
||||
@@ -64,6 +73,27 @@ export class ProposalController implements vscode.Disposable {
|
||||
private keyOf(document: vscode.TextDocument): string {
|
||||
return this.store.keyOf(docIdentity(document));
|
||||
}
|
||||
/** The doc key F4 uses (F8 routing) — exposed for F10's preview. */
|
||||
keyFor(document: vscode.TextDocument): string {
|
||||
return this.keyOf(document);
|
||||
}
|
||||
/** Resolved proposal views for the F10 preview (anchorStart=null when unresolved). */
|
||||
listProposals(document: vscode.TextDocument): ProposalView[] {
|
||||
const docPath = this.keyOf(document);
|
||||
const artifact = this.store.load(docPath) ?? emptyArtifact(docPath);
|
||||
const text = document.getText();
|
||||
return artifact.proposals.map((p) => {
|
||||
const fp = artifact.anchors[p.anchorId]?.fingerprint;
|
||||
const resolved = fp ? resolve(text, fp) : "orphaned";
|
||||
return {
|
||||
id: p.id,
|
||||
anchorStart: resolved === "orphaned" ? null : resolved.start,
|
||||
anchorEnd: resolved === "orphaned" ? null : resolved.end,
|
||||
replaced: fp?.text ?? "",
|
||||
replacement: p.replacement,
|
||||
};
|
||||
});
|
||||
}
|
||||
private ensureState(document: vscode.TextDocument): DocState {
|
||||
const docPath = this.keyOf(document);
|
||||
let state = this.docs.get(docPath);
|
||||
@@ -181,6 +211,7 @@ export class ProposalController implements vscode.Disposable {
|
||||
}
|
||||
}
|
||||
this.renderStatus(state);
|
||||
this.fireChanged(document);
|
||||
}
|
||||
|
||||
/** Shared-watcher entry point (extension.ts): a sidecar changed externally. */
|
||||
|
||||
Reference in New Issue
Block a user