@nkzw/codiff-core 1.13.0 → 1.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/app/components/ReviewCodeView.d.ts +3 -1
- package/dist/app/hooks/code-editing-store.d.ts +68 -0
- package/dist/app/hooks/useCodeEditing.d.ts +34 -0
- package/dist/app/hooks/useCodeViewAnnotations.d.ts +3 -0
- package/dist/app/hooks/useCodeViewPlaceholderFile.d.ts +2 -0
- package/dist/config/types.d.ts +2 -0
- package/dist/lib/app-types.d.ts +1 -1
- package/dist/lib/code-view-options.d.ts +1 -2
- package/dist/lib/identifier-navigation.d.ts +1 -0
- package/dist/lib/narrative-walkthrough-diff.d.ts +5 -1
- package/dist/lib/narrative-walkthrough-diff.mjs +4 -2
- package/dist/lib/narrative-walkthrough.d.ts +1 -1
- package/dist/lib/review-comments.d.ts +1 -0
- package/dist/react.mjs +933 -240
- package/dist/style.css +110 -27
- package/dist/types.d.ts +13 -0
- package/package.json +5 -5
package/dist/react.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { filterPatchToHunkIds, getSectionWalkthroughHunks, isGeneratedWalkthroughFile, isSyntheticWalkthroughHunk } from "./lib/narrative-walkthrough-diff.mjs";
|
|
1
|
+
import { filterPatchToHunkIds, getHunkOrdinal, getSectionWalkthroughHunks, isGeneratedWalkthroughFile, isSyntheticWalkthroughHunk } from "./lib/narrative-walkthrough-diff.mjs";
|
|
2
2
|
import { Slot } from "@radix-ui/react-slot";
|
|
3
3
|
import { cva } from "class-variance-authority";
|
|
4
|
-
import { Fragment, Suspense, forwardRef, lazy, useCallback, useEffect, useId, useImperativeHandle, useLayoutEffect, useMemo, useOptimistic, useRef, useState, useTransition } from "react";
|
|
4
|
+
import { Fragment, Suspense, forwardRef, lazy, useCallback, useEffect, useId, useImperativeHandle, useLayoutEffect, useMemo, useOptimistic, useRef, useState, useSyncExternalStore, useTransition } from "react";
|
|
5
5
|
import { createPortal, useFormStatus } from "react-dom";
|
|
6
6
|
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
7
7
|
import { MarkdownEditor } from "@nkzw/mdx-editor";
|
|
@@ -14,7 +14,7 @@ import { ChatCircleIcon } from "@phosphor-icons/react/ChatCircle";
|
|
|
14
14
|
import { PathIcon } from "@phosphor-icons/react/Path";
|
|
15
15
|
import { TreeStructureIcon } from "@phosphor-icons/react/TreeStructure";
|
|
16
16
|
import { FileTree, useFileTree } from "@pierre/trees/react";
|
|
17
|
-
import { hydratePartialDiff, parseDiffFromFile, parsePatchFiles, registerCustomTheme, setCustomExtension } from "@pierre/diffs";
|
|
17
|
+
import { cloneFileDiffMetadata, getFiletypeFromFileName, getHighlighterOptions, hydratePartialDiff, parseDiffFromFile, parsePatchFiles, preloadHighlighter, registerCustomTheme, setCustomExtension } from "@pierre/diffs";
|
|
18
18
|
import useRelativeTime from "@nkzw/use-relative-time";
|
|
19
19
|
import { CaretDownIcon } from "@phosphor-icons/react/CaretDown";
|
|
20
20
|
import "@phosphor-icons/react/CaretUp";
|
|
@@ -26,8 +26,9 @@ import { WarningOctagonIcon } from "@phosphor-icons/react/WarningOctagon";
|
|
|
26
26
|
import { XIcon } from "@phosphor-icons/react/X";
|
|
27
27
|
import { ColumnsIcon } from "@phosphor-icons/react/Columns";
|
|
28
28
|
import { ImageBrokenIcon } from "@phosphor-icons/react/ImageBroken";
|
|
29
|
+
import { PencilSimpleIcon } from "@phosphor-icons/react/PencilSimple";
|
|
29
30
|
import { SquareSplitVerticalIcon } from "@phosphor-icons/react/SquareSplitVertical";
|
|
30
|
-
import { CodeView, WorkerPoolContextProvider } from "@pierre/diffs/react";
|
|
31
|
+
import { CodeView, EditProvider, WorkerPoolContextProvider } from "@pierre/diffs/react";
|
|
31
32
|
import { CrosshairSimpleIcon } from "@phosphor-icons/react/CrosshairSimple";
|
|
32
33
|
import { ProhibitIcon } from "@phosphor-icons/react/Prohibit";
|
|
33
34
|
import { PersistentMarkdownEditor } from "@nkzw/mdx-editor/persistence";
|
|
@@ -1505,7 +1506,7 @@ const parseSectionDiffWithOptions = (file, section, showWhitespace) => {
|
|
|
1505
1506
|
}
|
|
1506
1507
|
else if (section.patch.trim().length === 0) fileDiff = createEmptyFileDiff(file, section);
|
|
1507
1508
|
else {
|
|
1508
|
-
const parsedFileDiff = parsePatchFiles(section.patch)[0]?.files[0];
|
|
1509
|
+
const parsedFileDiff = parsePatchFiles(section.patch, cacheKey)[0]?.files[0];
|
|
1509
1510
|
if (parsedFileDiff) {
|
|
1510
1511
|
const loaded = parsedFileDiff.isPartial ? getLoadedSectionContents(file, section) : void 0;
|
|
1511
1512
|
let hydrated = null;
|
|
@@ -3574,14 +3575,6 @@ registerCustomTheme("Licht", async () => licht_default);
|
|
|
3574
3575
|
registerCustomTheme("Dunkel", async () => dunkel_default);
|
|
3575
3576
|
setCustomExtension("cts", "typescript");
|
|
3576
3577
|
setCustomExtension("mts", "typescript");
|
|
3577
|
-
const statusLabel = {
|
|
3578
|
-
added: "Added",
|
|
3579
|
-
conflicted: "Conflicted",
|
|
3580
|
-
deleted: "Deleted",
|
|
3581
|
-
modified: "Modified",
|
|
3582
|
-
renamed: "Renamed",
|
|
3583
|
-
untracked: "Untracked"
|
|
3584
|
-
};
|
|
3585
3578
|
const sectionLabel = {
|
|
3586
3579
|
commit: "Commit",
|
|
3587
3580
|
"pull-request": "PR",
|
|
@@ -3601,7 +3594,7 @@ const workerHighlighterOptions = {
|
|
|
3601
3594
|
light: "Licht"
|
|
3602
3595
|
},
|
|
3603
3596
|
tokenizeMaxLineLength: 2e4,
|
|
3604
|
-
useTokenTransformer:
|
|
3597
|
+
useTokenTransformer: true
|
|
3605
3598
|
};
|
|
3606
3599
|
const codeViewUnsafeCSS = `
|
|
3607
3600
|
:host {
|
|
@@ -3887,11 +3880,10 @@ const wrapIdentifierNavigationText = (root) => {
|
|
|
3887
3880
|
};
|
|
3888
3881
|
const applyIdentifierNavigationState = (renderedItems, active) => {
|
|
3889
3882
|
for (const { element } of renderedItems) {
|
|
3890
|
-
element.toggleAttribute(definitionModifierAttribute, active);
|
|
3891
3883
|
const root = element.shadowRoot;
|
|
3892
|
-
|
|
3893
|
-
|
|
3894
|
-
if (
|
|
3884
|
+
const enabled = active && !hasActiveTextSelection(root);
|
|
3885
|
+
element.toggleAttribute(definitionModifierAttribute, enabled);
|
|
3886
|
+
if (root && enabled) wrapIdentifierNavigationText(root);
|
|
3895
3887
|
}
|
|
3896
3888
|
};
|
|
3897
3889
|
const getIdentifierAtOffset = (text, offset) => {
|
|
@@ -3935,7 +3927,7 @@ const getItemVersion = (value) => {
|
|
|
3935
3927
|
//#region lib/keyboard.ts
|
|
3936
3928
|
const isNativeInputTarget = (target) => {
|
|
3937
3929
|
const candidate = target;
|
|
3938
|
-
return candidate?.closest?.("input, select, textarea") != null || candidate?.isContentEditable === true;
|
|
3930
|
+
return candidate?.closest?.("input, select, textarea, [contenteditable=\"true\"]") != null || candidate?.isContentEditable === true || candidate?.shadowRoot?.activeElement != null && isNativeInputTarget(candidate.shadowRoot.activeElement);
|
|
3939
3931
|
};
|
|
3940
3932
|
const isMacPlatform = (platform = navigator.platform) => platform.toLowerCase().includes("mac");
|
|
3941
3933
|
const isPrimaryModifier = (event, platform = navigator.platform) => isMacPlatform(platform) ? event.metaKey && !event.ctrlKey : event.ctrlKey && !event.metaKey;
|
|
@@ -4039,6 +4031,7 @@ const highlightTextContainer = (container, normalizedQuery, activeMatch) => {
|
|
|
4039
4031
|
const applySearchHighlights = (renderedItems, query, activeMatch) => {
|
|
4040
4032
|
const normalizedQuery = query.trim().toLowerCase();
|
|
4041
4033
|
for (const { element, id } of renderedItems) for (const root of getSearchableRoots(element)) {
|
|
4034
|
+
if (normalizedQuery) clearIdentifierNavigationWrappers(root);
|
|
4042
4035
|
clearSearchHighlights(root);
|
|
4043
4036
|
if (!normalizedQuery) continue;
|
|
4044
4037
|
const matchForItem = activeMatch && activeMatch.itemId === id ? activeMatch : null;
|
|
@@ -4052,6 +4045,516 @@ const getSourceKey = (source) => source.type === "commit" ? `commit:${source.ref
|
|
|
4052
4045
|
const getShortRef = (ref) => ref.slice(0, 7);
|
|
4053
4046
|
const getSourceLabel = (source) => source.type === "commit" ? getShortRef(source.ref) : source.type === "branch" || source.type === "branch-diff" ? `Branch vs ${source.ref}` : source.type === "branch-working-tree" ? `Local + branch vs ${source.ref}` : source.type === "range" ? rangeLabel(source) : source.type === "pull-request" ? source.number ? `${source.provider === "gitlab" ? "MR" : "PR"} #${source.number}` : source.provider === "gitlab" ? "Merge request" : "Pull request" : "Uncommitted";
|
|
4054
4047
|
//#endregion
|
|
4048
|
+
//#region config/defaults.ts
|
|
4049
|
+
const defaultConfigTemplate = {
|
|
4050
|
+
settings: {
|
|
4051
|
+
"agentBackend": "codex",
|
|
4052
|
+
"checkForUpdates": true,
|
|
4053
|
+
"claudeModel": "claude-sonnet-4-6",
|
|
4054
|
+
"codeFontFamily": "",
|
|
4055
|
+
"codeFontSize": 13,
|
|
4056
|
+
"copyCommentsOnClose": false,
|
|
4057
|
+
"diffStyle": "split",
|
|
4058
|
+
"editorCommand": "",
|
|
4059
|
+
"lastRepositoryPath": "",
|
|
4060
|
+
"openAIModel": "gpt-5.6-terra",
|
|
4061
|
+
"opencodeModel": "opencode-default",
|
|
4062
|
+
"piModel": "pi-default",
|
|
4063
|
+
"reviewCommentsPrefix": "# Address these Review Comments",
|
|
4064
|
+
"sidebarPosition": "left",
|
|
4065
|
+
"showOutdated": false,
|
|
4066
|
+
"showWhitespace": false,
|
|
4067
|
+
"theme": "system",
|
|
4068
|
+
"walkthroughPrompt": "",
|
|
4069
|
+
"wordWrap": false
|
|
4070
|
+
},
|
|
4071
|
+
keymap: {
|
|
4072
|
+
"askAgent": "Mod+Alt+Enter",
|
|
4073
|
+
"closeSearch": "Escape",
|
|
4074
|
+
"commandBar": "Mod+k",
|
|
4075
|
+
"diffSearch": "Mod+f",
|
|
4076
|
+
"discardComment": "Escape",
|
|
4077
|
+
"doneEditing": "Mod+s",
|
|
4078
|
+
"editFile": "Mod+e",
|
|
4079
|
+
"fileFilter": "Mod+p",
|
|
4080
|
+
"nextHunk": ["Ctrl+ArrowDown", "j"],
|
|
4081
|
+
"nextSearchMatch": "Enter",
|
|
4082
|
+
"openFile": "Mod+Shift+o",
|
|
4083
|
+
"prevHunk": ["Ctrl+ArrowUp", "k"],
|
|
4084
|
+
"prevSearchMatch": "Shift+Enter",
|
|
4085
|
+
"shortcutsHelp": "Shift+?",
|
|
4086
|
+
"submitComment": "Mod+Enter",
|
|
4087
|
+
"toggleSidebar": "Mod+Shift+b",
|
|
4088
|
+
"toggleWordWrap": "Alt+z"
|
|
4089
|
+
}
|
|
4090
|
+
};
|
|
4091
|
+
const createDefaultConfig = () => ({
|
|
4092
|
+
keymap: { ...defaultConfigTemplate.keymap },
|
|
4093
|
+
settings: { ...defaultConfigTemplate.settings }
|
|
4094
|
+
});
|
|
4095
|
+
const defaultKeymap = Object.freeze({ ...defaultConfigTemplate.keymap });
|
|
4096
|
+
Object.freeze({ ...defaultConfigTemplate.settings });
|
|
4097
|
+
const createFileEditingStore = (onChange) => {
|
|
4098
|
+
const sessionRef = { current: null };
|
|
4099
|
+
const draftRef = { current: "" };
|
|
4100
|
+
let timer;
|
|
4101
|
+
let pendingWrite = null;
|
|
4102
|
+
const clearTimer = () => {
|
|
4103
|
+
clearTimeout(timer);
|
|
4104
|
+
timer = void 0;
|
|
4105
|
+
};
|
|
4106
|
+
const setSession = (session) => {
|
|
4107
|
+
sessionRef.current = session ? {
|
|
4108
|
+
...session,
|
|
4109
|
+
dirty: draftRef.current !== session.document.content,
|
|
4110
|
+
hasChanges: session.finishing === "revert" ? session.hasChanges : draftRef.current !== session.originalContent
|
|
4111
|
+
} : null;
|
|
4112
|
+
if (!session) clearTimer();
|
|
4113
|
+
onChange();
|
|
4114
|
+
};
|
|
4115
|
+
const scheduleSave = () => {
|
|
4116
|
+
clearTimer();
|
|
4117
|
+
timer = setTimeout(() => void flush(), 300);
|
|
4118
|
+
};
|
|
4119
|
+
const flush = () => {
|
|
4120
|
+
clearTimer();
|
|
4121
|
+
if (pendingWrite) return pendingWrite.then((saved) => saved ? flush() : false);
|
|
4122
|
+
const current = sessionRef.current;
|
|
4123
|
+
if (!current || draftRef.current === current.document.content) return Promise.resolve(true);
|
|
4124
|
+
const content = draftRef.current;
|
|
4125
|
+
setSession({
|
|
4126
|
+
...current,
|
|
4127
|
+
saveError: void 0,
|
|
4128
|
+
saving: true
|
|
4129
|
+
});
|
|
4130
|
+
pendingWrite = Promise.resolve().then(() => window.codiff.saveRepositoryFile({
|
|
4131
|
+
...current.document,
|
|
4132
|
+
baseVersion: current.document.version,
|
|
4133
|
+
content
|
|
4134
|
+
})).then((result) => {
|
|
4135
|
+
if (result.status === "conflict") throw new Error("The file changed on disk. Your edits are kept; copy them before refreshing.");
|
|
4136
|
+
const latest = sessionRef.current;
|
|
4137
|
+
if (latest) setSession({
|
|
4138
|
+
...latest,
|
|
4139
|
+
document: result.document,
|
|
4140
|
+
saving: false
|
|
4141
|
+
});
|
|
4142
|
+
return true;
|
|
4143
|
+
}).catch((error) => {
|
|
4144
|
+
const latest = sessionRef.current;
|
|
4145
|
+
if (latest) setSession({
|
|
4146
|
+
...latest,
|
|
4147
|
+
saveError: error instanceof Error ? error.message : String(error),
|
|
4148
|
+
saving: false
|
|
4149
|
+
});
|
|
4150
|
+
return false;
|
|
4151
|
+
}).finally(() => {
|
|
4152
|
+
pendingWrite = null;
|
|
4153
|
+
const latest = sessionRef.current;
|
|
4154
|
+
if (latest && !latest.finishing && !latest.saveError && draftRef.current !== latest.document.content) scheduleSave();
|
|
4155
|
+
});
|
|
4156
|
+
return pendingWrite;
|
|
4157
|
+
};
|
|
4158
|
+
const finish = async (revert, beforeClose) => {
|
|
4159
|
+
const current = sessionRef.current;
|
|
4160
|
+
if (!current || current.finishing) return false;
|
|
4161
|
+
clearTimer();
|
|
4162
|
+
setSession({
|
|
4163
|
+
...current,
|
|
4164
|
+
finishing: revert ? "revert" : "done"
|
|
4165
|
+
});
|
|
4166
|
+
let previousDraft;
|
|
4167
|
+
try {
|
|
4168
|
+
if (pendingWrite && !await pendingWrite) return false;
|
|
4169
|
+
if (revert) {
|
|
4170
|
+
previousDraft = draftRef.current;
|
|
4171
|
+
draftRef.current = current.originalContent;
|
|
4172
|
+
}
|
|
4173
|
+
do {
|
|
4174
|
+
do
|
|
4175
|
+
if (!await flush()) {
|
|
4176
|
+
if (previousDraft !== void 0) draftRef.current = previousDraft;
|
|
4177
|
+
return false;
|
|
4178
|
+
}
|
|
4179
|
+
while (!revert && draftRef.current !== sessionRef.current?.document.content);
|
|
4180
|
+
await beforeClose?.();
|
|
4181
|
+
} while (!revert && draftRef.current !== sessionRef.current?.document.content);
|
|
4182
|
+
setSession(null);
|
|
4183
|
+
return true;
|
|
4184
|
+
} catch (error) {
|
|
4185
|
+
if (previousDraft !== void 0) draftRef.current = previousDraft;
|
|
4186
|
+
throw error;
|
|
4187
|
+
} finally {
|
|
4188
|
+
const latest = sessionRef.current;
|
|
4189
|
+
if (latest) setSession({
|
|
4190
|
+
...latest,
|
|
4191
|
+
finishing: void 0
|
|
4192
|
+
});
|
|
4193
|
+
}
|
|
4194
|
+
};
|
|
4195
|
+
return {
|
|
4196
|
+
draftRef,
|
|
4197
|
+
finish,
|
|
4198
|
+
flush,
|
|
4199
|
+
getSnapshot: () => sessionRef.current,
|
|
4200
|
+
setDraft: (content) => {
|
|
4201
|
+
const current = sessionRef.current;
|
|
4202
|
+
if (!current || current.finishing === "revert" || content === draftRef.current) return;
|
|
4203
|
+
const wasDirty = draftRef.current !== current.document.content;
|
|
4204
|
+
draftRef.current = content;
|
|
4205
|
+
const isDirty = content !== current.document.content;
|
|
4206
|
+
if (isDirty && !current.finishing && !current.saveError) scheduleSave();
|
|
4207
|
+
else clearTimer();
|
|
4208
|
+
if (wasDirty !== isDirty || current.hasChanges !== (content !== current.originalContent)) setSession({ ...current });
|
|
4209
|
+
},
|
|
4210
|
+
setSession
|
|
4211
|
+
};
|
|
4212
|
+
};
|
|
4213
|
+
const getCodeEditKey = (sourceKey, itemId) => JSON.stringify([sourceKey, itemId]);
|
|
4214
|
+
const createCodeEditingStore = () => {
|
|
4215
|
+
const entries = /* @__PURE__ */ new Map();
|
|
4216
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
4217
|
+
let snapshot = /* @__PURE__ */ new Map();
|
|
4218
|
+
const hasFile = (path) => [...snapshot.values()].some((session) => session.document.path === path);
|
|
4219
|
+
return {
|
|
4220
|
+
clear: () => {
|
|
4221
|
+
for (const entry of entries.values()) entry.setSession(null);
|
|
4222
|
+
},
|
|
4223
|
+
flush: (sourceKey) => Promise.all([...entries.values()].filter((entry) => entry.getSnapshot()?.sourceKey === sourceKey).map((entry) => entry.flush())),
|
|
4224
|
+
get: (sourceKey, itemId) => entries.get(getCodeEditKey(sourceKey, itemId)),
|
|
4225
|
+
getForItem: (item) => item.type === "diff" ? [...entries.values()].find((entry) => {
|
|
4226
|
+
const session = entry.getSnapshot();
|
|
4227
|
+
return session?.item.id === item.id && session.item.fileDiff === item.fileDiff;
|
|
4228
|
+
}) : void 0,
|
|
4229
|
+
getSnapshot: () => snapshot,
|
|
4230
|
+
hasFile,
|
|
4231
|
+
hasUnsavedEdits: () => [...entries.values()].some((entry) => {
|
|
4232
|
+
const session = entry.getSnapshot();
|
|
4233
|
+
return session && (session.saving || entry.draftRef.current !== session.document.content);
|
|
4234
|
+
}),
|
|
4235
|
+
start: (session) => {
|
|
4236
|
+
if (hasFile(session.document.path)) return null;
|
|
4237
|
+
const key = getCodeEditKey(session.sourceKey, session.item.id);
|
|
4238
|
+
const entry = createFileEditingStore(() => {
|
|
4239
|
+
const next = new Map(snapshot);
|
|
4240
|
+
const current = entry.getSnapshot();
|
|
4241
|
+
if (current) next.set(key, current);
|
|
4242
|
+
else {
|
|
4243
|
+
next.delete(key);
|
|
4244
|
+
entries.delete(key);
|
|
4245
|
+
}
|
|
4246
|
+
snapshot = next;
|
|
4247
|
+
for (const listener of listeners) listener();
|
|
4248
|
+
});
|
|
4249
|
+
entries.set(key, entry);
|
|
4250
|
+
entry.draftRef.current = session.document.content;
|
|
4251
|
+
entry.setSession(session);
|
|
4252
|
+
return entry;
|
|
4253
|
+
},
|
|
4254
|
+
subscribe: (listener) => {
|
|
4255
|
+
listeners.add(listener);
|
|
4256
|
+
return () => {
|
|
4257
|
+
listeners.delete(listener);
|
|
4258
|
+
};
|
|
4259
|
+
}
|
|
4260
|
+
};
|
|
4261
|
+
};
|
|
4262
|
+
//#endregion
|
|
4263
|
+
//#region app/hooks/useCodeEditing.ts
|
|
4264
|
+
let editorModule = null;
|
|
4265
|
+
let editorModulePromise = null;
|
|
4266
|
+
const loadEditor = () => editorModulePromise ??= import("@pierre/diffs/edit").then((module) => {
|
|
4267
|
+
editorModule = module;
|
|
4268
|
+
return module;
|
|
4269
|
+
}).catch((error) => {
|
|
4270
|
+
editorModulePromise = null;
|
|
4271
|
+
throw error;
|
|
4272
|
+
});
|
|
4273
|
+
const prepareEditor = (fileDiff) => {
|
|
4274
|
+
const lang = fileDiff.lang ?? getFiletypeFromFileName(fileDiff.name);
|
|
4275
|
+
return Promise.all([loadEditor(), preloadHighlighter(getHighlighterOptions(lang, workerHighlighterOptions))]);
|
|
4276
|
+
};
|
|
4277
|
+
const createCodeEditor = (type, options, key) => {
|
|
4278
|
+
if (!editorModule) throw new Error("The code editor has not loaded.");
|
|
4279
|
+
return new editorModule.Editor(type, options, key);
|
|
4280
|
+
};
|
|
4281
|
+
function useUnsavedCodeEditsGuard(store) {
|
|
4282
|
+
useEffect(() => {
|
|
4283
|
+
const beforeUnload = (event) => {
|
|
4284
|
+
if (store.hasUnsavedEdits()) {
|
|
4285
|
+
event.preventDefault();
|
|
4286
|
+
event.returnValue = "";
|
|
4287
|
+
}
|
|
4288
|
+
};
|
|
4289
|
+
window.addEventListener("beforeunload", beforeUnload);
|
|
4290
|
+
return () => window.removeEventListener("beforeunload", beforeUnload);
|
|
4291
|
+
}, [store]);
|
|
4292
|
+
}
|
|
4293
|
+
const errorMessage = (error) => error instanceof Error ? error.message : String(error);
|
|
4294
|
+
const getFirstVisibleChangedLine = (root, viewport) => {
|
|
4295
|
+
const viewportRect = viewport.getBoundingClientRect();
|
|
4296
|
+
const header = root.querySelector("[data-diffs-header][data-sticky]");
|
|
4297
|
+
const top = Math.max(viewportRect.top, header?.getBoundingClientRect().bottom ?? viewportRect.top) + 11;
|
|
4298
|
+
for (const row of root.querySelectorAll("[data-content] > [data-line-type=\"change-addition\"]")) {
|
|
4299
|
+
const rect = row.getBoundingClientRect();
|
|
4300
|
+
if (rect.height > 0 && rect.top >= top && rect.top < viewportRect.bottom) {
|
|
4301
|
+
const line = Number(row.dataset.line);
|
|
4302
|
+
if (Number.isInteger(line) && line > 0) return line;
|
|
4303
|
+
}
|
|
4304
|
+
}
|
|
4305
|
+
};
|
|
4306
|
+
function useCodeEditing({ codeViewRef, items, keymap = defaultKeymap, onLoadSectionContents, onRefresh, selectedItemId, sourceKey, store: sharedStore }) {
|
|
4307
|
+
const [localStore] = useState(createCodeEditingStore);
|
|
4308
|
+
const store = sharedStore ?? localStore;
|
|
4309
|
+
const sessions = useSyncExternalStore(store.subscribe, store.getSnapshot, store.getSnapshot);
|
|
4310
|
+
useUnsavedCodeEditsGuard(store);
|
|
4311
|
+
const busyRef = useRef(/* @__PURE__ */ new Set());
|
|
4312
|
+
const [busyItemKeys, setBusyItemKeys] = useState(() => /* @__PURE__ */ new Set());
|
|
4313
|
+
const [errors, setErrors] = useState(() => /* @__PURE__ */ new Map());
|
|
4314
|
+
const setBusy = useCallback((key, busy) => {
|
|
4315
|
+
if (busy) busyRef.current.add(key);
|
|
4316
|
+
else busyRef.current.delete(key);
|
|
4317
|
+
setBusyItemKeys(new Set(busyRef.current));
|
|
4318
|
+
}, []);
|
|
4319
|
+
const setError = useCallback((key, message) => {
|
|
4320
|
+
setErrors((current) => {
|
|
4321
|
+
const next = new Map(current);
|
|
4322
|
+
if (message) next.set(key, message);
|
|
4323
|
+
else next.delete(key);
|
|
4324
|
+
return next;
|
|
4325
|
+
});
|
|
4326
|
+
}, []);
|
|
4327
|
+
const currentSessions = useMemo(() => new Map([...sessions.values()].filter((session) => session.sourceKey === sourceKey).map((session) => [session.item.id, session])), [sessions, sourceKey]);
|
|
4328
|
+
const editorOptions = useMemo(() => {
|
|
4329
|
+
const focusedEditors = /* @__PURE__ */ new WeakSet();
|
|
4330
|
+
return { onAttach: (editor, fileInstance) => {
|
|
4331
|
+
if (!focusedEditors.has(editor)) {
|
|
4332
|
+
focusedEditors.add(editor);
|
|
4333
|
+
const viewer = codeViewRef.current?.getInstance();
|
|
4334
|
+
const root = viewer?.getRenderedItems().find(({ instance }) => instance === fileInstance)?.element.shadowRoot;
|
|
4335
|
+
const viewport = viewer?.getContainerElement();
|
|
4336
|
+
editor.focus({
|
|
4337
|
+
character: 0,
|
|
4338
|
+
lineNumber: (root && viewport ? getFirstVisibleChangedLine(root, viewport) : void 0) ?? "first-visible",
|
|
4339
|
+
offset: 11,
|
|
4340
|
+
preventScroll: true
|
|
4341
|
+
});
|
|
4342
|
+
const position = editor.getViewState().selections?.[0]?.start;
|
|
4343
|
+
const indentation = (position && editor.getEditState()?.document.getLineText(position.line))?.match(/^\s*/)?.[0].length ?? 0;
|
|
4344
|
+
if (position && indentation > 0) editor.focus({
|
|
4345
|
+
character: indentation,
|
|
4346
|
+
lineNumber: position.line + 1,
|
|
4347
|
+
preventScroll: true
|
|
4348
|
+
});
|
|
4349
|
+
}
|
|
4350
|
+
} };
|
|
4351
|
+
}, [codeViewRef]);
|
|
4352
|
+
const loadEditContents = useCallback((item, metadata) => {
|
|
4353
|
+
if (!item.fileDiff.isPartial) return Promise.resolve({
|
|
4354
|
+
newFile: {
|
|
4355
|
+
contents: item.fileDiff.additionLines.join(""),
|
|
4356
|
+
name: item.fileDiff.name
|
|
4357
|
+
},
|
|
4358
|
+
oldFile: null
|
|
4359
|
+
});
|
|
4360
|
+
return loadSectionContents(metadata.file, metadata.section, onLoadSectionContents);
|
|
4361
|
+
}, [onLoadSectionContents]);
|
|
4362
|
+
const prepareEdit = useCallback(async (item, metadata) => {
|
|
4363
|
+
if (item.type === "diff" && onLoadSectionContents) {
|
|
4364
|
+
const [, loaded] = await Promise.all([prepareEditor(item.fileDiff), loadEditContents(item, metadata)]);
|
|
4365
|
+
const rendered = codeViewRef.current?.getInstance()?.getRenderedItems().find(({ id }) => id === item.id);
|
|
4366
|
+
if (rendered?.type === "diff") {
|
|
4367
|
+
const fileDiff = item.fileDiff.isPartial ? hydratePartialDiff("clone", item.fileDiff, loaded) : item.fileDiff;
|
|
4368
|
+
await rendered.instance.primeHighlightCache(fileDiff);
|
|
4369
|
+
}
|
|
4370
|
+
}
|
|
4371
|
+
}, [
|
|
4372
|
+
codeViewRef,
|
|
4373
|
+
loadEditContents,
|
|
4374
|
+
onLoadSectionContents
|
|
4375
|
+
]);
|
|
4376
|
+
const startEdit = useCallback(async (item, metadata) => {
|
|
4377
|
+
const itemKey = getCodeEditKey(sourceKey, item.id);
|
|
4378
|
+
if (item.type !== "diff" || !onLoadSectionContents || store.hasFile(metadata.file.path) || busyRef.current.has(itemKey)) return;
|
|
4379
|
+
setBusy(itemKey, true);
|
|
4380
|
+
setError(itemKey);
|
|
4381
|
+
try {
|
|
4382
|
+
const [, loaded, document] = await Promise.all([
|
|
4383
|
+
prepareEditor(item.fileDiff),
|
|
4384
|
+
loadEditContents(item, metadata),
|
|
4385
|
+
window.codiff.getRepositoryFile(metadata.file.path)
|
|
4386
|
+
]);
|
|
4387
|
+
if (!loaded.newFile || loaded.newFile.contents !== document.content) throw new Error("The file changed on disk. Refresh the diff before editing.");
|
|
4388
|
+
const key = crypto.randomUUID();
|
|
4389
|
+
const fileDiff = item.fileDiff.isPartial ? hydratePartialDiff("clone", item.fileDiff, loaded) : cloneFileDiffMetadata(item.fileDiff);
|
|
4390
|
+
fileDiff.cacheKey ??= `code-edit:${key}`;
|
|
4391
|
+
const rendered = codeViewRef.current?.getInstance()?.getRenderedItems().find(({ id }) => id === item.id);
|
|
4392
|
+
if (rendered?.type === "diff") await rendered.instance.primeHighlightCache(fileDiff);
|
|
4393
|
+
const nextSession = {
|
|
4394
|
+
dirty: false,
|
|
4395
|
+
document,
|
|
4396
|
+
hasChanges: false,
|
|
4397
|
+
item: {
|
|
4398
|
+
...item,
|
|
4399
|
+
collapsed: false,
|
|
4400
|
+
edit: true,
|
|
4401
|
+
fileDiff,
|
|
4402
|
+
version: getItemVersion(`code-edit:${key}`)
|
|
4403
|
+
},
|
|
4404
|
+
metadata,
|
|
4405
|
+
originalContent: document.content,
|
|
4406
|
+
sourceKey
|
|
4407
|
+
};
|
|
4408
|
+
if (store.start(nextSession)) codeViewRef.current?.clearSelectedLines();
|
|
4409
|
+
} catch (error) {
|
|
4410
|
+
setError(itemKey, errorMessage(error));
|
|
4411
|
+
} finally {
|
|
4412
|
+
setBusy(itemKey, false);
|
|
4413
|
+
}
|
|
4414
|
+
}, [
|
|
4415
|
+
codeViewRef,
|
|
4416
|
+
loadEditContents,
|
|
4417
|
+
onLoadSectionContents,
|
|
4418
|
+
setBusy,
|
|
4419
|
+
setError,
|
|
4420
|
+
sourceKey,
|
|
4421
|
+
store
|
|
4422
|
+
]);
|
|
4423
|
+
const finishEdit = useCallback(async (itemId, revert) => {
|
|
4424
|
+
const itemKey = getCodeEditKey(sourceKey, itemId);
|
|
4425
|
+
const entry = store.get(sourceKey, itemId);
|
|
4426
|
+
const current = entry?.getSnapshot();
|
|
4427
|
+
if (!entry || !current || busyRef.current.has(itemKey)) return;
|
|
4428
|
+
setBusy(itemKey, true);
|
|
4429
|
+
setError(itemKey);
|
|
4430
|
+
const needsRefresh = current.hasChanges || current.document.content !== current.originalContent || current.saving;
|
|
4431
|
+
try {
|
|
4432
|
+
await entry.finish(revert, async () => {
|
|
4433
|
+
const latest = entry.getSnapshot();
|
|
4434
|
+
if ((needsRefresh || latest?.hasChanges) && onRefresh && !await onRefresh(current.metadata.file, current.metadata.section)) throw new Error("File saved. Refresh the review to see the updated diff.");
|
|
4435
|
+
});
|
|
4436
|
+
} catch (error) {
|
|
4437
|
+
setError(itemKey, errorMessage(error));
|
|
4438
|
+
} finally {
|
|
4439
|
+
setBusy(itemKey, false);
|
|
4440
|
+
}
|
|
4441
|
+
}, [
|
|
4442
|
+
onRefresh,
|
|
4443
|
+
setBusy,
|
|
4444
|
+
setError,
|
|
4445
|
+
sourceKey,
|
|
4446
|
+
store
|
|
4447
|
+
]);
|
|
4448
|
+
const doneEdit = useCallback((itemId) => finishEdit(itemId, false), [finishEdit]);
|
|
4449
|
+
const revertEdit = useCallback((itemId) => finishEdit(itemId, true), [finishEdit]);
|
|
4450
|
+
const onItemEditChange = useCallback((event, item) => {
|
|
4451
|
+
store.getForItem(item)?.setDraft(event.file.contents);
|
|
4452
|
+
}, [store]);
|
|
4453
|
+
const onItemEditComplete = useCallback((_event, item, nextItem) => {
|
|
4454
|
+
const entry = store.getForItem(item);
|
|
4455
|
+
const current = entry?.getSnapshot();
|
|
4456
|
+
if (!entry || !current || nextItem.type !== "diff") return "reject";
|
|
4457
|
+
nextItem.fileDiff.cacheKey = `code-edit:${crypto.randomUUID()}`;
|
|
4458
|
+
entry.setSession({
|
|
4459
|
+
...current,
|
|
4460
|
+
item: {
|
|
4461
|
+
...nextItem,
|
|
4462
|
+
edit: true
|
|
4463
|
+
}
|
|
4464
|
+
});
|
|
4465
|
+
return "accept";
|
|
4466
|
+
}, [store]);
|
|
4467
|
+
const editedItems = useMemo(() => {
|
|
4468
|
+
if (currentSessions.size === 0) return items;
|
|
4469
|
+
const found = /* @__PURE__ */ new Set();
|
|
4470
|
+
const next = items.map((item) => {
|
|
4471
|
+
const session = currentSessions.get(item.id);
|
|
4472
|
+
if (!session) return item;
|
|
4473
|
+
found.add(item.id);
|
|
4474
|
+
return {
|
|
4475
|
+
...session.item,
|
|
4476
|
+
collapsed: item.collapsed
|
|
4477
|
+
};
|
|
4478
|
+
});
|
|
4479
|
+
for (const session of currentSessions.values()) if (!found.has(session.item.id)) next.push(session.item);
|
|
4480
|
+
return next;
|
|
4481
|
+
}, [currentSessions, items]);
|
|
4482
|
+
useEffect(() => {
|
|
4483
|
+
if (currentSessions.size === 0) return;
|
|
4484
|
+
const keyDown = (event) => {
|
|
4485
|
+
if (event.defaultPrevented || event.repeat || event.isComposing || !matchesShortcut(event, keymap, "doneEditing")) return;
|
|
4486
|
+
const path = event.composedPath();
|
|
4487
|
+
if (isNativeInputTarget(event.target) && !path.some((node) => node.matches?.("[data-content][contenteditable=\"true\"]"))) return;
|
|
4488
|
+
const itemId = codeViewRef.current?.getInstance()?.getRenderedItems().find(({ element, id }) => currentSessions.has(id) && path.includes(element))?.id ?? selectedItemId ?? (currentSessions.size === 1 ? currentSessions.keys().next().value : void 0);
|
|
4489
|
+
if (itemId == null || !currentSessions.has(itemId)) return;
|
|
4490
|
+
event.preventDefault();
|
|
4491
|
+
event.stopPropagation();
|
|
4492
|
+
doneEdit(itemId);
|
|
4493
|
+
};
|
|
4494
|
+
window.addEventListener("keydown", keyDown, true);
|
|
4495
|
+
return () => window.removeEventListener("keydown", keyDown, true);
|
|
4496
|
+
}, [
|
|
4497
|
+
codeViewRef,
|
|
4498
|
+
currentSessions,
|
|
4499
|
+
doneEdit,
|
|
4500
|
+
keymap,
|
|
4501
|
+
selectedItemId
|
|
4502
|
+
]);
|
|
4503
|
+
return {
|
|
4504
|
+
canStartEdit: (itemId, path) => !busyItemKeys.has(getCodeEditKey(sourceKey, itemId)) && ![...sessions.values()].some((session) => session.document.path === path),
|
|
4505
|
+
doneEdit,
|
|
4506
|
+
editorOptions,
|
|
4507
|
+
getError: (itemId) => currentSessions.get(itemId)?.saveError ?? errors.get(getCodeEditKey(sourceKey, itemId)),
|
|
4508
|
+
isBusy: (itemId) => busyItemKeys.has(getCodeEditKey(sourceKey, itemId)) || currentSessions.get(itemId)?.finishing != null,
|
|
4509
|
+
items: editedItems,
|
|
4510
|
+
onItemEditChange,
|
|
4511
|
+
onItemEditComplete,
|
|
4512
|
+
prepareEdit,
|
|
4513
|
+
revertEdit,
|
|
4514
|
+
sessions: currentSessions,
|
|
4515
|
+
startEdit
|
|
4516
|
+
};
|
|
4517
|
+
}
|
|
4518
|
+
//#endregion
|
|
4519
|
+
//#region app/hooks/useCodeViewAnnotations.ts
|
|
4520
|
+
function useCodeViewAnnotations() {
|
|
4521
|
+
const [getAnnotations] = useState(() => {
|
|
4522
|
+
const cache = /* @__PURE__ */ new Map();
|
|
4523
|
+
return (id, key, annotations) => {
|
|
4524
|
+
const previous = cache.get(id);
|
|
4525
|
+
if (previous?.key === key) return previous.annotations;
|
|
4526
|
+
cache.set(id, {
|
|
4527
|
+
annotations,
|
|
4528
|
+
key
|
|
4529
|
+
});
|
|
4530
|
+
return annotations;
|
|
4531
|
+
};
|
|
4532
|
+
});
|
|
4533
|
+
return getAnnotations;
|
|
4534
|
+
}
|
|
4535
|
+
//#endregion
|
|
4536
|
+
//#region app/hooks/useCodeViewPlaceholderFile.ts
|
|
4537
|
+
function useCodeViewPlaceholderFile() {
|
|
4538
|
+
const [getPlaceholderFile] = useState(() => {
|
|
4539
|
+
const files = /* @__PURE__ */ new Map();
|
|
4540
|
+
return (name, contents = " ") => {
|
|
4541
|
+
const cacheKey = `placeholder:${contents.length}:${name}`;
|
|
4542
|
+
let file = files.get(cacheKey);
|
|
4543
|
+
if (!file) {
|
|
4544
|
+
file = {
|
|
4545
|
+
cacheKey,
|
|
4546
|
+
contents,
|
|
4547
|
+
lang: "text",
|
|
4548
|
+
name
|
|
4549
|
+
};
|
|
4550
|
+
files.set(cacheKey, file);
|
|
4551
|
+
}
|
|
4552
|
+
return file;
|
|
4553
|
+
};
|
|
4554
|
+
});
|
|
4555
|
+
return getPlaceholderFile;
|
|
4556
|
+
}
|
|
4557
|
+
//#endregion
|
|
4055
4558
|
//#region app/components/DefinitionPopover.tsx
|
|
4056
4559
|
function DefinitionPopover({ anchor, getDestination, identifier, onClose, onOpen, result }) {
|
|
4057
4560
|
const popoverRef = useRef(null);
|
|
@@ -4445,14 +4948,17 @@ const resolveWalkthroughHunkFile = (hunk, files) => {
|
|
|
4445
4948
|
};
|
|
4446
4949
|
};
|
|
4447
4950
|
const walkthroughHunkRunKey = (item, hunks) => `${item.id}:${hunks.map((hunk) => hunk.id).join(",")}`;
|
|
4448
|
-
/** Resolve
|
|
4951
|
+
/** Resolve authored hunk order, coalescing only forward runs within each file section. */
|
|
4449
4952
|
const resolveWalkthroughHunkRuns = (item, files) => {
|
|
4450
4953
|
const runs = [];
|
|
4451
4954
|
for (const hunk of item.hunks) {
|
|
4452
4955
|
const resolved = resolveWalkthroughHunkFile(hunk, files);
|
|
4453
4956
|
if (!resolved) continue;
|
|
4454
4957
|
const previous = runs.at(-1);
|
|
4455
|
-
|
|
4958
|
+
const previousHunk = previous?.hunks.at(-1);
|
|
4959
|
+
const previousOrdinal = previousHunk ? getHunkOrdinal(resolved.section.id, previousHunk.id) : null;
|
|
4960
|
+
const ordinal = getHunkOrdinal(resolved.section.id, hunk.id);
|
|
4961
|
+
if (previous && previous.resolved.file.path === resolved.file.path && previous.resolved.section.id === resolved.section.id && previousOrdinal != null && ordinal != null && previousOrdinal < ordinal) {
|
|
4456
4962
|
const hunks = [...previous.hunks, hunk];
|
|
4457
4963
|
runs[runs.length - 1] = {
|
|
4458
4964
|
...previous,
|
|
@@ -5056,124 +5562,165 @@ function CopyFilePathButton({ path }) {
|
|
|
5056
5562
|
})
|
|
5057
5563
|
});
|
|
5058
5564
|
}
|
|
5059
|
-
function
|
|
5565
|
+
function CodeEditButton({ disabled, isBusy, item, meta, onEdit, onPrepare }) {
|
|
5566
|
+
useEffect(() => {
|
|
5567
|
+
onPrepare(item, meta).catch(() => {});
|
|
5568
|
+
}, [
|
|
5569
|
+
item,
|
|
5570
|
+
meta,
|
|
5571
|
+
onPrepare
|
|
5572
|
+
]);
|
|
5573
|
+
return /* @__PURE__ */ jsxs(Button, {
|
|
5574
|
+
"aria-label": `Edit ${meta.file.path}`,
|
|
5575
|
+
disabled: disabled || isBusy,
|
|
5576
|
+
onClick: onEdit,
|
|
5577
|
+
title: "Edit working-tree file",
|
|
5578
|
+
type: "button",
|
|
5579
|
+
children: [/* @__PURE__ */ jsx(PencilSimpleIcon, {
|
|
5580
|
+
"aria-hidden": true,
|
|
5581
|
+
size: 14,
|
|
5582
|
+
weight: "bold"
|
|
5583
|
+
}), "Edit"]
|
|
5584
|
+
});
|
|
5585
|
+
}
|
|
5586
|
+
function CodeViewHeader({ allowViewedToggle, canCreateFileComment, editActions, isEditing = false, isSectionLoading, meta, onCreateFileComment, onLoadSection, onOpenFile, onToggleCollapsed, onToggleMarkdownPreview, onToggleViewed, readOnly }) {
|
|
5060
5587
|
const { canRenderMarkdown, file, isCollapsed, isMarkdownPreview, isSelected, isViewed, lineCount, reviewIdentity, section, sectionCount, walkthroughNote } = meta;
|
|
5061
5588
|
const canOpenFile = file.status !== "deleted";
|
|
5062
5589
|
const canLoadSection = shouldLoadDiffSectionContents(section);
|
|
5590
|
+
const directoryEnd = file.path.lastIndexOf("/") + 1;
|
|
5063
5591
|
return /* @__PURE__ */ jsxs("div", {
|
|
5064
5592
|
className: `codiff-file-header${walkthroughNote ? " with-note" : ""}${isCollapsed ? " collapsed" : ""}${isSelected ? " selected" : ""}${isViewed ? " viewed" : ""}`,
|
|
5065
|
-
children: [
|
|
5066
|
-
|
|
5067
|
-
|
|
5068
|
-
|
|
5069
|
-
|
|
5070
|
-
|
|
5071
|
-
|
|
5072
|
-
|
|
5073
|
-
|
|
5074
|
-
|
|
5075
|
-
|
|
5076
|
-
|
|
5077
|
-
|
|
5078
|
-
|
|
5079
|
-
|
|
5593
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
5594
|
+
"aria-expanded": !isCollapsed,
|
|
5595
|
+
"aria-label": isCollapsed ? "Expand file" : "Collapse file",
|
|
5596
|
+
className: "codiff-header-toggle",
|
|
5597
|
+
onClick: () => onToggleCollapsed(file, isCollapsed, reviewIdentity.key),
|
|
5598
|
+
onKeyDown: (event) => {
|
|
5599
|
+
if (event.key === "Enter" || event.key === " ") {
|
|
5600
|
+
event.preventDefault();
|
|
5601
|
+
onToggleCollapsed(file, isCollapsed, reviewIdentity.key);
|
|
5602
|
+
}
|
|
5603
|
+
},
|
|
5604
|
+
role: "button",
|
|
5605
|
+
tabIndex: 0,
|
|
5606
|
+
title: isCollapsed ? "Expand" : "Collapse",
|
|
5607
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
5608
|
+
className: "codiff-chevron-box",
|
|
5609
|
+
children: /* @__PURE__ */ jsx(CaretDownIcon, {
|
|
5610
|
+
"aria-hidden": true,
|
|
5611
|
+
className: isCollapsed ? "codiff-chevron collapsed" : "codiff-chevron",
|
|
5612
|
+
size: 16,
|
|
5613
|
+
weight: "bold"
|
|
5614
|
+
})
|
|
5615
|
+
}), /* @__PURE__ */ jsxs("span", {
|
|
5616
|
+
className: "codiff-file-heading",
|
|
5080
5617
|
children: [
|
|
5081
|
-
/* @__PURE__ */ jsx("span", {
|
|
5082
|
-
className: "codiff-chevron-box",
|
|
5083
|
-
children: /* @__PURE__ */ jsx(CaretDownIcon, {
|
|
5084
|
-
"aria-hidden": true,
|
|
5085
|
-
className: isCollapsed ? "codiff-chevron collapsed" : "codiff-chevron",
|
|
5086
|
-
size: 16,
|
|
5087
|
-
weight: "bold"
|
|
5088
|
-
})
|
|
5089
|
-
}),
|
|
5090
5618
|
/* @__PURE__ */ jsxs("span", {
|
|
5091
|
-
className: "codiff-file-
|
|
5619
|
+
className: "codiff-file-path-row",
|
|
5092
5620
|
children: [
|
|
5093
5621
|
/* @__PURE__ */ jsxs("span", {
|
|
5094
|
-
className: "codiff-file-path
|
|
5095
|
-
|
|
5096
|
-
|
|
5097
|
-
|
|
5098
|
-
|
|
5622
|
+
className: "codiff-file-path",
|
|
5623
|
+
title: file.path,
|
|
5624
|
+
children: [directoryEnd > 0 ? /* @__PURE__ */ jsx("span", {
|
|
5625
|
+
className: "codiff-file-directory",
|
|
5626
|
+
children: file.path.slice(0, directoryEnd)
|
|
5627
|
+
}) : null, /* @__PURE__ */ jsx("span", {
|
|
5628
|
+
className: "codiff-file-name",
|
|
5629
|
+
children: file.path.slice(directoryEnd)
|
|
5630
|
+
})]
|
|
5099
5631
|
}),
|
|
5100
|
-
|
|
5101
|
-
|
|
5102
|
-
|
|
5103
|
-
|
|
5104
|
-
|
|
5105
|
-
|
|
5106
|
-
|
|
5632
|
+
/* @__PURE__ */ jsx(CopyFilePathButton, { path: file.path }),
|
|
5633
|
+
!readOnly && onOpenFile ? /* @__PURE__ */ jsx("button", {
|
|
5634
|
+
"aria-label": `Open ${file.path} in editor`,
|
|
5635
|
+
className: "codiff-open-file-button",
|
|
5636
|
+
disabled: !canOpenFile,
|
|
5637
|
+
onClick: (event) => {
|
|
5638
|
+
event.stopPropagation();
|
|
5639
|
+
onOpenFile(file);
|
|
5640
|
+
},
|
|
5641
|
+
onKeyDown: (event) => {
|
|
5642
|
+
if (event.key === "Enter" || event.key === " ") event.stopPropagation();
|
|
5643
|
+
},
|
|
5644
|
+
title: canOpenFile ? "Open file in editor" : "Deleted files cannot be opened",
|
|
5645
|
+
type: "button",
|
|
5646
|
+
children: /* @__PURE__ */ jsx(ArrowSquareOutIcon, {
|
|
5647
|
+
"aria-hidden": true,
|
|
5648
|
+
size: 16,
|
|
5649
|
+
weight: "bold"
|
|
5650
|
+
})
|
|
5107
5651
|
}) : null
|
|
5108
5652
|
]
|
|
5109
5653
|
}),
|
|
5110
|
-
|
|
5111
|
-
className:
|
|
5112
|
-
children:
|
|
5654
|
+
file.oldPath ? /* @__PURE__ */ jsx("span", {
|
|
5655
|
+
className: "codiff-file-old-path",
|
|
5656
|
+
children: file.oldPath
|
|
5113
5657
|
}) : null,
|
|
5114
|
-
|
|
5115
|
-
className: "codiff-
|
|
5116
|
-
|
|
5117
|
-
children: "Generated"
|
|
5658
|
+
walkthroughNote ? /* @__PURE__ */ jsx("span", {
|
|
5659
|
+
className: "codiff-file-note",
|
|
5660
|
+
children: walkthroughNote.reason
|
|
5118
5661
|
}) : null
|
|
5119
5662
|
]
|
|
5120
|
-
})
|
|
5121
|
-
|
|
5122
|
-
|
|
5123
|
-
|
|
5124
|
-
|
|
5125
|
-
|
|
5126
|
-
|
|
5127
|
-
|
|
5128
|
-
|
|
5129
|
-
|
|
5130
|
-
|
|
5131
|
-
|
|
5132
|
-
"
|
|
5133
|
-
|
|
5134
|
-
|
|
5135
|
-
|
|
5136
|
-
|
|
5137
|
-
|
|
5138
|
-
|
|
5139
|
-
|
|
5140
|
-
|
|
5141
|
-
|
|
5142
|
-
|
|
5143
|
-
type: "button",
|
|
5144
|
-
children: isMarkdownPreview ? "View as Diff" : "View as Markdown"
|
|
5145
|
-
}) : null,
|
|
5146
|
-
canLoadSection && !readOnly ? /* @__PURE__ */ jsx("button", {
|
|
5147
|
-
className: "codiff-load-button",
|
|
5148
|
-
disabled: isSectionLoading,
|
|
5149
|
-
onClick: () => onLoadSection(file, section),
|
|
5150
|
-
title: isSectionLoading ? "Loading file contents" : "Load file contents",
|
|
5151
|
-
type: "button",
|
|
5152
|
-
children: isSectionLoading ? "Loading..." : "Load"
|
|
5153
|
-
}) : null,
|
|
5154
|
-
!readOnly && onOpenFile ? /* @__PURE__ */ jsx(Button, {
|
|
5155
|
-
disabled: !canOpenFile,
|
|
5156
|
-
onClick: () => onOpenFile(file),
|
|
5157
|
-
title: canOpenFile ? "Open file in editor" : "Deleted files cannot be opened",
|
|
5158
|
-
type: "button",
|
|
5159
|
-
children: "Open"
|
|
5160
|
-
}) : null,
|
|
5161
|
-
!readOnly || allowViewedToggle ? /* @__PURE__ */ jsxs("button", {
|
|
5162
|
-
"aria-pressed": isViewed,
|
|
5163
|
-
className: `codiff-viewed-button${isViewed ? " active" : ""}`,
|
|
5164
|
-
onClick: () => onToggleViewed(file, isViewed, reviewIdentity),
|
|
5165
|
-
type: "button",
|
|
5166
|
-
children: [/* @__PURE__ */ jsx("span", {
|
|
5167
|
-
"aria-hidden": true,
|
|
5168
|
-
className: "codiff-viewed-checkbox",
|
|
5169
|
-
children: isViewed ? /* @__PURE__ */ jsx(CheckIcon, {
|
|
5170
|
-
className: "codiff-viewed-check",
|
|
5171
|
-
size: 10,
|
|
5663
|
+
})]
|
|
5664
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
5665
|
+
className: "codiff-file-details",
|
|
5666
|
+
children: [
|
|
5667
|
+
/* @__PURE__ */ jsx(DiffLineCountBadge, { lineCount }),
|
|
5668
|
+
sectionCount > 1 ? /* @__PURE__ */ jsx("span", {
|
|
5669
|
+
className: `codiff-section-badge ${section.kind}`,
|
|
5670
|
+
children: sectionLabel[section.kind]
|
|
5671
|
+
}) : null,
|
|
5672
|
+
isGeneratedWalkthroughFile(file) ? /* @__PURE__ */ jsx("span", {
|
|
5673
|
+
className: "codiff-generated-badge",
|
|
5674
|
+
title: "Generated file",
|
|
5675
|
+
children: "Generated"
|
|
5676
|
+
}) : null,
|
|
5677
|
+
canCreateFileComment ? /* @__PURE__ */ jsxs(Button, {
|
|
5678
|
+
className: "codiff-file-comment-button",
|
|
5679
|
+
onClick: onCreateFileComment,
|
|
5680
|
+
title: "Comment on file",
|
|
5681
|
+
type: "button",
|
|
5682
|
+
children: [/* @__PURE__ */ jsx(ChatCircleIcon, {
|
|
5683
|
+
"aria-hidden": true,
|
|
5684
|
+
className: "codiff-file-comment-icon",
|
|
5685
|
+
size: 14,
|
|
5172
5686
|
weight: "bold"
|
|
5173
|
-
})
|
|
5174
|
-
}),
|
|
5175
|
-
|
|
5176
|
-
|
|
5687
|
+
}), "Comment"]
|
|
5688
|
+
}) : null,
|
|
5689
|
+
canRenderMarkdown ? /* @__PURE__ */ jsx(Button, {
|
|
5690
|
+
"aria-pressed": isMarkdownPreview,
|
|
5691
|
+
className: `codiff-markdown-button${isMarkdownPreview ? " active" : ""}`,
|
|
5692
|
+
disabled: isEditing,
|
|
5693
|
+
onClick: () => onToggleMarkdownPreview(file, section),
|
|
5694
|
+
title: isMarkdownPreview ? "View as Diff" : "View as Markdown",
|
|
5695
|
+
type: "button",
|
|
5696
|
+
children: isMarkdownPreview ? "View as Diff" : "View as Markdown"
|
|
5697
|
+
}) : null,
|
|
5698
|
+
editActions,
|
|
5699
|
+
canLoadSection && !readOnly ? /* @__PURE__ */ jsx("button", {
|
|
5700
|
+
className: "codiff-load-button",
|
|
5701
|
+
disabled: isSectionLoading,
|
|
5702
|
+
onClick: () => onLoadSection(file, section),
|
|
5703
|
+
title: isSectionLoading ? "Loading file contents" : "Load file contents",
|
|
5704
|
+
type: "button",
|
|
5705
|
+
children: isSectionLoading ? "Loading..." : "Load"
|
|
5706
|
+
}) : null,
|
|
5707
|
+
!readOnly || allowViewedToggle ? /* @__PURE__ */ jsxs("button", {
|
|
5708
|
+
"aria-pressed": isViewed,
|
|
5709
|
+
className: `codiff-viewed-button${isViewed ? " active" : ""}`,
|
|
5710
|
+
onClick: () => onToggleViewed(file, isViewed, reviewIdentity),
|
|
5711
|
+
type: "button",
|
|
5712
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
5713
|
+
"aria-hidden": true,
|
|
5714
|
+
className: "codiff-viewed-checkbox",
|
|
5715
|
+
children: isViewed ? /* @__PURE__ */ jsx(CheckIcon, {
|
|
5716
|
+
className: "codiff-viewed-check",
|
|
5717
|
+
size: 10,
|
|
5718
|
+
weight: "bold"
|
|
5719
|
+
}) : null
|
|
5720
|
+
}), "Viewed"]
|
|
5721
|
+
}) : null
|
|
5722
|
+
]
|
|
5723
|
+
})]
|
|
5177
5724
|
});
|
|
5178
5725
|
}
|
|
5179
5726
|
const getReviewAuthorDisplayName = (author) => author.name || author.login || "Git user";
|
|
@@ -5223,28 +5770,48 @@ const formatBytes = (size) => {
|
|
|
5223
5770
|
}
|
|
5224
5771
|
return `${size} B`;
|
|
5225
5772
|
};
|
|
5226
|
-
function MarkdownPreview({ contents, editable,
|
|
5227
|
-
|
|
5228
|
-
|
|
5773
|
+
function MarkdownPreview({ cacheKey, contents, editable, heightCache, onEditorRef, onLayoutReady, path, sectionId }) {
|
|
5774
|
+
const contentRef = useRef(null);
|
|
5775
|
+
const [ready, setReady] = useState(false);
|
|
5776
|
+
const measure = useCallback((reportedHeight) => {
|
|
5777
|
+
const content = contentRef.current;
|
|
5778
|
+
if (!content?.isConnected || content.querySelector(".codiff-markdown-editor-message:not(.error), .codiff-readonly-markdown-loading")) return;
|
|
5779
|
+
const height = content.getBoundingClientRect().height || reportedHeight;
|
|
5780
|
+
if (height == null || height <= 0) return;
|
|
5781
|
+
setReady(true);
|
|
5782
|
+
if (heightCache.get(cacheKey) !== height) {
|
|
5783
|
+
heightCache.set(cacheKey, height);
|
|
5784
|
+
onLayoutReady(sectionId);
|
|
5785
|
+
}
|
|
5229
5786
|
}, [
|
|
5230
|
-
|
|
5787
|
+
cacheKey,
|
|
5788
|
+
heightCache,
|
|
5231
5789
|
onLayoutReady,
|
|
5232
5790
|
sectionId
|
|
5233
5791
|
]);
|
|
5234
|
-
|
|
5235
|
-
|
|
5236
|
-
|
|
5237
|
-
|
|
5238
|
-
|
|
5239
|
-
|
|
5240
|
-
|
|
5241
|
-
}
|
|
5242
|
-
|
|
5243
|
-
|
|
5244
|
-
|
|
5245
|
-
className:
|
|
5246
|
-
|
|
5247
|
-
|
|
5792
|
+
useLayoutEffect(() => {
|
|
5793
|
+
const content = contentRef.current;
|
|
5794
|
+
if (!content) return;
|
|
5795
|
+
const observer = new ResizeObserver(() => measure());
|
|
5796
|
+
observer.observe(content);
|
|
5797
|
+
measure();
|
|
5798
|
+
return () => observer.disconnect();
|
|
5799
|
+
}, [measure]);
|
|
5800
|
+
return /* @__PURE__ */ jsx("div", {
|
|
5801
|
+
style: { minHeight: ready ? void 0 : heightCache.get(cacheKey) },
|
|
5802
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
5803
|
+
className: `codiff-markdown-preview${editable ? " editable" : ""}`,
|
|
5804
|
+
ref: contentRef,
|
|
5805
|
+
children: editable ? /* @__PURE__ */ jsx(RepositoryMarkdownEditor, {
|
|
5806
|
+
onHeightChange: measure,
|
|
5807
|
+
path,
|
|
5808
|
+
ref: (editor) => onEditorRef(sectionId, editor)
|
|
5809
|
+
}) : /* @__PURE__ */ jsx(ReadOnlyMarkdown, {
|
|
5810
|
+
ariaLabel: `Preview ${path}`,
|
|
5811
|
+
className: "codiff-markdown-preview-editor",
|
|
5812
|
+
onHeightChange: measure,
|
|
5813
|
+
value: contents
|
|
5814
|
+
})
|
|
5248
5815
|
})
|
|
5249
5816
|
});
|
|
5250
5817
|
}
|
|
@@ -6642,8 +7209,30 @@ const getHunkSelectionRange = (hunk) => {
|
|
|
6642
7209
|
} : null;
|
|
6643
7210
|
};
|
|
6644
7211
|
const isSameSelection = (a, b) => a.start === b.start && a.end === b.end && a.side === b.side;
|
|
6645
|
-
function ReviewCodeView({ activeSearchMatch, agentId, agentLabel, allowViewedToggle = false, blocks, bottomInset = codeViewLayout.paddingBottom, codeQualityFindings = [], collapsed, comments, commitMetadata, diffLineHeight = 20, diffStyle, disableWorkerPool = false, expandedReviewKeys = emptyExpandedReviewKeys, files, focusCommentId, focusCommentRequest, forceExpandedPaths, gitIdentity, hunkNavigation, initialMarkdownPreviewSectionIds = emptyMarkdownPreviewSectionIds, isReadOnly = false, itemVersionByKey, keymap, loadingSectionIds, onActiveBlockChange, onAskCodex, onCommentDraftChange, onCreateComment, onDeleteComment, onFindDefinitions, onLoadImageContent, onLoadSection, onLoadSectionContents, onOpenDefinition, onOpenFile, onRefreshMarkdown, onResolveThread = noopResolveThread, onSaveCommentEdit, onSelectPathFromScroll, onSubmitComment, onToggleCollapsed, onToggleViewed, onUpdateComment, onUpdateSourceDescription, onUpdateSourceTitle, onUploadSourceDescriptionAsset, reviewIdentityByPath, scrollTarget, searchQuery, selectedPath, showSourceDescription = true, showWhitespace, source, sourceDescriptionActions, sourceDescriptionFooter, supportsReviewCommentActions, theme = "system", viewed, walkthroughNotes, wordWrap }) {
|
|
7212
|
+
function ReviewCodeView({ activeSearchMatch, agentId, agentLabel, allowViewedToggle = false, blocks, bottomInset = codeViewLayout.paddingBottom, codeEditingStore, codeQualityFindings = [], collapsed, comments, commitMetadata, diffLineHeight = 20, diffStyle, disableWorkerPool = false, expandedReviewKeys = emptyExpandedReviewKeys, files, focusCommentId, focusCommentRequest, forceExpandedPaths, gitIdentity, hunkNavigation, initialMarkdownPreviewSectionIds = emptyMarkdownPreviewSectionIds, isReadOnly = false, itemVersionByKey, keymap, loadingSectionIds, onActiveBlockChange, onAskCodex, onCommentDraftChange, onCreateComment, onDeleteComment, onFindDefinitions, onLoadImageContent, onLoadSection, onLoadSectionContents, onOpenDefinition, onOpenFile, onRefreshMarkdown, onResolveThread = noopResolveThread, onSaveCommentEdit, onSelectPathFromScroll, onSubmitComment, onToggleCollapsed, onToggleViewed, onUpdateComment, onUpdateSourceDescription, onUpdateSourceTitle, onUploadSourceDescriptionAsset, reviewIdentityByPath, scrollTarget, searchQuery, selectedPath, showSourceDescription = true, showWhitespace, source, sourceDescriptionActions, sourceDescriptionFooter, supportsReviewCommentActions, theme = "system", viewed, walkthroughNotes, wordWrap }) {
|
|
6646
7213
|
const codeViewRef = useRef(null);
|
|
7214
|
+
const [codeViewElement, setCodeViewElement] = useState(null);
|
|
7215
|
+
const [compactHeaders, setCompactHeaders] = useState(false);
|
|
7216
|
+
useLayoutEffect(() => {
|
|
7217
|
+
if (!codeViewElement) return;
|
|
7218
|
+
const measure = () => {
|
|
7219
|
+
const width = codeViewElement.getBoundingClientRect().width;
|
|
7220
|
+
if (width > 0) setCompactHeaders(width <= 760);
|
|
7221
|
+
};
|
|
7222
|
+
measure();
|
|
7223
|
+
const observer = new ResizeObserver(measure);
|
|
7224
|
+
observer.observe(codeViewElement);
|
|
7225
|
+
return () => observer.disconnect();
|
|
7226
|
+
}, [codeViewElement]);
|
|
7227
|
+
const headerHeight = compactHeaders ? 90 : codeViewItemMetrics.diffHeaderHeight;
|
|
7228
|
+
const itemMetrics = useMemo(() => ({
|
|
7229
|
+
...codeViewItemMetrics,
|
|
7230
|
+
diffHeaderHeight: headerHeight
|
|
7231
|
+
}), [headerHeight]);
|
|
7232
|
+
const codeViewStyle = { "--codiff-file-header-height": `${headerHeight}px` };
|
|
7233
|
+
const getPlaceholderFile = useCodeViewPlaceholderFile();
|
|
7234
|
+
const getAnnotations = useCodeViewAnnotations();
|
|
7235
|
+
const [markdownPreviewHeights] = useState(() => /* @__PURE__ */ new Map());
|
|
6647
7236
|
const markdownEditorRefs = useRef(/* @__PURE__ */ new Map());
|
|
6648
7237
|
const refreshingMarkdownSectionsRef = useRef(/* @__PURE__ */ new Set());
|
|
6649
7238
|
const deferredTimersRef = useRef(/* @__PURE__ */ new Set());
|
|
@@ -6751,12 +7340,7 @@ function ReviewCodeView({ activeSearchMatch, agentId, agentLabel, allowViewedTog
|
|
|
6751
7340
|
}
|
|
6752
7341
|
}],
|
|
6753
7342
|
collapsed: false,
|
|
6754
|
-
file:
|
|
6755
|
-
cacheKey: `walkthrough-header:${block.id}`,
|
|
6756
|
-
contents: " ",
|
|
6757
|
-
lang: "text",
|
|
6758
|
-
name: headerId
|
|
6759
|
-
},
|
|
7343
|
+
file: getPlaceholderFile(headerId),
|
|
6760
7344
|
id: headerId,
|
|
6761
7345
|
type: "file",
|
|
6762
7346
|
version: getItemVersion(`${block.id}:walkthrough-header`)
|
|
@@ -6861,12 +7445,7 @@ function ReviewCodeView({ activeSearchMatch, agentId, agentLabel, allowViewedTog
|
|
|
6861
7445
|
}
|
|
6862
7446
|
}],
|
|
6863
7447
|
collapsed: isCollapsed,
|
|
6864
|
-
file:
|
|
6865
|
-
cacheKey: `image-preview:${file.fingerprint}:${section.id}`,
|
|
6866
|
-
contents: " ",
|
|
6867
|
-
lang: "text",
|
|
6868
|
-
name: file.path
|
|
6869
|
-
},
|
|
7448
|
+
file: getPlaceholderFile(file.path),
|
|
6870
7449
|
id,
|
|
6871
7450
|
type: "file",
|
|
6872
7451
|
version: getItemVersion(`${reviewVersionPrefix}:image:${sectionStateVersionKey}:${imagePreviewLayoutPassBySection[section.id] ?? 0}`)
|
|
@@ -6877,7 +7456,12 @@ function ReviewCodeView({ activeSearchMatch, agentId, agentLabel, allowViewedTog
|
|
|
6877
7456
|
const markdownPreviewAddedLinesDigest = getAddedLinesDigest(markdownPreview.addedLines);
|
|
6878
7457
|
const markdownPreviewLayoutKey = `${section.id}:${markdownPreview.contents.length}:${markdownPreviewAddedLinesDigest}`;
|
|
6879
7458
|
nextItems.push({
|
|
6880
|
-
annotations:
|
|
7459
|
+
annotations: getAnnotations(id, JSON.stringify([
|
|
7460
|
+
markdownPreview.contents,
|
|
7461
|
+
markdownPreviewAddedLinesDigest,
|
|
7462
|
+
canEditMarkdown,
|
|
7463
|
+
fileCommentAnnotations
|
|
7464
|
+
]), [...fileCommentAnnotations, {
|
|
6881
7465
|
lineNumber: 1,
|
|
6882
7466
|
metadata: {
|
|
6883
7467
|
addedLines: markdownPreview.addedLines,
|
|
@@ -6888,14 +7472,9 @@ function ReviewCodeView({ activeSearchMatch, agentId, agentLabel, allowViewedTog
|
|
|
6888
7472
|
sectionId: section.id,
|
|
6889
7473
|
type: "markdown-preview"
|
|
6890
7474
|
}
|
|
6891
|
-
}],
|
|
7475
|
+
}]),
|
|
6892
7476
|
collapsed: isCollapsed,
|
|
6893
|
-
file:
|
|
6894
|
-
cacheKey: `markdown-preview:${section.newFile?.cacheKey ?? file.fingerprint}:${markdownPreview.contents.length}:${markdownPreviewAddedLinesDigest}`,
|
|
6895
|
-
contents: " ",
|
|
6896
|
-
lang: "text",
|
|
6897
|
-
name: file.path
|
|
6898
|
-
},
|
|
7477
|
+
file: getPlaceholderFile(file.path),
|
|
6899
7478
|
id,
|
|
6900
7479
|
type: "file",
|
|
6901
7480
|
version: getItemVersion(`${reviewVersionPrefix}:markdown:${sectionStateVersionKey}:${markdownPreviewLayoutKey}:${markdownPreviewLayoutPassBySection[section.id] ?? 0}`)
|
|
@@ -6931,6 +7510,8 @@ function ReviewCodeView({ activeSearchMatch, agentId, agentLabel, allowViewedTog
|
|
|
6931
7510
|
diffStyle,
|
|
6932
7511
|
expandedReviewKeys,
|
|
6933
7512
|
forceExpandedPaths,
|
|
7513
|
+
getAnnotations,
|
|
7514
|
+
getPlaceholderFile,
|
|
6934
7515
|
imagePreviewLayoutPassBySection,
|
|
6935
7516
|
isReadOnly,
|
|
6936
7517
|
itemVersionByKey,
|
|
@@ -6949,20 +7530,101 @@ function ReviewCodeView({ activeSearchMatch, agentId, agentLabel, allowViewedTog
|
|
|
6949
7530
|
if (items.length > 0 || !sourceDescriptionItemId) return items;
|
|
6950
7531
|
return [{
|
|
6951
7532
|
collapsed: true,
|
|
6952
|
-
file:
|
|
6953
|
-
cacheKey: sourceDescriptionItemId,
|
|
6954
|
-
contents: "",
|
|
6955
|
-
lang: "text",
|
|
6956
|
-
name: shouldShowCommitMessage ? "commit-message.md" : "source-description.md"
|
|
6957
|
-
},
|
|
7533
|
+
file: getPlaceholderFile(shouldShowCommitMessage ? "commit-message.md" : "source-description.md", ""),
|
|
6958
7534
|
id: sourceDescriptionItemId,
|
|
6959
7535
|
type: "file"
|
|
6960
7536
|
}];
|
|
6961
7537
|
}, [
|
|
7538
|
+
getPlaceholderFile,
|
|
6962
7539
|
items,
|
|
6963
7540
|
shouldShowCommitMessage,
|
|
6964
7541
|
sourceDescriptionItemId
|
|
6965
7542
|
]);
|
|
7543
|
+
const highlightedCodeItems = codeViewItems.filter((item) => itemMetadata.get(item.id)?.isSelected);
|
|
7544
|
+
const selectedCodeItemId = highlightedCodeItems.find((item) => item.id === selectedLines?.id && itemMetadata.get(item.id)?.section.kind === "unstaged")?.id ?? highlightedCodeItems.find((item) => itemMetadata.get(item.id)?.section.kind === "unstaged")?.id ?? highlightedCodeItems[0]?.id;
|
|
7545
|
+
const codeEditing = useCodeEditing({
|
|
7546
|
+
codeViewRef,
|
|
7547
|
+
items: codeViewItems,
|
|
7548
|
+
keymap,
|
|
7549
|
+
onLoadSectionContents,
|
|
7550
|
+
onRefresh: onRefreshMarkdown,
|
|
7551
|
+
selectedItemId: selectedCodeItemId,
|
|
7552
|
+
sourceKey,
|
|
7553
|
+
store: codeEditingStore
|
|
7554
|
+
});
|
|
7555
|
+
const canEditCodeItem = useCallback((item, meta) => meta != null && item.type === "diff" && !isReadOnly && !meta.section.binary && (meta.section.loadState == null || meta.section.loadState === "ready" || meta.section.loadState === "deferred") && !meta.isMarkdownPreview && meta.section.kind === "unstaged" && isEditableWorkingTreeSection(source.type, meta.file, meta.section) && onLoadSectionContents != null && window.codiff?.getRepositoryFile != null, [
|
|
7556
|
+
isReadOnly,
|
|
7557
|
+
onLoadSectionContents,
|
|
7558
|
+
source.type
|
|
7559
|
+
]);
|
|
7560
|
+
const startCodeEdit = useCallback((item, meta) => {
|
|
7561
|
+
if (meta.isCollapsed) onToggleCollapsed(meta.file, true, meta.reviewIdentity.key);
|
|
7562
|
+
codeEditing.startEdit(item, meta);
|
|
7563
|
+
}, [codeEditing, onToggleCollapsed]);
|
|
7564
|
+
const editAfterExpandRef = useRef(null);
|
|
7565
|
+
useEffect(() => {
|
|
7566
|
+
const pending = editAfterExpandRef.current;
|
|
7567
|
+
if (!pending) return;
|
|
7568
|
+
if (pending.sourceKey !== sourceKey || !highlightedCodeItems.some((item) => itemMetadata.get(item.id)?.file.path === pending.path)) {
|
|
7569
|
+
editAfterExpandRef.current = null;
|
|
7570
|
+
return;
|
|
7571
|
+
}
|
|
7572
|
+
const item = highlightedCodeItems.find((candidate) => {
|
|
7573
|
+
const meta = itemMetadata.get(candidate.id);
|
|
7574
|
+
return meta?.file.path === pending.path && canEditCodeItem(candidate, meta);
|
|
7575
|
+
});
|
|
7576
|
+
const meta = item && itemMetadata.get(item.id);
|
|
7577
|
+
if (item && meta) {
|
|
7578
|
+
editAfterExpandRef.current = null;
|
|
7579
|
+
startCodeEdit(item, meta);
|
|
7580
|
+
}
|
|
7581
|
+
}, [
|
|
7582
|
+
canEditCodeItem,
|
|
7583
|
+
highlightedCodeItems,
|
|
7584
|
+
itemMetadata,
|
|
7585
|
+
sourceKey,
|
|
7586
|
+
startCodeEdit
|
|
7587
|
+
]);
|
|
7588
|
+
useEffect(() => {
|
|
7589
|
+
const handleKeyDown = (event) => {
|
|
7590
|
+
if (event.defaultPrevented || event.repeat || event.isComposing || isNativeInputTarget(event.target) || !matchesShortcut(event, keymap, "editFile")) return;
|
|
7591
|
+
const item = codeViewItems.find((candidate) => candidate.id === selectedCodeItemId);
|
|
7592
|
+
const meta = item && itemMetadata.get(item.id);
|
|
7593
|
+
if (!item || !meta || !codeEditing.canStartEdit(item.id, meta.file.path)) return;
|
|
7594
|
+
if (!canEditCodeItem(item, meta)) {
|
|
7595
|
+
if (!meta.isCollapsed || !getVisibleDiffSections(meta.file, showWhitespace).some(({ fileDiff, section }) => canEditCodeItem({
|
|
7596
|
+
fileDiff,
|
|
7597
|
+
id: item.id,
|
|
7598
|
+
type: "diff"
|
|
7599
|
+
}, {
|
|
7600
|
+
...meta,
|
|
7601
|
+
section
|
|
7602
|
+
}))) return;
|
|
7603
|
+
event.preventDefault();
|
|
7604
|
+
editAfterExpandRef.current = {
|
|
7605
|
+
path: meta.file.path,
|
|
7606
|
+
sourceKey
|
|
7607
|
+
};
|
|
7608
|
+
onToggleCollapsed(meta.file, true, meta.reviewIdentity.key);
|
|
7609
|
+
return;
|
|
7610
|
+
}
|
|
7611
|
+
event.preventDefault();
|
|
7612
|
+
startCodeEdit(item, meta);
|
|
7613
|
+
};
|
|
7614
|
+
window.addEventListener("keydown", handleKeyDown);
|
|
7615
|
+
return () => window.removeEventListener("keydown", handleKeyDown);
|
|
7616
|
+
}, [
|
|
7617
|
+
canEditCodeItem,
|
|
7618
|
+
codeEditing,
|
|
7619
|
+
codeViewItems,
|
|
7620
|
+
itemMetadata,
|
|
7621
|
+
keymap,
|
|
7622
|
+
onToggleCollapsed,
|
|
7623
|
+
selectedCodeItemId,
|
|
7624
|
+
showWhitespace,
|
|
7625
|
+
sourceKey,
|
|
7626
|
+
startCodeEdit
|
|
7627
|
+
]);
|
|
6966
7628
|
const clearCommentLineHighlight = useCallback(() => {
|
|
6967
7629
|
codeViewRef.current?.clearSelectedLines();
|
|
6968
7630
|
navigatedSelectionRef.current = null;
|
|
@@ -7145,7 +7807,7 @@ function ReviewCodeView({ activeSearchMatch, agentId, agentLabel, allowViewedTog
|
|
|
7145
7807
|
expandUnchanged: false,
|
|
7146
7808
|
expansionLineCount: 100,
|
|
7147
7809
|
hunkSeparators: "line-info-basic",
|
|
7148
|
-
itemMetrics
|
|
7810
|
+
itemMetrics,
|
|
7149
7811
|
layout: {
|
|
7150
7812
|
...codeViewLayout,
|
|
7151
7813
|
paddingBottom: bottomInset
|
|
@@ -7153,11 +7815,12 @@ function ReviewCodeView({ activeSearchMatch, agentId, agentLabel, allowViewedTog
|
|
|
7153
7815
|
lineHoverHighlight: "both",
|
|
7154
7816
|
loadDiffFiles,
|
|
7155
7817
|
onGutterUtilityClick: (range, context) => {
|
|
7156
|
-
if (isReadOnly) return;
|
|
7818
|
+
if (isReadOnly || context.item.edit) return;
|
|
7157
7819
|
ignoreNextLineSelectionEndRef.current = context.item.type === "diff";
|
|
7158
7820
|
createCommentForRange(range, context);
|
|
7159
7821
|
},
|
|
7160
7822
|
onLineClick: (line, context) => {
|
|
7823
|
+
if (context.item.edit) return;
|
|
7161
7824
|
const lineElement = "lineElement" in line ? line.lineElement : null;
|
|
7162
7825
|
if (isPrimaryModifier(line.event) && onFindDefinitions) {
|
|
7163
7826
|
line.event.preventDefault();
|
|
@@ -7222,7 +7885,7 @@ function ReviewCodeView({ activeSearchMatch, agentId, agentLabel, allowViewedTog
|
|
|
7222
7885
|
});
|
|
7223
7886
|
},
|
|
7224
7887
|
onLineSelectionEnd: (range, context) => {
|
|
7225
|
-
if (isReadOnly) return;
|
|
7888
|
+
if (isReadOnly || context.item.edit) return;
|
|
7226
7889
|
if (ignoreNextLineSelectionEndRef.current) {
|
|
7227
7890
|
ignoreNextLineSelectionEndRef.current = false;
|
|
7228
7891
|
return;
|
|
@@ -7237,10 +7900,10 @@ function ReviewCodeView({ activeSearchMatch, agentId, agentLabel, allowViewedTog
|
|
|
7237
7900
|
node.classList.toggle("codiff-selected-item", metadata?.isSelected === true || selectedHeaderItemIds.has(context.item.id));
|
|
7238
7901
|
node.classList.toggle("codiff-markdown-preview-item", metadata?.isMarkdownPreview === true);
|
|
7239
7902
|
node.classList.toggle("codiff-image-preview-item", context.item.type === "file" && Boolean(metadata && canRenderImagePreview(metadata.file.path, metadata.section)));
|
|
7240
|
-
node.classList.toggle("codiff-loadable-summary-item", metadata != null && shouldLoadDiffSectionContents(metadata.section));
|
|
7903
|
+
node.classList.toggle("codiff-loadable-summary-item", !context.item.edit && metadata != null && shouldLoadDiffSectionContents(metadata.section));
|
|
7241
7904
|
node.classList.toggle("codiff-loading-summary-item", Boolean(metadata && loadingSectionIds.has(metadata.section.id)));
|
|
7242
7905
|
if (definitionModifierActiveRef.current) window.requestAnimationFrame(() => {
|
|
7243
|
-
if (definitionModifierActiveRef.current && node.isConnected) applyIdentifierNavigationState([{ element: node }], true);
|
|
7906
|
+
if (definitionModifierActiveRef.current && node.isConnected && !codeViewRef.current?.getItem(context.item.id)?.edit) applyIdentifierNavigationState([{ element: node }], true);
|
|
7244
7907
|
});
|
|
7245
7908
|
},
|
|
7246
7909
|
overflow: wordWrap ? "wrap" : "scroll",
|
|
@@ -7251,7 +7914,8 @@ function ReviewCodeView({ activeSearchMatch, agentId, agentLabel, allowViewedTog
|
|
|
7251
7914
|
},
|
|
7252
7915
|
themeType: theme,
|
|
7253
7916
|
tokenizeMaxLength: 1e5,
|
|
7254
|
-
unsafeCSS: codeViewUnsafeCSS
|
|
7917
|
+
unsafeCSS: codeViewUnsafeCSS,
|
|
7918
|
+
useTokenTransformer: workerHighlighterOptions.useTokenTransformer
|
|
7255
7919
|
}), [
|
|
7256
7920
|
bottomInset,
|
|
7257
7921
|
cancelPendingEmptyCommentDeletes,
|
|
@@ -7259,6 +7923,7 @@ function ReviewCodeView({ activeSearchMatch, agentId, agentLabel, allowViewedTog
|
|
|
7259
7923
|
diffStyle,
|
|
7260
7924
|
isReadOnly,
|
|
7261
7925
|
itemMetadata,
|
|
7926
|
+
itemMetrics,
|
|
7262
7927
|
loadDiffFiles,
|
|
7263
7928
|
loadingSectionIds,
|
|
7264
7929
|
onCreateComment,
|
|
@@ -7428,7 +8093,6 @@ function ReviewCodeView({ activeSearchMatch, agentId, agentLabel, allowViewedTog
|
|
|
7428
8093
|
const viewer = handle?.getInstance();
|
|
7429
8094
|
if (!handle || !viewer) return;
|
|
7430
8095
|
handledHunkNavRef.current = hunkNavigation.request;
|
|
7431
|
-
const headerHeight = codeViewItemMetrics.diffHeaderHeight;
|
|
7432
8096
|
const anchors = [];
|
|
7433
8097
|
const seen = /* @__PURE__ */ new Set();
|
|
7434
8098
|
const lineScrollTarget = (id, lineNumber, side) => ({
|
|
@@ -7547,6 +8211,7 @@ function ReviewCodeView({ activeSearchMatch, agentId, agentLabel, allowViewedTog
|
|
|
7547
8211
|
clearCommentLineHighlight,
|
|
7548
8212
|
diffLineHeight,
|
|
7549
8213
|
diffStyle,
|
|
8214
|
+
headerHeight,
|
|
7550
8215
|
hunkNavigation,
|
|
7551
8216
|
itemMetadata,
|
|
7552
8217
|
items
|
|
@@ -7575,7 +8240,7 @@ function ReviewCodeView({ activeSearchMatch, agentId, agentLabel, allowViewedTog
|
|
|
7575
8240
|
if (highlightFrameRef.current != null) window.cancelAnimationFrame(highlightFrameRef.current);
|
|
7576
8241
|
highlightFrameRef.current = window.requestAnimationFrame(() => {
|
|
7577
8242
|
highlightFrameRef.current = null;
|
|
7578
|
-
applySearchHighlights(viewer.getRenderedItems(), searchQuery, resolvedActiveSearchMatch);
|
|
8243
|
+
applySearchHighlights(viewer.getRenderedItems().filter(({ item }) => !item.edit), searchQuery, resolvedActiveSearchMatch);
|
|
7579
8244
|
});
|
|
7580
8245
|
}, [resolvedActiveSearchMatch, searchQuery]);
|
|
7581
8246
|
const updateRenderedIdentifierNavigation = useCallback((active, viewer) => {
|
|
@@ -7586,12 +8251,12 @@ function ReviewCodeView({ activeSearchMatch, agentId, agentLabel, allowViewedTog
|
|
|
7586
8251
|
definitionHighlightFrameRef.current = null;
|
|
7587
8252
|
}
|
|
7588
8253
|
if (!active) {
|
|
7589
|
-
applyIdentifierNavigationState(nextViewer.getRenderedItems(), false);
|
|
8254
|
+
applyIdentifierNavigationState(nextViewer.getRenderedItems().filter(({ item }) => !item.edit), false);
|
|
7590
8255
|
return;
|
|
7591
8256
|
}
|
|
7592
8257
|
definitionHighlightFrameRef.current = window.requestAnimationFrame(() => {
|
|
7593
8258
|
definitionHighlightFrameRef.current = null;
|
|
7594
|
-
applyIdentifierNavigationState(nextViewer.getRenderedItems(), true);
|
|
8259
|
+
applyIdentifierNavigationState(nextViewer.getRenderedItems().filter(({ item }) => !item.edit), true);
|
|
7595
8260
|
});
|
|
7596
8261
|
}, []);
|
|
7597
8262
|
const scheduleStickyHeaderStateUpdate = useCallback((viewer) => {
|
|
@@ -7621,30 +8286,44 @@ function ReviewCodeView({ activeSearchMatch, agentId, agentLabel, allowViewedTog
|
|
|
7621
8286
|
]);
|
|
7622
8287
|
useEffect(() => {
|
|
7623
8288
|
if (!onFindDefinitions) return;
|
|
8289
|
+
let pointerDown = false;
|
|
7624
8290
|
const updateDefinitionModifierState = (active) => {
|
|
7625
8291
|
if (definitionModifierActiveRef.current === active) return;
|
|
7626
8292
|
definitionModifierActiveRef.current = active;
|
|
7627
8293
|
updateRenderedIdentifierNavigation(active);
|
|
7628
8294
|
};
|
|
7629
8295
|
const handleModifierChange = (event) => {
|
|
7630
|
-
updateDefinitionModifierState(isPrimaryModifier(event));
|
|
8296
|
+
updateDefinitionModifierState(isPrimaryModifier(event) && !pointerDown);
|
|
7631
8297
|
};
|
|
7632
8298
|
const handleModifierPointer = (event) => {
|
|
7633
|
-
|
|
8299
|
+
pointerDown = (event.buttons & 1) !== 0;
|
|
8300
|
+
updateDefinitionModifierState(isPrimaryModifier(event) && !pointerDown);
|
|
8301
|
+
};
|
|
8302
|
+
const handleSelectionChange = () => {
|
|
8303
|
+
updateRenderedIdentifierNavigation(definitionModifierActiveRef.current);
|
|
8304
|
+
};
|
|
8305
|
+
const clearDefinitionModifierState = () => {
|
|
8306
|
+
pointerDown = false;
|
|
8307
|
+
updateDefinitionModifierState(false);
|
|
7634
8308
|
};
|
|
7635
|
-
const clearDefinitionModifierState = () => updateDefinitionModifierState(false);
|
|
7636
8309
|
window.addEventListener("keydown", handleModifierChange);
|
|
7637
8310
|
window.addEventListener("keyup", handleModifierChange);
|
|
7638
8311
|
window.addEventListener("pointerdown", handleModifierPointer);
|
|
7639
8312
|
window.addEventListener("pointermove", handleModifierPointer);
|
|
8313
|
+
window.addEventListener("pointerup", handleModifierPointer);
|
|
8314
|
+
window.addEventListener("pointercancel", clearDefinitionModifierState);
|
|
7640
8315
|
window.addEventListener("blur", clearDefinitionModifierState);
|
|
8316
|
+
document.addEventListener("selectionchange", handleSelectionChange);
|
|
7641
8317
|
return () => {
|
|
7642
8318
|
clearDefinitionModifierState();
|
|
7643
8319
|
window.removeEventListener("keydown", handleModifierChange);
|
|
7644
8320
|
window.removeEventListener("keyup", handleModifierChange);
|
|
7645
8321
|
window.removeEventListener("pointerdown", handleModifierPointer);
|
|
7646
8322
|
window.removeEventListener("pointermove", handleModifierPointer);
|
|
8323
|
+
window.removeEventListener("pointerup", handleModifierPointer);
|
|
8324
|
+
window.removeEventListener("pointercancel", clearDefinitionModifierState);
|
|
7647
8325
|
window.removeEventListener("blur", clearDefinitionModifierState);
|
|
8326
|
+
document.removeEventListener("selectionchange", handleSelectionChange);
|
|
7648
8327
|
};
|
|
7649
8328
|
}, [onFindDefinitions, updateRenderedIdentifierNavigation]);
|
|
7650
8329
|
const invalidateDefinitionLookup = useCallback(() => {
|
|
@@ -7719,10 +8398,47 @@ function ReviewCodeView({ activeSearchMatch, agentId, agentLabel, allowViewedTog
|
|
|
7719
8398
|
toggleSourceDescriptionCollapsed
|
|
7720
8399
|
]);
|
|
7721
8400
|
const renderCustomHeader = useCallback((item) => {
|
|
7722
|
-
const
|
|
7723
|
-
|
|
8401
|
+
const editSession = codeEditing.sessions.get(item.id);
|
|
8402
|
+
const isEditing = editSession != null;
|
|
8403
|
+
const meta = editSession?.metadata ?? itemMetadata.get(item.id);
|
|
8404
|
+
const isBusy = codeEditing.isBusy(item.id);
|
|
8405
|
+
const isAutosaving = editSession?.saving && !isBusy;
|
|
8406
|
+
const canEdit = canEditCodeItem(item, meta);
|
|
8407
|
+
const editError = codeEditing.getError(item.id);
|
|
8408
|
+
return meta ? /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(CodeViewHeader, {
|
|
7724
8409
|
allowViewedToggle,
|
|
7725
8410
|
canCreateFileComment: canCreateFileComments,
|
|
8411
|
+
editActions: isEditing ? /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(Button, {
|
|
8412
|
+
"aria-label": `${editSession?.hasChanges ? "Revert edits to" : "Cancel editing"} ${meta.file.path}`,
|
|
8413
|
+
className: "codiff-edit-revert-button",
|
|
8414
|
+
"data-autosaving": isAutosaving ? "" : void 0,
|
|
8415
|
+
disabled: isBusy || editSession.saving,
|
|
8416
|
+
onClick: () => void codeEditing.revertEdit(item.id),
|
|
8417
|
+
title: editSession?.hasChanges ? "Restore the file to when editing started" : "Cancel editing",
|
|
8418
|
+
type: "button",
|
|
8419
|
+
variant: editSession?.hasChanges ? "destructive" : "default",
|
|
8420
|
+
children: editSession?.hasChanges ? "Revert" : "Cancel"
|
|
8421
|
+
}), /* @__PURE__ */ jsxs(Button, {
|
|
8422
|
+
"aria-label": `Done editing ${meta.file.path}`,
|
|
8423
|
+
"data-autosaving": isAutosaving ? "" : void 0,
|
|
8424
|
+
disabled: isBusy || editSession.saving,
|
|
8425
|
+
onClick: () => void codeEditing.doneEdit(item.id),
|
|
8426
|
+
title: "Finish editing; changes are saved automatically",
|
|
8427
|
+
type: "button",
|
|
8428
|
+
children: [/* @__PURE__ */ jsx(CheckIcon, {
|
|
8429
|
+
"aria-hidden": true,
|
|
8430
|
+
size: 14,
|
|
8431
|
+
weight: "bold"
|
|
8432
|
+
}), "Done"]
|
|
8433
|
+
})] }) : canEdit ? /* @__PURE__ */ jsx(CodeEditButton, {
|
|
8434
|
+
disabled: !codeEditing.canStartEdit(item.id, meta.file.path),
|
|
8435
|
+
isBusy,
|
|
8436
|
+
item,
|
|
8437
|
+
meta,
|
|
8438
|
+
onEdit: () => startCodeEdit(item, meta),
|
|
8439
|
+
onPrepare: codeEditing.prepareEdit
|
|
8440
|
+
}) : null,
|
|
8441
|
+
isEditing,
|
|
7726
8442
|
isSectionLoading: loadingSectionIds.has(meta.section.id),
|
|
7727
8443
|
meta,
|
|
7728
8444
|
onCreateFileComment: () => createFileComment(meta, item.id),
|
|
@@ -7732,11 +8448,17 @@ function ReviewCodeView({ activeSearchMatch, agentId, agentLabel, allowViewedTog
|
|
|
7732
8448
|
onToggleMarkdownPreview: toggleMarkdownPreview,
|
|
7733
8449
|
onToggleViewed,
|
|
7734
8450
|
readOnly: isReadOnly
|
|
7735
|
-
})
|
|
8451
|
+
}), editError ? /* @__PURE__ */ jsx("div", {
|
|
8452
|
+
className: "codiff-code-edit-error",
|
|
8453
|
+
role: "alert",
|
|
8454
|
+
children: editError
|
|
8455
|
+
}) : null] }) : null;
|
|
7736
8456
|
}, [
|
|
7737
8457
|
allowViewedToggle,
|
|
7738
8458
|
canCreateFileComments,
|
|
8459
|
+
canEditCodeItem,
|
|
7739
8460
|
createFileComment,
|
|
8461
|
+
codeEditing,
|
|
7740
8462
|
itemMetadata,
|
|
7741
8463
|
isReadOnly,
|
|
7742
8464
|
loadingSectionIds,
|
|
@@ -7744,6 +8466,7 @@ function ReviewCodeView({ activeSearchMatch, agentId, agentLabel, allowViewedTog
|
|
|
7744
8466
|
onOpenFile,
|
|
7745
8467
|
onToggleCollapsed,
|
|
7746
8468
|
onToggleViewed,
|
|
8469
|
+
startCodeEdit,
|
|
7747
8470
|
toggleMarkdownPreview
|
|
7748
8471
|
]);
|
|
7749
8472
|
const renderAnnotation = useCallback((annotation, item) => {
|
|
@@ -7758,9 +8481,10 @@ function ReviewCodeView({ activeSearchMatch, agentId, agentLabel, allowViewedTog
|
|
|
7758
8481
|
}) : null;
|
|
7759
8482
|
}
|
|
7760
8483
|
if (annotation.metadata.type === "markdown-preview") return /* @__PURE__ */ jsx(MarkdownPreview, {
|
|
8484
|
+
cacheKey: `${sourceKey}:${item.id}`,
|
|
7761
8485
|
contents: annotation.metadata.contents,
|
|
7762
8486
|
editable: annotation.metadata.editable,
|
|
7763
|
-
|
|
8487
|
+
heightCache: markdownPreviewHeights,
|
|
7764
8488
|
onEditorRef: setMarkdownEditorRef,
|
|
7765
8489
|
onLayoutReady: markMarkdownPreviewLayoutReady,
|
|
7766
8490
|
path: annotation.metadata.path,
|
|
@@ -7802,6 +8526,7 @@ function ReviewCodeView({ activeSearchMatch, agentId, agentLabel, allowViewedTog
|
|
|
7802
8526
|
itemMetadata,
|
|
7803
8527
|
keymap,
|
|
7804
8528
|
markMarkdownPreviewLayoutReady,
|
|
8529
|
+
markdownPreviewHeights,
|
|
7805
8530
|
markImagePreviewLayoutReady,
|
|
7806
8531
|
markCommentLayoutChanged,
|
|
7807
8532
|
onAskCodex,
|
|
@@ -7815,6 +8540,7 @@ function ReviewCodeView({ activeSearchMatch, agentId, agentLabel, allowViewedTog
|
|
|
7815
8540
|
replyToThread,
|
|
7816
8541
|
setMarkdownEditorRef,
|
|
7817
8542
|
source,
|
|
8543
|
+
sourceKey,
|
|
7818
8544
|
supportsReviewCommentActions
|
|
7819
8545
|
]);
|
|
7820
8546
|
const handleScroll = useCallback((_scrollTop, viewer) => {
|
|
@@ -7842,10 +8568,14 @@ function ReviewCodeView({ activeSearchMatch, agentId, agentLabel, allowViewedTog
|
|
|
7842
8568
|
scheduleStickyHeaderStateUpdate,
|
|
7843
8569
|
updateRenderedIdentifierNavigation
|
|
7844
8570
|
]);
|
|
7845
|
-
|
|
7846
|
-
className:
|
|
8571
|
+
const codeView = /* @__PURE__ */ jsx(CodeView, {
|
|
8572
|
+
className: `code-view${compactHeaders ? " compact-file-headers" : ""}`,
|
|
8573
|
+
containerRef: setCodeViewElement,
|
|
7847
8574
|
disableWorkerPool,
|
|
7848
|
-
|
|
8575
|
+
editorOptions: codeEditing.editorOptions,
|
|
8576
|
+
items: codeEditing.items,
|
|
8577
|
+
onItemEditChange: codeEditing.onItemEditChange,
|
|
8578
|
+
onItemEditComplete: codeEditing.onItemEditComplete,
|
|
7849
8579
|
onScroll: handleScroll,
|
|
7850
8580
|
onSelectedLinesChange: setCodeViewSelectedLines,
|
|
7851
8581
|
options: codeViewOptions,
|
|
@@ -7853,14 +8583,20 @@ function ReviewCodeView({ activeSearchMatch, agentId, agentLabel, allowViewedTog
|
|
|
7853
8583
|
renderAnnotation,
|
|
7854
8584
|
renderCodeViewHeader: sourceDescriptionItemId ? renderCodeViewHeader : void 0,
|
|
7855
8585
|
renderCustomHeader,
|
|
7856
|
-
selectedLines: isReadOnly ? null : selectedLines
|
|
7857
|
-
|
|
8586
|
+
selectedLines: isReadOnly ? null : selectedLines,
|
|
8587
|
+
style: codeViewStyle
|
|
8588
|
+
});
|
|
8589
|
+
const renderedCodeView = disableWorkerPool ? codeView : /* @__PURE__ */ jsx(WorkerPoolContextProvider, {
|
|
7858
8590
|
highlighterOptions: workerHighlighterOptions,
|
|
7859
8591
|
poolOptions: workerPoolOptions,
|
|
7860
8592
|
children: /* @__PURE__ */ jsx(CodeView, {
|
|
7861
|
-
className:
|
|
8593
|
+
className: `code-view${compactHeaders ? " compact-file-headers" : ""}`,
|
|
8594
|
+
containerRef: setCodeViewElement,
|
|
7862
8595
|
disableWorkerPool: false,
|
|
7863
|
-
|
|
8596
|
+
editorOptions: codeEditing.editorOptions,
|
|
8597
|
+
items: codeEditing.items,
|
|
8598
|
+
onItemEditChange: codeEditing.onItemEditChange,
|
|
8599
|
+
onItemEditComplete: codeEditing.onItemEditComplete,
|
|
7864
8600
|
onScroll: handleScroll,
|
|
7865
8601
|
onSelectedLinesChange: setCodeViewSelectedLines,
|
|
7866
8602
|
options: codeViewOptions,
|
|
@@ -7868,8 +8604,13 @@ function ReviewCodeView({ activeSearchMatch, agentId, agentLabel, allowViewedTog
|
|
|
7868
8604
|
renderAnnotation,
|
|
7869
8605
|
renderCodeViewHeader: sourceDescriptionItemId ? renderCodeViewHeader : void 0,
|
|
7870
8606
|
renderCustomHeader,
|
|
7871
|
-
selectedLines: isReadOnly ? null : selectedLines
|
|
8607
|
+
selectedLines: isReadOnly ? null : selectedLines,
|
|
8608
|
+
style: codeViewStyle
|
|
7872
8609
|
})
|
|
8610
|
+
});
|
|
8611
|
+
return /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(EditProvider, {
|
|
8612
|
+
createEditor: createCodeEditor,
|
|
8613
|
+
children: renderedCodeView
|
|
7873
8614
|
}), definitionLookup?.sourceKey === sourceKey && onOpenDefinition ? /* @__PURE__ */ jsx(DefinitionPopover, {
|
|
7874
8615
|
anchor: definitionLookup.anchor,
|
|
7875
8616
|
getDestination: (candidate) => getDefinitionDiffTarget(candidate) ? "diff" : candidate.canOpenInEditor ? "editor" : "unavailable",
|
|
@@ -9586,54 +10327,6 @@ function useReviewFileState({ initialSelectedPath = null, onViewedChange } = {})
|
|
|
9586
10327
|
};
|
|
9587
10328
|
}
|
|
9588
10329
|
//#endregion
|
|
9589
|
-
//#region config/defaults.ts
|
|
9590
|
-
const defaultConfigTemplate = {
|
|
9591
|
-
settings: {
|
|
9592
|
-
"agentBackend": "codex",
|
|
9593
|
-
"checkForUpdates": true,
|
|
9594
|
-
"claudeModel": "claude-sonnet-4-6",
|
|
9595
|
-
"codeFontFamily": "",
|
|
9596
|
-
"codeFontSize": 13,
|
|
9597
|
-
"copyCommentsOnClose": false,
|
|
9598
|
-
"diffStyle": "split",
|
|
9599
|
-
"editorCommand": "",
|
|
9600
|
-
"lastRepositoryPath": "",
|
|
9601
|
-
"openAIModel": "gpt-5.6-terra",
|
|
9602
|
-
"opencodeModel": "opencode-default",
|
|
9603
|
-
"piModel": "pi-default",
|
|
9604
|
-
"reviewCommentsPrefix": "# Address these Review Comments",
|
|
9605
|
-
"sidebarPosition": "left",
|
|
9606
|
-
"showOutdated": false,
|
|
9607
|
-
"showWhitespace": false,
|
|
9608
|
-
"theme": "system",
|
|
9609
|
-
"walkthroughPrompt": "",
|
|
9610
|
-
"wordWrap": false
|
|
9611
|
-
},
|
|
9612
|
-
keymap: {
|
|
9613
|
-
"askAgent": "Mod+Alt+Enter",
|
|
9614
|
-
"closeSearch": "Escape",
|
|
9615
|
-
"commandBar": "Mod+k",
|
|
9616
|
-
"diffSearch": "Mod+f",
|
|
9617
|
-
"discardComment": "Escape",
|
|
9618
|
-
"fileFilter": "Mod+p",
|
|
9619
|
-
"nextHunk": ["Ctrl+ArrowDown", "j"],
|
|
9620
|
-
"nextSearchMatch": "Enter",
|
|
9621
|
-
"openFile": "Mod+Shift+o",
|
|
9622
|
-
"prevHunk": ["Ctrl+ArrowUp", "k"],
|
|
9623
|
-
"prevSearchMatch": "Shift+Enter",
|
|
9624
|
-
"shortcutsHelp": "Shift+?",
|
|
9625
|
-
"submitComment": "Mod+Enter",
|
|
9626
|
-
"toggleSidebar": "Mod+Shift+b",
|
|
9627
|
-
"toggleWordWrap": "Alt+z"
|
|
9628
|
-
}
|
|
9629
|
-
};
|
|
9630
|
-
const createDefaultConfig = () => ({
|
|
9631
|
-
keymap: { ...defaultConfigTemplate.keymap },
|
|
9632
|
-
settings: { ...defaultConfigTemplate.settings }
|
|
9633
|
-
});
|
|
9634
|
-
Object.freeze({ ...defaultConfigTemplate.keymap });
|
|
9635
|
-
Object.freeze({ ...defaultConfigTemplate.settings });
|
|
9636
|
-
//#endregion
|
|
9637
10330
|
//#region lib/app-constants.ts
|
|
9638
10331
|
const AGENT_LABELS = {
|
|
9639
10332
|
claude: "Claude Code",
|