Adds DiffSplitView component for side-by-side diff mode, whitespace-only change filtering, inline review comments with thread/gutter cell UI, diff preferences persistence, and write-file API support for in-browser editing. Backend: hideWhitespace param on git diff endpoint, write_file route.
69 lines
1.8 KiB
TypeScript
69 lines
1.8 KiB
TypeScript
import { useCallback, useEffect, useState } from 'react';
|
|
|
|
export interface DiffPreferences {
|
|
layout: 'unified' | 'split';
|
|
wrapLines: boolean;
|
|
hideWhitespace: boolean;
|
|
}
|
|
|
|
const DEFAULT_PREFERENCES: DiffPreferences = {
|
|
layout: 'unified',
|
|
wrapLines: false,
|
|
hideWhitespace: false,
|
|
};
|
|
|
|
const STORAGE_KEY = 'boocode.diff.preferences';
|
|
|
|
function loadPreferences(): DiffPreferences {
|
|
try {
|
|
const stored = localStorage.getItem(STORAGE_KEY);
|
|
if (stored) {
|
|
const parsed = JSON.parse(stored) as Partial<DiffPreferences>;
|
|
return {
|
|
layout: parsed.layout ?? DEFAULT_PREFERENCES.layout,
|
|
wrapLines: parsed.wrapLines ?? DEFAULT_PREFERENCES.wrapLines,
|
|
hideWhitespace: parsed.hideWhitespace ?? DEFAULT_PREFERENCES.hideWhitespace,
|
|
};
|
|
}
|
|
} catch {
|
|
// ignore parse errors
|
|
}
|
|
return DEFAULT_PREFERENCES;
|
|
}
|
|
|
|
function savePreferences(prefs: DiffPreferences): void {
|
|
try {
|
|
localStorage.setItem(STORAGE_KEY, JSON.stringify(prefs));
|
|
} catch {
|
|
// ignore storage errors
|
|
}
|
|
}
|
|
|
|
export function useDiffPreferences(): {
|
|
preferences: DiffPreferences;
|
|
updatePreferences: (updates: Partial<DiffPreferences>) => void;
|
|
resetPreferences: () => void;
|
|
} {
|
|
const [preferences, setPreferences] = useState<DiffPreferences>(loadPreferences);
|
|
|
|
// Sync from localStorage on mount (handles multi-tab changes if we add a storage listener later)
|
|
useEffect(() => {
|
|
setPreferences(loadPreferences());
|
|
}, []);
|
|
|
|
const updatePreferences = useCallback((updates: Partial<DiffPreferences>) => {
|
|
setPreferences((prev) => {
|
|
const next = { ...prev, ...updates };
|
|
savePreferences(next);
|
|
return next;
|
|
});
|
|
}, []);
|
|
|
|
const resetPreferences = useCallback(() => {
|
|
setPreferences(DEFAULT_PREFERENCES);
|
|
savePreferences(DEFAULT_PREFERENCES);
|
|
}, []);
|
|
|
|
return { preferences, updatePreferences, resetPreferences };
|
|
}
|