Polish diff view hunk controls
This commit is contained in:
@@ -99,7 +99,7 @@
|
|||||||
},
|
},
|
||||||
"packages/electron": {
|
"packages/electron": {
|
||||||
"name": "@openchamber/electron",
|
"name": "@openchamber/electron",
|
||||||
"version": "1.12.3",
|
"version": "1.12.4",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@openchamber/web": "workspace:*",
|
"@openchamber/web": "workspace:*",
|
||||||
"electron-context-menu": "^4.1.2",
|
"electron-context-menu": "^4.1.2",
|
||||||
@@ -114,7 +114,7 @@
|
|||||||
},
|
},
|
||||||
"packages/ui": {
|
"packages/ui": {
|
||||||
"name": "@openchamber/ui",
|
"name": "@openchamber/ui",
|
||||||
"version": "1.12.3",
|
"version": "1.12.4",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@base-ui/react": "^1.4.0",
|
"@base-ui/react": "^1.4.0",
|
||||||
"@codemirror/autocomplete": "^6.20.0",
|
"@codemirror/autocomplete": "^6.20.0",
|
||||||
@@ -146,7 +146,7 @@
|
|||||||
"@ibm/plex": "^6.4.1",
|
"@ibm/plex": "^6.4.1",
|
||||||
"@lezer/highlight": "^1.2.3",
|
"@lezer/highlight": "^1.2.3",
|
||||||
"@opencode-ai/sdk": "^1.17.0",
|
"@opencode-ai/sdk": "^1.17.0",
|
||||||
"@pierre/diffs": "1.1.0-beta.13",
|
"@pierre/diffs": "1.3.0-beta.4",
|
||||||
"@replit/codemirror-vim": "^6.3.0",
|
"@replit/codemirror-vim": "^6.3.0",
|
||||||
"@simplewebauthn/browser": "13.3.0",
|
"@simplewebauthn/browser": "13.3.0",
|
||||||
"@tanstack/react-virtual": "^3.13.18",
|
"@tanstack/react-virtual": "^3.13.18",
|
||||||
@@ -216,7 +216,7 @@
|
|||||||
},
|
},
|
||||||
"packages/vscode": {
|
"packages/vscode": {
|
||||||
"name": "openchamber",
|
"name": "openchamber",
|
||||||
"version": "1.12.3",
|
"version": "1.12.4",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@openchamber/ui": "workspace:*",
|
"@openchamber/ui": "workspace:*",
|
||||||
"@opencode-ai/sdk": "^1.17.0",
|
"@opencode-ai/sdk": "^1.17.0",
|
||||||
@@ -239,7 +239,7 @@
|
|||||||
},
|
},
|
||||||
"packages/web": {
|
"packages/web": {
|
||||||
"name": "@openchamber/web",
|
"name": "@openchamber/web",
|
||||||
"version": "1.12.3",
|
"version": "1.12.4",
|
||||||
"bin": {
|
"bin": {
|
||||||
"openchamber": "./bin/cli.js",
|
"openchamber": "./bin/cli.js",
|
||||||
},
|
},
|
||||||
@@ -969,7 +969,11 @@
|
|||||||
|
|
||||||
"@peculiar/x509": ["@peculiar/x509@1.14.3", "", { "dependencies": { "@peculiar/asn1-cms": "^2.6.0", "@peculiar/asn1-csr": "^2.6.0", "@peculiar/asn1-ecc": "^2.6.0", "@peculiar/asn1-pkcs9": "^2.6.0", "@peculiar/asn1-rsa": "^2.6.0", "@peculiar/asn1-schema": "^2.6.0", "@peculiar/asn1-x509": "^2.6.0", "pvtsutils": "^1.3.6", "reflect-metadata": "^0.2.2", "tslib": "^2.8.1", "tsyringe": "^4.10.0" } }, "sha512-C2Xj8FZ0uHWeCXXqX5B4/gVFQmtSkiuOolzAgutjTfseNOHT3pUjljDZsTSxXFGgio54bCzVFqmEOUrIVk8RDA=="],
|
"@peculiar/x509": ["@peculiar/x509@1.14.3", "", { "dependencies": { "@peculiar/asn1-cms": "^2.6.0", "@peculiar/asn1-csr": "^2.6.0", "@peculiar/asn1-ecc": "^2.6.0", "@peculiar/asn1-pkcs9": "^2.6.0", "@peculiar/asn1-rsa": "^2.6.0", "@peculiar/asn1-schema": "^2.6.0", "@peculiar/asn1-x509": "^2.6.0", "pvtsutils": "^1.3.6", "reflect-metadata": "^0.2.2", "tslib": "^2.8.1", "tsyringe": "^4.10.0" } }, "sha512-C2Xj8FZ0uHWeCXXqX5B4/gVFQmtSkiuOolzAgutjTfseNOHT3pUjljDZsTSxXFGgio54bCzVFqmEOUrIVk8RDA=="],
|
||||||
|
|
||||||
"@pierre/diffs": ["@pierre/diffs@1.1.0-beta.13", "", { "dependencies": { "@shikijs/transformers": "^3.0.0", "diff": "8.0.3", "hast-util-to-html": "9.0.5", "lru_map": "0.4.1", "shiki": "^3.0.0" }, "peerDependencies": { "react": "^18.3.1 || ^19.0.0", "react-dom": "^18.3.1 || ^19.0.0" } }, "sha512-D35rxDu5V7XHX5aVGU6PF12GhscL+I+9QYgxK/i3h0d2XSirAxDdVNm49aYwlOhgmdvL0NbS1IHxPswVB5yJvw=="],
|
"@pierre/diffs": ["@pierre/diffs@1.3.0-beta.4", "", { "dependencies": { "@pierre/theme": "1.0.3", "@pierre/theming": "0.0.1", "@shikijs/transformers": "^3.0.0", "diff": "8.0.3", "hast-util-to-html": "9.0.5", "lru_map": "0.4.1", "shiki": "^3.0.0" }, "peerDependencies": { "react": "^18.3.1 || ^19.0.0", "react-dom": "^18.3.1 || ^19.0.0" } }, "sha512-poFcsvhcQt9lH/InzAPaGs47WYHMidnFCjuYGNU41HiVLJP4mkIQDSdvcnPIkBuh/cYbPOQg/YE3T1kSpr01GA=="],
|
||||||
|
|
||||||
|
"@pierre/theme": ["@pierre/theme@1.0.3", "", {}, "sha512-sWHv11TMoqKxKDgTIk5VbhQjdPhs8DCcBxbjh3mRlS3YOM/OcrWoGX6MM8eBGn9cUu3M46Py0JnxsG2nJaFTuA=="],
|
||||||
|
|
||||||
|
"@pierre/theming": ["@pierre/theming@0.0.1", "", { "peerDependencies": { "@pierre/theme": "^1.0.0", "@shikijs/themes": "^3.0.0 || ^4.0.0", "react": "^18.3.1 || ^19.0.0", "react-dom": "^18.3.1 || ^19.0.0", "shiki": "^3.0.0 || ^4.0.0" }, "optionalPeers": ["@pierre/theme", "@shikijs/themes", "react", "react-dom", "shiki"] }, "sha512-1thlEtJbqdyLzc1ZS2KQa1q7FzDGHT4dTEdKHoyQjOMeWWOmbVG5/ndEfOKfAb5Fzkz8cNJrOjFLiZoDH/A03A=="],
|
||||||
|
|
||||||
"@pkgjs/parseargs": ["@pkgjs/parseargs@0.11.0", "", {}, "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg=="],
|
"@pkgjs/parseargs": ["@pkgjs/parseargs@0.11.0", "", {}, "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg=="],
|
||||||
|
|
||||||
|
|||||||
@@ -41,7 +41,7 @@
|
|||||||
"@ibm/plex": "^6.4.1",
|
"@ibm/plex": "^6.4.1",
|
||||||
"@lezer/highlight": "^1.2.3",
|
"@lezer/highlight": "^1.2.3",
|
||||||
"@opencode-ai/sdk": "^1.17.0",
|
"@opencode-ai/sdk": "^1.17.0",
|
||||||
"@pierre/diffs": "1.1.0-beta.13",
|
"@pierre/diffs": "1.3.0-beta.4",
|
||||||
"@replit/codemirror-vim": "^6.3.0",
|
"@replit/codemirror-vim": "^6.3.0",
|
||||||
"@simplewebauthn/browser": "13.3.0",
|
"@simplewebauthn/browser": "13.3.0",
|
||||||
"@tanstack/react-virtual": "^3.13.18",
|
"@tanstack/react-virtual": "^3.13.18",
|
||||||
|
|||||||
@@ -119,7 +119,7 @@ const TOOL_DIFF_METRICS = {
|
|||||||
lineHeight: 24,
|
lineHeight: 24,
|
||||||
diffHeaderHeight: 44,
|
diffHeaderHeight: 44,
|
||||||
hunkSeparatorHeight: 24,
|
hunkSeparatorHeight: 24,
|
||||||
fileGap: 0,
|
spacing: 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
const usePierreThemeConfig = (): PierreThemeConfig => {
|
const usePierreThemeConfig = (): PierreThemeConfig => {
|
||||||
|
|||||||
@@ -1388,7 +1388,7 @@ const TOOL_DIFF_METRICS = {
|
|||||||
lineHeight: 24,
|
lineHeight: 24,
|
||||||
diffHeaderHeight: 44,
|
diffHeaderHeight: 44,
|
||||||
hunkSeparatorHeight: 24,
|
hunkSeparatorHeight: 24,
|
||||||
fileGap: 0,
|
spacing: 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
const TOOL_COLLAPSED_CUSTOM_STYLE: React.CSSProperties = {
|
const TOOL_COLLAPSED_CUSTOM_STYLE: React.CSSProperties = {
|
||||||
|
|||||||
@@ -599,15 +599,15 @@ const MultiFileDiffEntry = React.memo<MultiFileDiffEntryProps>(({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div ref={setSectionRef} className="scroll-mt-9 border-b border-[var(--interactive-border)]/40 last:border-b-0">
|
<div ref={setSectionRef} className="scroll-mt-9 border-b border-[var(--interactive-border)]/40 last:border-b-0">
|
||||||
<div className="sticky top-0 z-10 bg-[var(--surface-muted)]">
|
<div className="sticky top-0 z-10 border-b border-[var(--interactive-border)]/35 bg-[var(--surface-elevated)]/90 backdrop-blur-md supports-[backdrop-filter]:bg-[var(--surface-elevated)]/80">
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={handleToggle}
|
onClick={handleToggle}
|
||||||
className={cn(
|
className={cn(
|
||||||
'group/header relative flex w-full items-center gap-2 px-3 py-1.5 overflow-hidden',
|
'group/header relative flex min-h-9 w-full items-center gap-2 overflow-hidden px-3 py-2',
|
||||||
'bg-transparent',
|
'bg-transparent',
|
||||||
'text-muted-foreground hover:text-foreground',
|
'text-muted-foreground hover:text-foreground',
|
||||||
isSelected ? 'bg-[var(--interactive-selection)]/40' : null
|
isSelected ? 'bg-[var(--interactive-selection)]/35' : null
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<div className="absolute inset-0 pointer-events-none group-hover/header:bg-[var(--interactive-hover)]/50" />
|
<div className="absolute inset-0 pointer-events-none group-hover/header:bg-[var(--interactive-hover)]/50" />
|
||||||
|
|||||||
@@ -91,6 +91,104 @@ const WEBKIT_SCROLL_FIX_CSS = `
|
|||||||
height: 24px !important;
|
height: 24px !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[data-separator="line-info-basic"] {
|
||||||
|
height: 24px !important;
|
||||||
|
background: var(--diffs-bg) !important;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-diff-type="single"] [data-gutter],
|
||||||
|
[data-diff-type="split"] [data-deletions] [data-gutter] {
|
||||||
|
[data-separator-wrapper] {
|
||||||
|
position: absolute;
|
||||||
|
left: 100%;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: unset;
|
||||||
|
width: max-content;
|
||||||
|
background: transparent;
|
||||||
|
color: var(--diffs-fg-number);
|
||||||
|
font-family: var(--diffs-header-font-family, var(--font-sans));
|
||||||
|
font-size: 0.75rem;
|
||||||
|
line-height: 1;
|
||||||
|
margin-left: calc(-2ch - 2px);
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-separator-wrapper][data-separator-multi-button] {
|
||||||
|
margin-left: calc(-3ch - 2px);
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-expand-button],
|
||||||
|
[data-separator-content] {
|
||||||
|
display: block;
|
||||||
|
align-self: unset;
|
||||||
|
min-width: unset;
|
||||||
|
min-height: unset;
|
||||||
|
padding: 0;
|
||||||
|
flex-shrink: 0;
|
||||||
|
grid-column: unset;
|
||||||
|
border: none;
|
||||||
|
width: auto;
|
||||||
|
height: auto;
|
||||||
|
background-color: transparent;
|
||||||
|
color: inherit;
|
||||||
|
font: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-expand-button]:not([data-expand-all-button]) {
|
||||||
|
&[data-expand-down]::before {
|
||||||
|
content: '\\2191';
|
||||||
|
}
|
||||||
|
|
||||||
|
&[data-expand-up]::before {
|
||||||
|
content: '\\2193';
|
||||||
|
}
|
||||||
|
|
||||||
|
&[data-expand-both]::before {
|
||||||
|
content: '\\2195';
|
||||||
|
}
|
||||||
|
|
||||||
|
svg {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-separator-content] {
|
||||||
|
background: transparent;
|
||||||
|
margin-left: calc(2px + 1ch);
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-expand-all-button] {
|
||||||
|
position: relative;
|
||||||
|
margin-left: 14px;
|
||||||
|
text-transform: lowercase;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-expand-all-button]::before {
|
||||||
|
content: '';
|
||||||
|
display: block;
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
left: -8px;
|
||||||
|
margin-top: -1px;
|
||||||
|
width: 3px;
|
||||||
|
height: 3px;
|
||||||
|
border-radius: 2px;
|
||||||
|
background-color: var(--diffs-fg-number);
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-separator-content]:hover,
|
||||||
|
[data-expand-button]:hover,
|
||||||
|
[data-expand-all-button]:hover {
|
||||||
|
color: var(--diffs-fg);
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-expand-all-button]:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
// Fast cache key - use length + samples instead of full hash
|
// Fast cache key - use length + samples instead of full hash
|
||||||
@@ -267,7 +365,7 @@ const virtualizerCache = new WeakMap<Document | HTMLElement, VirtualizerEntry>()
|
|||||||
const VIRTUAL_METRICS: Partial<VirtualFileMetrics> = {
|
const VIRTUAL_METRICS: Partial<VirtualFileMetrics> = {
|
||||||
lineHeight: 24,
|
lineHeight: 24,
|
||||||
hunkSeparatorHeight: 24,
|
hunkSeparatorHeight: 24,
|
||||||
fileGap: 0,
|
spacing: 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
function resolveVirtualizerTarget(container: HTMLElement): VirtualizerTarget {
|
function resolveVirtualizerTarget(container: HTMLElement): VirtualizerTarget {
|
||||||
@@ -324,7 +422,7 @@ function acquireSharedVirtualizer(container: HTMLElement): SharedVirtualizer | n
|
|||||||
}
|
}
|
||||||
|
|
||||||
const wakeVirtualizer = (
|
const wakeVirtualizer = (
|
||||||
instance: PierreFileDiff<unknown>,
|
instance: PierreFileDiff<PierreAnnotationData>,
|
||||||
sharedVirtualizer: SharedVirtualizer | null,
|
sharedVirtualizer: SharedVirtualizer | null,
|
||||||
forceUpdate: () => void,
|
forceUpdate: () => void,
|
||||||
): (() => void) => {
|
): (() => void) => {
|
||||||
@@ -545,11 +643,11 @@ export const PierreDiffViewer: React.FC<PierreDiffViewerProps> = ({
|
|||||||
|
|
||||||
const diffRootRef = useRef<HTMLDivElement | null>(null);
|
const diffRootRef = useRef<HTMLDivElement | null>(null);
|
||||||
const diffContainerRef = useRef<HTMLDivElement | null>(null);
|
const diffContainerRef = useRef<HTMLDivElement | null>(null);
|
||||||
const diffInstanceRef = useRef<PierreFileDiff<unknown> | null>(null);
|
const diffInstanceRef = useRef<PierreFileDiff<PierreAnnotationData> | null>(null);
|
||||||
const sharedVirtualizerRef = useRef<SharedVirtualizer | null>(null);
|
const sharedVirtualizerRef = useRef<SharedVirtualizer | null>(null);
|
||||||
const instanceVirtualizerRef = useRef<Virtualizer | null>(null);
|
const instanceVirtualizerRef = useRef<Virtualizer | null>(null);
|
||||||
const instanceWorkerPoolRef = useRef<unknown>(null);
|
const instanceWorkerPoolRef = useRef<unknown>(null);
|
||||||
const instanceVirtualHunkSeparatorsRef = useRef<FileDiffOptions<unknown>['hunkSeparators'] | undefined>(undefined);
|
const instanceVirtualHunkSeparatorsRef = useRef<FileDiffOptions<PierreAnnotationData>['hunkSeparators'] | undefined>(undefined);
|
||||||
const instanceFileDiffRef = useRef<FileDiffMetadata | undefined>(undefined);
|
const instanceFileDiffRef = useRef<FileDiffMetadata | undefined>(undefined);
|
||||||
const instanceOldFileRef = useRef<FileContents | undefined>(undefined);
|
const instanceOldFileRef = useRef<FileContents | undefined>(undefined);
|
||||||
const instanceNewFileRef = useRef<FileContents | undefined>(undefined);
|
const instanceNewFileRef = useRef<FileContents | undefined>(undefined);
|
||||||
@@ -755,17 +853,17 @@ export const PierreDiffViewer: React.FC<PierreDiffViewerProps> = ({
|
|||||||
: false;
|
: false;
|
||||||
if (!instance) {
|
if (!instance) {
|
||||||
instance = sharedVirtualizer
|
instance = sharedVirtualizer
|
||||||
? new VirtualizedFileDiff(
|
? new VirtualizedFileDiff<PierreAnnotationData>(
|
||||||
options as unknown as FileDiffOptions<unknown>,
|
options as FileDiffOptions<PierreAnnotationData>,
|
||||||
sharedVirtualizer.virtualizer,
|
sharedVirtualizer.virtualizer,
|
||||||
VIRTUAL_METRICS,
|
VIRTUAL_METRICS,
|
||||||
workerPool,
|
workerPool,
|
||||||
)
|
)
|
||||||
: new PierreFileDiff(options as unknown as FileDiffOptions<unknown>, workerPool);
|
: new PierreFileDiff(options as FileDiffOptions<PierreAnnotationData>, workerPool);
|
||||||
diffInstanceRef.current = instance;
|
diffInstanceRef.current = instance;
|
||||||
lastAppliedSelectionRef.current = null;
|
lastAppliedSelectionRef.current = null;
|
||||||
} else {
|
} else {
|
||||||
instance.setOptions(options as unknown as FileDiffOptions<unknown>);
|
instance.setOptions(options as FileDiffOptions<PierreAnnotationData>);
|
||||||
}
|
}
|
||||||
|
|
||||||
instanceVirtualizerRef.current = virtualizer;
|
instanceVirtualizerRef.current = virtualizer;
|
||||||
|
|||||||
Reference in New Issue
Block a user