2025-11-24 21:29:54 +00:00
|
|
|
import { Diff2HtmlUI, type Diff2HtmlUIConfig } from "diff2html/lib/ui/js/diff2html-ui";
|
2025-11-27 12:39:08 +00:00
|
|
|
import { Event } from "Enums/Event";
|
2025-11-24 21:29:54 +00:00
|
|
|
import { ItemView, WorkspaceLeaf, type ViewStateResult } from "obsidian";
|
2025-11-27 12:39:08 +00:00
|
|
|
import { Resolve } from "Services/DependencyService";
|
|
|
|
|
import type { EventService } from "Services/EventService";
|
|
|
|
|
import { Services } from "Services/Services";
|
2025-11-24 21:29:54 +00:00
|
|
|
|
|
|
|
|
export const VIEW_TYPE_DIFF = 'vaultkeeper-ai-diff-view';
|
|
|
|
|
|
|
|
|
|
interface DiffViewState {
|
|
|
|
|
diffString: string;
|
|
|
|
|
config: Diff2HtmlUIConfig;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export class DiffView extends ItemView {
|
2025-11-27 12:39:08 +00:00
|
|
|
|
|
|
|
|
private readonly eventService: EventService;
|
|
|
|
|
|
2025-11-24 21:29:54 +00:00
|
|
|
private diffString: string = "";
|
|
|
|
|
private config: Diff2HtmlUIConfig = {};
|
|
|
|
|
|
|
|
|
|
private diffContainer: HTMLElement | null = null;
|
|
|
|
|
|
|
|
|
|
constructor(leaf: WorkspaceLeaf) {
|
|
|
|
|
super(leaf);
|
2025-11-27 12:39:08 +00:00
|
|
|
|
|
|
|
|
this.eventService = Resolve<EventService>(Services.EventService);
|
|
|
|
|
|
|
|
|
|
this.registerEvent(this.eventService.on(Event.DiffClosed, () => {
|
|
|
|
|
this.leaf.detach();
|
|
|
|
|
}));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected override onClose(): Promise<void> {
|
|
|
|
|
// trigger DiffClosed event in case the user closed the tab
|
|
|
|
|
this.eventService.trigger(Event.DiffClosed);
|
|
|
|
|
return Promise.resolve();
|
2025-11-24 21:29:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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() {
|
2025-11-27 12:39:08 +00:00
|
|
|
const container = this.resetContainer();
|
|
|
|
|
|
|
|
|
|
this.diffContainer = container.createDiv({ cls: 'd2h-wrapper' });
|
|
|
|
|
const diff2htmlUi = new Diff2HtmlUI(this.diffContainer, this.diffString, this.config);
|
|
|
|
|
|
|
|
|
|
diff2htmlUi.draw();
|
2025-12-05 18:39:01 +00:00
|
|
|
diff2htmlUi.highlightCode();
|
|
|
|
|
|
|
|
|
|
requestAnimationFrame(() => {
|
|
|
|
|
const firstChange = this.diffContainer?.querySelector('.d2h-change, .d2h-ins, .d2h-del');
|
|
|
|
|
firstChange?.scrollIntoView({ behavior: 'smooth', block: 'center' });
|
|
|
|
|
});
|
2025-11-27 12:39:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private resetContainer(): HTMLElement {
|
2025-11-24 21:29:54 +00:00
|
|
|
const container = this.contentEl;
|
|
|
|
|
container.empty();
|
|
|
|
|
|
|
|
|
|
if (this.diffContainer) {
|
|
|
|
|
this.diffContainer.remove();
|
|
|
|
|
this.diffContainer = null
|
|
|
|
|
}
|
2025-11-27 12:39:08 +00:00
|
|
|
return container;
|
2025-11-24 21:29:54 +00:00
|
|
|
}
|
2025-11-27 12:39:08 +00:00
|
|
|
|
2025-11-24 21:29:54 +00:00
|
|
|
}
|