andy-stack_vaultkeeper-ai/Views/DiffView.ts
Andrew Beal 2d5a1b52bf feat: add interactive diff viewer with user approval workflow
Implement a comprehensive diff viewing system that allows users to review and approve/reject file changes before they're applied. The system includes event-driven architecture for managing diff lifecycle and integrates diff2html for rich visual diffs.

Key changes:
- Add DiffService for managing diff approval workflow with accept/reject/suggest actions
- Create EventService for type-safe event handling (DiffOpened/DiffClosed)
- Add DiffView component with diff2html integration for visual diff rendering
- Modify VaultService to propose changes and require confirmation before file operations
- Update FileSystemService to support optional confirmation for write operations
- Add Event enum for centralized event type definitions
- Import custom styles and diff2html styles for proper diff rendering
- Update ConversationContent validation to support optional toolId field
- Remove FileManager from dependency injection (now accessed directly from app)
- Update .gitignore to track styles.css instead of main.css
2025-11-24 21:29:54 +00:00

61 lines
No EOL
1.5 KiB
TypeScript

import { Diff2HtmlUI, type Diff2HtmlUIConfig } from "diff2html/lib/ui/js/diff2html-ui";
import { ItemView, WorkspaceLeaf, type ViewStateResult } from "obsidian";
export const VIEW_TYPE_DIFF = 'vaultkeeper-ai-diff-view';
interface DiffViewState {
diffString: string;
config: Diff2HtmlUIConfig;
}
export class DiffView extends ItemView {
private diffString: string = "";
private config: Diff2HtmlUIConfig = {};
private diffContainer: HTMLElement | null = null;
constructor(leaf: WorkspaceLeaf) {
super(leaf);
}
public getViewType(): string {
return VIEW_TYPE_DIFF;
}
public getDisplayText(): string {
return "Vaultkeeper AI diff";
}
public async setState(state: DiffViewState, result: ViewStateResult): Promise<void> {
this.diffString = state.diffString;
this.config = state.config;
this.renderDiff();
return super.setState(state, result);
}
public getState(): Record<string, unknown> {
return {
diffString: this.diffString,
config: this.config
};
}
private renderDiff() {
const container = this.contentEl;
container.empty();
if (this.diffContainer) {
this.diffContainer.remove();
this.diffContainer = null
}
this.diffContainer = container.createDiv({ cls: 'd2h-wrapper' });
const diff2htmlUi = new Diff2HtmlUI(this.diffContainer, this.diffString, this.config);
diff2htmlUi.draw();
}
}