@pi-chamber/web 0.3.1 → 0.3.2
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/bin/lib/cli-startup.js +53 -10
- package/bin/lib/cli-startup.test.js +42 -0
- package/dist/assets/{CommitSection-C336377Z.js → CommitSection-DLIvjYbM.js} +1 -1
- package/dist/assets/{DiagramEditor-gHLCXHtr.js → DiagramEditor-Tw3ZWHML.js} +1 -1
- package/dist/assets/{DiagramView-DlHzRRBc.js → DiagramView-CK6R7taL.js} +1 -1
- package/dist/assets/{DiffView-5wHwK-lg.js → DiffView-vrxi5oWp.js} +2 -2
- package/dist/assets/{FilesView-5bswI3JZ.js → FilesView-BD_h3EVr.js} +6 -6
- package/dist/assets/{GitView-BfykGpGh.js → GitView-BwNKqK0K.js} +4 -4
- package/dist/assets/{JsonTreeView-HVwQS7qG.js → JsonTreeView-CmY7QgEX.js} +1 -1
- package/dist/assets/{MarkdownRendererImpl-kjd4e0N8.js → MarkdownRendererImpl-CpI-25Xk.js} +1 -1
- package/dist/assets/{PatchDiff-Dlm4RU8n.js → PatchDiff-CrIWbYj7.js} +1 -1
- package/dist/assets/{PierreDiffViewer-St32rXlD.js → PierreDiffViewer-B410mdbq.js} +2 -2
- package/dist/assets/{SessionSwitcherDropdown-D5bWfZNA.js → SessionSwitcherDropdown-DROjbyIu.js} +93 -93
- package/dist/assets/SettingsView-CsJItYZh.js +4 -0
- package/dist/assets/{SettingsWindow-Ck_uhTnx.js → SettingsWindow-C9s4AX72.js} +1 -1
- package/dist/assets/{ToolOutputDialog-BCONUv3r.js → ToolOutputDialog-b_R4tAZu.js} +6 -6
- package/dist/assets/{ToolPartDiffPreview-BdVuk2kc.js → ToolPartDiffPreview-CfnliaE9.js} +1 -1
- package/dist/assets/{VirtualizedFileDiff-BsAZM0jo.js → VirtualizedFileDiff-CQz2fSZI.js} +4 -4
- package/dist/assets/{collapsible-Wnmq-13H.js → collapsible-CR4U9tjw.js} +1 -1
- package/dist/assets/{computeVirtualFileMetrics-skbyL2Az.js → computeVirtualFileMetrics-C7vXPUYT.js} +2 -2
- package/dist/assets/{contextFileOpenGuard-BsxQITMZ.js → contextFileOpenGuard-DtTHRnq1.js} +1 -1
- package/dist/assets/{index-8TL2HlaR.js → index-BAqpUCjs.js} +4 -4
- package/dist/assets/{index-Bfp6eYap.js → index-DZG82DE1.js} +1 -1
- package/dist/assets/{isDiffPlainText-dZkfk3yG.js → isDiffPlainText-zTq-4A04.js} +1 -1
- package/dist/assets/{isFilePlainText-UL_tMQZx.js → isFilePlainText-CLgIdzE5.js} +1 -1
- package/dist/assets/{main-CHQfoyRP.js → main-BVWtJYSk.js} +2 -2
- package/dist/assets/main-DXYHsqzA.js +133 -0
- package/dist/assets/{markdownCore-qX3mJFkL.js → markdownCore-CN0pApQE.js} +2 -2
- package/dist/assets/{miniChat-3QtCNwHl.js → miniChat-BrbRq5NQ.js} +2 -2
- package/dist/assets/{mobile-B_CyfRAX.js → mobile-DTPtCn5N.js} +2 -2
- package/dist/assets/{renderElectronMiniChatApp-OToslrv-.js → renderElectronMiniChatApp-CM8qBaye.js} +1 -1
- package/dist/assets/{renderMobileApp-BD_wep_I.js → renderMobileApp-KS_pt-qc.js} +4 -4
- package/dist/assets/{runtimeSurface-CkdOpqo7.js → runtimeSurface-CkHYYg0E.js} +1 -1
- package/dist/assets/{useInlineCommentController-DVif5Fr8.js → useInlineCommentController-CwNNjgc7.js} +2 -2
- package/dist/assets/usePanelSlide-DkorgQJ5.js +56 -0
- package/dist/assets/{useWindowTitle-BZVlLMCy.js → useWindowTitle-B9wt_3ZQ.js} +3 -3
- package/dist/assets/{vendor-codemirror-language-data-C-924Z4o.js → vendor-codemirror-language-data-x89A7Wy0.js} +2 -2
- package/dist/assets/{web-components-BG-6PEN4.js → web-components-BEPfE4kU.js} +4 -4
- package/dist/index.html +3 -3
- package/dist/mini-chat.html +2 -2
- package/dist/mobile.html +2 -2
- package/package.json +1 -1
- package/server/index.js +33 -0
- package/server/lib/pi/routes.js +5 -1
- package/server/lib/pi/session-daemon/DOCUMENTATION.md +1 -1
- package/server/lib/pi/session-daemon/session-daemon.js +111 -9
- package/server/lib/pi/session-daemon/session-daemon.test.js +75 -0
- package/server/lib/pi/settings-store.js +17 -0
- package/server/lib/pi/settings-store.test.js +33 -0
- package/server/lib/server/core-routes.js +36 -4
- package/server/lib/server/tunnel-service.DOCUMENTATION.md +74 -0
- package/server/lib/server/tunnel-service.js +228 -0
- package/server/lib/server/tunnel-service.test.js +61 -0
- package/server/lib/ui-auth/DOCUMENTATION.md +2 -0
- package/server/lib/ui-auth/ui-auth.js +5 -1
- package/server/lib/ui-auth/ui-auth.test.js +17 -0
- package/dist/assets/SettingsView-FGe5TEQq.js +0 -4
- package/dist/assets/main-DbnYXZeK.js +0 -133
- package/dist/assets/usePanelSlide-C_PJmPXW.js +0 -56
package/bin/lib/cli-startup.js
CHANGED
|
@@ -9,6 +9,8 @@ import { assertAuthenticatedNetworkExposure, hasUiPasswordConfigured, resolveSer
|
|
|
9
9
|
|
|
10
10
|
const STARTUP_SERVICE_ID = 'dev.pichamber.web';
|
|
11
11
|
|
|
12
|
+
const isRootUser = () => typeof process.getuid === 'function' && process.getuid() === 0;
|
|
13
|
+
|
|
12
14
|
function getStartupServicePaths() {
|
|
13
15
|
if (process.platform === 'darwin') {
|
|
14
16
|
return {
|
|
@@ -17,9 +19,17 @@ function getStartupServicePaths() {
|
|
|
17
19
|
};
|
|
18
20
|
}
|
|
19
21
|
if (process.platform === 'linux') {
|
|
22
|
+
if (isRootUser()) {
|
|
23
|
+
return {
|
|
24
|
+
platform: 'linux',
|
|
25
|
+
servicePath: '/etc/systemd/system/pichamber.service',
|
|
26
|
+
scope: 'system',
|
|
27
|
+
};
|
|
28
|
+
}
|
|
20
29
|
return {
|
|
21
30
|
platform: 'linux',
|
|
22
31
|
servicePath: path.join(os.homedir(), '.config', 'systemd', 'user', 'pichamber.service'),
|
|
32
|
+
scope: 'user',
|
|
23
33
|
};
|
|
24
34
|
}
|
|
25
35
|
if (process.platform === 'win32') {
|
|
@@ -169,13 +179,22 @@ function resolveCliEntrypoint() {
|
|
|
169
179
|
|
|
170
180
|
function isUserStartupServiceActive() {
|
|
171
181
|
if (process.platform !== 'linux') return false;
|
|
182
|
+
if (isRootUser()) {
|
|
183
|
+
const result = runStartupCommand('systemctl', ['is-active', 'pichamber.service'], { allowFailure: true });
|
|
184
|
+
return (result.stdout || '').trim() === 'active';
|
|
185
|
+
}
|
|
172
186
|
const result = runStartupCommand('systemctl', ['--user', 'is-active', 'pichamber.service'], { allowFailure: true });
|
|
173
187
|
return (result.stdout || '').trim() === 'active';
|
|
174
188
|
}
|
|
175
189
|
|
|
176
190
|
function restartUserStartupService() {
|
|
177
191
|
if (process.platform !== 'linux') {
|
|
178
|
-
throw new Error('Startup service restart is only supported on Linux systemd
|
|
192
|
+
throw new Error('Startup service restart is only supported on Linux systemd units.');
|
|
193
|
+
}
|
|
194
|
+
if (isRootUser()) {
|
|
195
|
+
runStartupCommand('systemctl', ['daemon-reload']);
|
|
196
|
+
runStartupCommand('systemctl', ['restart', 'pichamber.service']);
|
|
197
|
+
return;
|
|
179
198
|
}
|
|
180
199
|
runStartupCommand('systemctl', ['--user', 'daemon-reload']);
|
|
181
200
|
runStartupCommand('systemctl', ['--user', 'restart', 'pichamber.service']);
|
|
@@ -258,6 +277,9 @@ ${envXml} <key>ProcessType</key>
|
|
|
258
277
|
function buildSystemdUserService(options = {}) {
|
|
259
278
|
const args = buildStartupArgs(options).map((arg) => `"${systemdEscapeArg(arg)}"`).join(' ');
|
|
260
279
|
const envFilePath = getStartupEnvFilePath();
|
|
280
|
+
const isRoot = isRootUser();
|
|
281
|
+
const wantedBy = isRoot ? 'multi-user.target' : 'default.target';
|
|
282
|
+
const workingDir = isRoot ? systemdUnitPath('/root') : systemdUnitPath(os.homedir());
|
|
261
283
|
return `[Unit]
|
|
262
284
|
Description=PiChamber web server
|
|
263
285
|
After=network-online.target
|
|
@@ -266,15 +288,19 @@ After=network-online.target
|
|
|
266
288
|
Type=simple
|
|
267
289
|
EnvironmentFile=-${systemdEscapeArg(envFilePath)}
|
|
268
290
|
ExecStart="${systemdEscapeArg(process.execPath)}" ${args}
|
|
269
|
-
WorkingDirectory=${
|
|
291
|
+
WorkingDirectory=${workingDir}
|
|
270
292
|
Restart=always
|
|
271
293
|
RestartSec=5
|
|
272
294
|
|
|
273
295
|
[Install]
|
|
274
|
-
WantedBy
|
|
296
|
+
WantedBy=${wantedBy}
|
|
275
297
|
`;
|
|
276
298
|
}
|
|
277
299
|
|
|
300
|
+
function buildSystemdService(options = {}) {
|
|
301
|
+
return buildSystemdUserService(options);
|
|
302
|
+
}
|
|
303
|
+
|
|
278
304
|
function runStartupCommand(command, args, options = {}) {
|
|
279
305
|
const result = spawnSync(command, args, {
|
|
280
306
|
encoding: 'utf8',
|
|
@@ -301,8 +327,11 @@ function getStartupStatus() {
|
|
|
301
327
|
return { supported: true, platform: paths.platform, enabled: result.status === 0, active: null, servicePath: paths.servicePath };
|
|
302
328
|
}
|
|
303
329
|
if (paths.platform === 'linux') {
|
|
304
|
-
const
|
|
305
|
-
const
|
|
330
|
+
const isRoot = isRootUser();
|
|
331
|
+
const enabledArgs = isRoot ? ['is-enabled', 'pichamber.service'] : ['--user', 'is-enabled', 'pichamber.service'];
|
|
332
|
+
const activeArgs = isRoot ? ['is-active', 'pichamber.service'] : ['--user', 'is-active', 'pichamber.service'];
|
|
333
|
+
const enabledResult = runStartupCommand('systemctl', enabledArgs, { allowFailure: true });
|
|
334
|
+
const activeResult = runStartupCommand('systemctl', activeArgs, { allowFailure: true });
|
|
306
335
|
const activeState = (activeResult.stdout || '').trim() || 'inactive';
|
|
307
336
|
return {
|
|
308
337
|
supported: true,
|
|
@@ -311,6 +340,7 @@ function getStartupStatus() {
|
|
|
311
340
|
active: activeState === 'active',
|
|
312
341
|
activeState,
|
|
313
342
|
servicePath: paths.servicePath,
|
|
343
|
+
scope: isRoot ? 'system' : 'user',
|
|
314
344
|
};
|
|
315
345
|
}
|
|
316
346
|
return {
|
|
@@ -355,11 +385,17 @@ function enableStartupService(options = {}) {
|
|
|
355
385
|
}
|
|
356
386
|
|
|
357
387
|
if (paths.platform === 'linux') {
|
|
388
|
+
const isRoot = isRootUser();
|
|
358
389
|
writeStartupEnvFile(serveOptions, { quoteValue: systemdEnvFileQuote });
|
|
359
390
|
fs.mkdirSync(path.dirname(paths.servicePath), { recursive: true, mode: 0o700 });
|
|
360
391
|
fs.writeFileSync(paths.servicePath, buildSystemdUserService(serveOptions), { mode: 0o600 });
|
|
361
|
-
|
|
362
|
-
|
|
392
|
+
if (isRoot) {
|
|
393
|
+
runStartupCommand('systemctl', ['daemon-reload']);
|
|
394
|
+
runStartupCommand('systemctl', ['enable', '--now', 'pichamber.service']);
|
|
395
|
+
} else {
|
|
396
|
+
runStartupCommand('systemctl', ['--user', 'daemon-reload']);
|
|
397
|
+
runStartupCommand('systemctl', ['--user', 'enable', '--now', 'pichamber.service']);
|
|
398
|
+
}
|
|
363
399
|
return finish(getStartupStatus());
|
|
364
400
|
}
|
|
365
401
|
|
|
@@ -396,9 +432,16 @@ function disableStartupService() {
|
|
|
396
432
|
}
|
|
397
433
|
|
|
398
434
|
if (paths.platform === 'linux') {
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
435
|
+
const isRoot = isRootUser();
|
|
436
|
+
if (isRoot) {
|
|
437
|
+
runStartupCommand('systemctl', ['disable', '--now', 'pichamber.service'], { allowFailure: true });
|
|
438
|
+
try { fs.unlinkSync(paths.servicePath); } catch {}
|
|
439
|
+
runStartupCommand('systemctl', ['daemon-reload'], { allowFailure: true });
|
|
440
|
+
} else {
|
|
441
|
+
runStartupCommand('systemctl', ['--user', 'disable', '--now', 'pichamber.service'], { allowFailure: true });
|
|
442
|
+
try { fs.unlinkSync(paths.servicePath); } catch {}
|
|
443
|
+
runStartupCommand('systemctl', ['--user', 'daemon-reload'], { allowFailure: true });
|
|
444
|
+
}
|
|
402
445
|
return getStartupStatus();
|
|
403
446
|
}
|
|
404
447
|
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { describe, expect, it, vi, beforeEach, afterEach } from 'vitest';
|
|
2
|
+
import fs from 'node:fs';
|
|
3
|
+
import os from 'node:os';
|
|
4
|
+
import path from 'node:path';
|
|
5
|
+
import { mkdtempSync, rmSync } from 'node:fs';
|
|
6
|
+
|
|
7
|
+
describe('startup service paths', () => {
|
|
8
|
+
const originalPlatform = process.platform;
|
|
9
|
+
const originalGetuid = process.getuid;
|
|
10
|
+
let tmpHome;
|
|
11
|
+
|
|
12
|
+
beforeEach(() => {
|
|
13
|
+
tmpHome = mkdtempSync(path.join(os.tmpdir(), 'pichamber-startup-test-'));
|
|
14
|
+
vi.stubEnv('HOME', tmpHome);
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
afterEach(() => {
|
|
18
|
+
rmSync(tmpHome, { recursive: true, force: true });
|
|
19
|
+
vi.unstubAllEnvs();
|
|
20
|
+
if (originalGetuid) process.getuid = originalGetuid;
|
|
21
|
+
else delete process.getuid;
|
|
22
|
+
Object.defineProperty(process, 'platform', { value: originalPlatform });
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
it('uses user service path for non-root', async () => {
|
|
26
|
+
Object.defineProperty(process, 'platform', { value: 'linux' });
|
|
27
|
+
process.getuid = () => 1000;
|
|
28
|
+
const { getStartupServicePaths } = await import('./cli-startup.js?user');
|
|
29
|
+
const result = getStartupServicePaths();
|
|
30
|
+
expect(result.servicePath).toContain('.config/systemd/user/pichamber.service');
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
it('uses system service path for root', async () => {
|
|
34
|
+
Object.defineProperty(process, 'platform', { value: 'linux' });
|
|
35
|
+
process.getuid = () => 0;
|
|
36
|
+
// Need to re-import fresh module to pick up new getuid
|
|
37
|
+
vi.resetModules();
|
|
38
|
+
const { getStartupServicePaths } = await import('./cli-startup.js?root');
|
|
39
|
+
const result = getStartupServicePaths();
|
|
40
|
+
expect(result.servicePath).toBe('/etc/systemd/system/pichamber.service');
|
|
41
|
+
});
|
|
42
|
+
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{R as C,j as e}from"./vendor-react-DYyjh7Q0.js";import{f as z,T as y,q as _,B as c,I as a,s as v,
|
|
1
|
+
import{R as C,j as e}from"./vendor-react-DYyjh7Q0.js";import{f as z,T as y,q as _,B as c,I as a,s as v,aQ as I}from"./SessionSwitcherDropdown-DROjbyIu.js";import{u as H}from"./index-BAqpUCjs.js";const N=38,h=200,k=({value:t,onChange:o,placeholder:m,disabled:i=!1,hasTouchInput:r=!1,isMobile:u=!1})=>{const n=C.useRef(null),j=H(s=>s.inputSpellcheckEnabled);return C.useLayoutEffect(()=>{const s=n.current;if(!s)return;const l=document.activeElement===s,d=()=>{s.style.height=`${N}px`;const p=s.scrollHeight,x=Math.min(Math.max(p,N),h);s.style.height=`${x}px`,s.style.overflowY=p>h?"auto":"hidden",p>h&&!l&&(s.scrollTop=s.scrollHeight)};d();const f=window.requestAnimationFrame(d);return()=>{window.cancelAnimationFrame(f)}},[t]),e.jsx("textarea",{ref:n,value:t,onChange:s=>o(s.target.value),placeholder:m??"Commit message",rows:1,disabled:i,autoCorrect:r?"on":"off",autoCapitalize:r?"sentences":"off",spellCheck:u||j,className:z("w-full rounded-lg border border-border/60 bg-surface-elevated px-3 py-2 typography-ui-label text-foreground placeholder:text-muted-foreground","resize-none outline-none transition-[border-color,box-shadow] duration-150","focus-visible:ring-2 focus-visible:ring-[var(--interactive-focus-ring)]",i&&"opacity-50"),style:{minHeight:N,maxHeight:h}})},F=({highlights:t,onInsert:o})=>{if(t.length===0)return null;const m=()=>{o(t)};return e.jsxs("div",{className:"space-y-2 rounded-xl border border-border/60 bg-transparent px-3 py-2",children:[e.jsxs("div",{className:"flex items-center justify-between gap-2",children:[e.jsx("p",{className:"typography-micro text-muted-foreground",children:"Highlights"}),e.jsxs(y,{children:[e.jsx(_,{asChild:!0,children:e.jsx(c,{variant:"ghost",size:"icon",className:"size-6",onClick:m,"aria-label":"Insert aria label",children:e.jsx(a,{name:"arrow-down",className:"size-4"})})}),e.jsx(v,{sideOffset:8,children:"Insert tooltip"})]})]}),e.jsx("ul",{className:"space-y-1",children:t.map((i,r)=>e.jsx("li",{className:"typography-meta text-foreground",children:i},`${i}-${r}`))})]})},q=({stagedCount:t,commitMessage:o,onCommitMessageChange:m,generatedHighlights:i,onInsertHighlights:r,onGenerateMessage:u,isGeneratingMessage:n,onCommit:j,onCommitAndPush:s,commitAction:l,hasPendingIndexMutation:d=!1,gitmojiEnabled:f,onOpenGitmojiPicker:p})=>{const x=t>0,b=o.trim()&&x&&l===null&&!d,{isMobile:g,hasTouchInput:w}=I();return e.jsxs("section",{className:"border-0 bg-transparent rounded-none",children:[e.jsxs("div",{className:"flex w-full items-baseline gap-2 px-0 pt-2 pb-1",children:[e.jsx("h3",{className:"typography-ui-header font-semibold text-foreground",children:"Commit"}),x?null:e.jsx("span",{className:"min-w-0 truncate typography-meta text-muted-foreground",children:"Stage files to enable commit."})]}),e.jsxs("div",{className:"flex flex-col gap-3 px-0 pt-1 pb-3",children:[e.jsx(F,{highlights:i,onInsert:r}),e.jsx(k,{value:o,onChange:m,placeholder:"Commit message",disabled:l!==null,hasTouchInput:w,isMobile:g}),f&&e.jsxs(c,{variant:"outline",size:"sm",onClick:p,className:"w-fit",type:"button",children:[e.jsx(a,{name:"emotion-happy",className:"size-4"}),"Add gitmoji"]}),e.jsxs("div",{className:"@container/commit-actions flex items-center gap-2 min-w-0",children:[e.jsxs(c,{variant:"outline",size:"sm",onClick:u,disabled:n||l!==null||d||t===0,type:"button","aria-label":"Generate commit message",className:"commit-actions__btn",children:[n?e.jsx(a,{name:"loader-4",className:"size-4 animate-spin"}):e.jsx(a,{name:"ai-generate-2",className:"size-4 text-primary"}),e.jsx("span",{className:"commit-actions__label",children:"Generate"})]}),e.jsx("div",{className:"flex-1"}),e.jsx(c,{size:"sm",variant:"outline",onClick:j,disabled:!b||n,className:"commit-actions__btn whitespace-nowrap","aria-label":"Commit aria label",children:l==="commit"?e.jsxs(e.Fragment,{children:[e.jsx(a,{name:"loader-4",className:"size-4 animate-spin"}),e.jsx("span",{className:"commit-actions__label",children:"Committing..."})]}):e.jsxs(e.Fragment,{children:[e.jsx(a,{name:"git-commit",className:"size-4"}),e.jsx("span",{className:"commit-actions__label",children:"Commit"})]})}),g?e.jsxs(y,{children:[e.jsx(_,{asChild:!0,children:e.jsx(c,{variant:"default",size:"sm",onClick:()=>s(),disabled:!b||n,className:"h-7 w-7 p-0","aria-label":"Commit and sync",children:l==="commitAndPush"?e.jsx(a,{name:"loader-4",className:"size-4 animate-spin"}):e.jsx(a,{name:"arrow-up",className:"size-3.5"})})}),e.jsx(v,{side:"top",children:e.jsx("p",{children:"Commit & sync"})})]}):e.jsx(c,{size:"sm",variant:"default",onClick:()=>s(),disabled:!b||n,className:"commit-actions__btn","aria-label":"Commit and sync",children:l==="commitAndPush"?e.jsxs(e.Fragment,{children:[e.jsx(a,{name:"loader-4",className:"size-4 animate-spin"}),e.jsx("span",{className:"commit-actions__label commit-actions__label--push",children:"Syncing..."})]}):e.jsxs(e.Fragment,{children:[e.jsx(a,{name:"arrow-up",className:"size-3.5"}),e.jsx("span",{className:"commit-actions__label commit-actions__label--push",children:"Commit & sync"})]})})]})]})]})};export{q as C};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{R as e,j as h}from"./vendor-react-DYyjh7Q0.js";import{D as E}from"./vendor-react-drawio-Boqanm0j.js";import{f as x}from"./SessionSwitcherDropdown-
|
|
1
|
+
import{R as e,j as h}from"./vendor-react-DYyjh7Q0.js";import{D as E}from"./vendor-react-drawio-Boqanm0j.js";import{f as x}from"./SessionSwitcherDropdown-DROjbyIu.js";const D='<mxfile><diagram id="new" name="Page-1"><mxGraphModel dx="0" dy="0" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0"><root><mxCell id="0"/><mxCell id="1" parent="0"/></root></mxGraphModel></diagram></mxfile>';function g(){if(typeof document>"u")return!1;const o=document.documentElement.getAttribute("data-theme");return o==="dark"||!o&&window.matchMedia("(prefers-color-scheme: dark)").matches}const X=e.forwardRef(function({xml:t,readOnly:a,className:R,onChange:c},v){const s=e.useRef(t),i=e.useRef(null),m=e.useRef(!1),[n,k]=e.useState(g),u=e.useRef(t),d=e.useRef(t);d.current!==t&&(d.current=t,u.current=t,s.current=t);const f=e.useRef(n);f.current!==n&&(f.current=n,u.current=s.current);const l=e.useRef(null);e.useEffect(()=>{const r=()=>k(g());r();const p=new MutationObserver(r);return p.observe(document.documentElement,{attributes:!0,attributeFilter:["data-theme"]}),()=>p.disconnect()},[]),e.useEffect(()=>{const r=setTimeout(()=>{l.current?.querySelector(".diagrams-iframe")?.focus()},600);return()=>clearTimeout(r)},[]),e.useImperativeHandle(v,()=>({getXml:()=>s.current}));const b=e.useCallback(()=>{!t&&!m.current&&(m.current=!0,setTimeout(()=>{i.current?.template({})},500))},[t]),w=e.useCallback(r=>{s.current=r.xml,c?.(r.xml)},[c]);return h.jsx("div",{ref:l,className:x("h-full w-full",R),children:h.jsx(E,{ref:i,xml:u.current||D,autosave:!0,urlParameters:{ui:a?"simple":n?"dark":"kennedy",spin:!0,libraries:!a,chrome:a,nav:a,layers:a,noSaveBtn:!0,noExitBtn:!0,saveAndExit:!1},onLoad:b,onAutoSave:w},n?"dark":"light")})});export{X as D};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{R as r,j as t}from"./vendor-react-DYyjh7Q0.js";import{u as a}from"./index-
|
|
1
|
+
import{R as r,j as t}from"./vendor-react-DYyjh7Q0.js";import{u as a}from"./index-BAqpUCjs.js";import{C as v,I as m}from"./SessionSwitcherDropdown-DROjbyIu.js";import{D as j}from"./DiagramEditor-Tw3ZWHML.js";import"./vendor-scheduler-7OC5HNn7.js";import"./vendor-zustand-CnsBKjP5.js";import"./vendor-simplewebauthn-browser-VDA66rT_.js";import"./vendor-vite-runtime-DD1OZmLC.js";import"./vendor-base-ui-DL8r2fgQ.js";import"./vendor-floating-ui-utils-BzXdqYpP.js";import"./vendor-floating-ui-react-dom-sVFnuruh.js";import"./vendor-floating-ui-dom-Bkw82kL9.js";import"./vendor-floating-ui-core-CXmKXOXc.js";import"./vendor-use-sync-external-store-B7OScDIw.js";import"./runtimeSurface-CkHYYg0E.js";import"./vendor-dnd-kit-core-GipZW2tY.js";import"./vendor-dnd-kit-utilities-CrOcp0Bp.js";import"./vendor-dnd-kit-accessibility-Cv52zwWT.js";import"./vendor-dnd-kit-sortable-Ct2QxIHb.js";import"./vendor-cmdk-BCEUzcHE.js";import"./vendor-radix-ui-react-dialog-jX3Dld8c.js";import"./vendor-radix-ui-primitive-Dc_FVRD7.js";import"./vendor-radix-ui-react-compose-refs-D1GnwnP9.js";import"./vendor-radix-ui-react-context-CM4yFQ2I.js";import"./vendor-radix-ui-react-id-BcxRjnbX.js";import"./vendor-radix-ui-react-use-layout-effect-0fyGwS2_.js";import"./vendor-radix-ui-react-use-controllable-state-C_ecoh35.js";import"./vendor-radix-ui-react-dismissable-layer-M7LsH3yL.js";import"./vendor-radix-ui-react-primitive-CfpW6_IT.js";import"./vendor-radix-ui-react-slot-BxUc3Pvz.js";import"./vendor-radix-ui-react-use-callback-ref-UKEWHtoP.js";import"./vendor-radix-ui-react-use-escape-keydown-Co13lHGj.js";import"./vendor-radix-ui-react-focus-scope-C2K7lNPv.js";import"./vendor-radix-ui-react-portal-xlJWBfDg.js";import"./vendor-radix-ui-react-presence-Btn-Dp7L.js";import"./vendor-radix-ui-react-focus-guards-D5MZ0nQs.js";import"./vendor-react-remove-scroll-CfeMe0DL.js";import"./vendor-tslib-De9GV7Vy.js";import"./vendor-react-remove-scroll-bar-C9YRs2nU.js";import"./vendor-react-style-singleton-B1H4bWSG.js";import"./vendor-get-nonce-C-Z93AgS.js";import"./vendor-use-sidecar-C-AuTczP.js";import"./vendor-use-callback-ref-CJB0R85I.js";import"./vendor-aria-hidden-DvXkyWUv.js";import"./vendor-codemirror-language-E2vgV9K3.js";import"./vendor-lezer-common-B3-cUCR_.js";import"./vendor-codemirror-state-CNWM3Q8V.js";import"./vendor-marijn-find-cluster-break-DXwl3gUT.js";import"./vendor-codemirror-view-DSzLbZiS.js";import"./vendor-style-mod-NZ5MEPvj.js";import"./vendor-w3c-keyname-Vcq4gwWv.js";import"./vendor-crelt-C8TCjufn.js";import"./vendor-lezer-highlight-CDMHUZ74.js";import"./vendor-codemirror-lang-javascript-BUlYhQ3o.js";import"./vendor-lezer-javascript-D7Tj24ot.js";import"./vendor-lezer-lr-bhwg1HMg.js";import"./vendor-codemirror-autocomplete-BS2SpSAZ.js";import"./vendor-codemirror-lang-json-CqayksDf.js";import"./vendor-lezer-json-Iaex0UN-.js";import"./vendor-codemirror-lang-css-Ba8JZ6fp.js";import"./vendor-lezer-css-C5xB6jxd.js";import"./vendor-codemirror-lang-html-DK27qQri.js";import"./vendor-lezer-html-C0I1p52t.js";import"./vendor-codemirror-lang-markdown-CvO36Y1p.js";import"./vendor-lezer-markdown-C6g-d6P3.js";import"./vendor-codemirror-language-data-x89A7Wy0.js";import"./vendor-codemirror-lang-python-_2bIYTiJ.js";import"./vendor-lezer-python-CvuFxeZl.js";import"./vendor-codemirror-commands-RrgJ8H_6.js";import"./vendor-class-variance-authority-5VPnzWs2.js";import"./vendor-clsx-B-dksMZM.js";import"./vendor-tanstack-react-virtual-IrbCBGJ4.js";import"./vendor-tanstack-virtual-core-Dubg10g5.js";import"./vendor-framer-motion-DJASDzNt.js";import"./vendor-motion-dom-DJLgZh4Q.js";import"./vendor-motion-utils-BGh8QBgx.js";import"./vendor-sonner-CW8w438f.js";import"./vendor-tailwind-merge-CPcsbTWB.js";import"./vendor-fuse.js-Dw8P0qyA.js";import"./vendor-react-drawio-Boqanm0j.js";function Kt(){const{files:o}=v(),[e,d]=r.useState(null),[s,p]=r.useState(""),[x,n]=r.useState(!0),l=r.useRef(null),c=a(i=>i.pendingDiagramFile),u=r.useCallback(async i=>{n(!0),d(i);try{const f=await o?.readFile?.(i);f&&p(f.content)}catch{p("")}finally{n(!1)}},[o]);r.useEffect(()=>{if(!c)return;const i=a.getState().consumePendingDiagramFile();i&&u(i)},[u,c]);const g=r.useCallback(async()=>{const i=l.current?.getXml();e&&o?.writeFile&&i&&i!==s&&(await o.writeFile(e,i),p(i))},[e,o,s]),h=e?e.split("/").pop()||e:"";return e?x?t.jsx("div",{className:"flex h-full items-center justify-center p-3",children:t.jsx(m,{name:"loader-4",className:"size-4 animate-spin"})}):t.jsxs("div",{className:"flex h-full flex-col",children:[t.jsxs("div",{className:"flex items-center gap-2 border-b border-border/30 px-3 py-1.5",children:[t.jsx(m,{name:"file",className:"size-4 shrink-0 text-muted-foreground"}),t.jsx("span",{className:"typography-ui text-muted-foreground truncate flex-1",children:h}),t.jsx("button",{type:"button",onClick:()=>{g()},className:"size-6 flex items-center justify-center rounded-md text-foreground hover:bg-interactive-hover/50 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary",title:"Save diagram",children:t.jsx(m,{name:"save-3",className:"size-4"})}),t.jsx("button",{type:"button",onClick:()=>a.getState().setActiveMainTab("chat"),className:"size-6 flex items-center justify-center rounded-md text-muted-foreground hover:bg-interactive-hover/50 hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary",title:"Close diagram view",children:t.jsx(m,{name:"close",className:"size-4"})})]}),t.jsx("div",{className:"flex-1 min-h-0",children:t.jsx(j,{ref:l,xml:s,className:"h-full"})})]}):t.jsx("div",{className:"flex h-full items-center justify-center p-3",children:t.jsx("div",{className:"typography-ui text-muted-foreground",children:"Pick a file from the tree."})})}export{Kt as DiagramView};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{R as o,j as n}from"./vendor-react-DYyjh7Q0.js";import{u as _,a as ut}from"./index-
|
|
1
|
+
import{R as o,j as n}from"./vendor-react-DYyjh7Q0.js";import{u as _,a as ut}from"./index-BAqpUCjs.js";import{dm as Pt,dn as Wt,dp as Ot,C as dt,E as zt,aQ as Gt,H as Ht,G as Ut,J as Kt,K as J,h as Vt,aC as qt,dq as Xt,dr as Jt,a_ as Qt,W as ve,t as ft,B as Ne,I as A,f as P,T as Yt,q as Zt,s as en,ds as mt,dl as tn,as as nn,at as sn,au as rn,dt as on,du as je,ay as pt,F as ht,V as an}from"./SessionSwitcherDropdown-DROjbyIu.js";import{P as ln}from"./PierreDiffViewer-B410mdbq.js";import{v as cn,g as un}from"./contextFileOpenGuard-DtTHRnq1.js";import{p as dn}from"./VirtualizedFileDiff-CQz2fSZI.js";import"./vendor-scheduler-7OC5HNn7.js";import"./vendor-zustand-CnsBKjP5.js";import"./vendor-simplewebauthn-browser-VDA66rT_.js";import"./vendor-vite-runtime-DD1OZmLC.js";import"./vendor-base-ui-DL8r2fgQ.js";import"./vendor-floating-ui-utils-BzXdqYpP.js";import"./vendor-floating-ui-react-dom-sVFnuruh.js";import"./vendor-floating-ui-dom-Bkw82kL9.js";import"./vendor-floating-ui-core-CXmKXOXc.js";import"./vendor-use-sync-external-store-B7OScDIw.js";import"./runtimeSurface-CkHYYg0E.js";import"./vendor-dnd-kit-core-GipZW2tY.js";import"./vendor-dnd-kit-utilities-CrOcp0Bp.js";import"./vendor-dnd-kit-accessibility-Cv52zwWT.js";import"./vendor-dnd-kit-sortable-Ct2QxIHb.js";import"./vendor-cmdk-BCEUzcHE.js";import"./vendor-radix-ui-react-dialog-jX3Dld8c.js";import"./vendor-radix-ui-primitive-Dc_FVRD7.js";import"./vendor-radix-ui-react-compose-refs-D1GnwnP9.js";import"./vendor-radix-ui-react-context-CM4yFQ2I.js";import"./vendor-radix-ui-react-id-BcxRjnbX.js";import"./vendor-radix-ui-react-use-layout-effect-0fyGwS2_.js";import"./vendor-radix-ui-react-use-controllable-state-C_ecoh35.js";import"./vendor-radix-ui-react-dismissable-layer-M7LsH3yL.js";import"./vendor-radix-ui-react-primitive-CfpW6_IT.js";import"./vendor-radix-ui-react-slot-BxUc3Pvz.js";import"./vendor-radix-ui-react-use-callback-ref-UKEWHtoP.js";import"./vendor-radix-ui-react-use-escape-keydown-Co13lHGj.js";import"./vendor-radix-ui-react-focus-scope-C2K7lNPv.js";import"./vendor-radix-ui-react-portal-xlJWBfDg.js";import"./vendor-radix-ui-react-presence-Btn-Dp7L.js";import"./vendor-radix-ui-react-focus-guards-D5MZ0nQs.js";import"./vendor-react-remove-scroll-CfeMe0DL.js";import"./vendor-tslib-De9GV7Vy.js";import"./vendor-react-remove-scroll-bar-C9YRs2nU.js";import"./vendor-react-style-singleton-B1H4bWSG.js";import"./vendor-get-nonce-C-Z93AgS.js";import"./vendor-use-sidecar-C-AuTczP.js";import"./vendor-use-callback-ref-CJB0R85I.js";import"./vendor-aria-hidden-DvXkyWUv.js";import"./vendor-codemirror-language-E2vgV9K3.js";import"./vendor-lezer-common-B3-cUCR_.js";import"./vendor-codemirror-state-CNWM3Q8V.js";import"./vendor-marijn-find-cluster-break-DXwl3gUT.js";import"./vendor-codemirror-view-DSzLbZiS.js";import"./vendor-style-mod-NZ5MEPvj.js";import"./vendor-w3c-keyname-Vcq4gwWv.js";import"./vendor-crelt-C8TCjufn.js";import"./vendor-lezer-highlight-CDMHUZ74.js";import"./vendor-codemirror-lang-javascript-BUlYhQ3o.js";import"./vendor-lezer-javascript-D7Tj24ot.js";import"./vendor-lezer-lr-bhwg1HMg.js";import"./vendor-codemirror-autocomplete-BS2SpSAZ.js";import"./vendor-codemirror-lang-json-CqayksDf.js";import"./vendor-lezer-json-Iaex0UN-.js";import"./vendor-codemirror-lang-css-Ba8JZ6fp.js";import"./vendor-lezer-css-C5xB6jxd.js";import"./vendor-codemirror-lang-html-DK27qQri.js";import"./vendor-lezer-html-C0I1p52t.js";import"./vendor-codemirror-lang-markdown-CvO36Y1p.js";import"./vendor-lezer-markdown-C6g-d6P3.js";import"./vendor-codemirror-language-data-x89A7Wy0.js";import"./vendor-codemirror-lang-python-_2bIYTiJ.js";import"./vendor-lezer-python-CvuFxeZl.js";import"./vendor-codemirror-commands-RrgJ8H_6.js";import"./vendor-class-variance-authority-5VPnzWs2.js";import"./vendor-clsx-B-dksMZM.js";import"./vendor-tanstack-react-virtual-IrbCBGJ4.js";import"./vendor-tanstack-virtual-core-Dubg10g5.js";import"./vendor-framer-motion-DJASDzNt.js";import"./vendor-motion-dom-DJLgZh4Q.js";import"./vendor-motion-utils-BGh8QBgx.js";import"./vendor-sonner-CW8w438f.js";import"./vendor-tailwind-merge-CPcsbTWB.js";import"./vendor-fuse.js-Dw8P0qyA.js";import"./web-components-BEPfE4kU.js";import"./computeVirtualFileMetrics-C7vXPUYT.js";import"./vendor-shiki-Bbf2GEcE.js";import"./vendor-shikijs-core-CGM_jqPK.js";import"./vendor-shikijs-types-CPSbSeK6.js";import"./vendor-shikijs-vscode-textmate-BgLrS_2D.js";import"./vendor-hast-util-to-html-BKBhbTDb.js";import"./vendor-html-void-elements-CkdplsNl.js";import"./vendor-property-information-rJCbAzvX.js";import"./vendor-zwitch-C2o2j-tx.js";import"./vendor-stringify-entities-CsH1VEn9.js";import"./vendor-character-entities-legacy-BpoLgcEt.js";import"./vendor-character-entities-html4-D7taRCQ7.js";import"./vendor-ccount-c2V3InAJ.js";import"./vendor-comma-separated-tokens-D8TqSuIK.js";import"./vendor-space-separated-tokens-DD3iYX1K.js";import"./vendor-hast-util-whitespace-D4Wp6AEg.js";import"./vendor-shikijs-engine-oniguruma-DPWuIF1G.js";import"./themeResolver-BmJyTmjJ.js";import"./vendor-pierre-theming-C6Z4M5_u.js";import"./vendor-shikijs-engine-javascript-Cme4830A.js";import"./vendor-oniguruma-to-es-DLBnFDCE.js";import"./vendor-oniguruma-parser-C0D4_9rT.js";import"./vendor-regex-BBWcyTkg.js";import"./vendor-regex-utilities-2BQyy0xI.js";import"./vendor-regex-recursion-JU4mF-dD.js";import"./vendor-shikijs-transformers-CZWsLLKm.js";import"./usePanelSlide-DkorgQJ5.js";import"./permissionStore-BRcQ9Jgt.js";import"./useInlineCommentController-CwNNjgc7.js";import"./collapsible-CR4U9tjw.js";import"./appThemeRegistry-BK0dHKa6.js";import"./registerCustomTheme-BBXUCRnG.js";import"./isDiffPlainText-zTq-4A04.js";import"./vendor-diff-C3JhlQdm.js";function fn(t,e=10){const a=[];let i;for(const u of t.split(`
|
|
2
2
|
`)){const x=u.match(Pt);if(x!=null){i!=null&&(i.hunkLines.length>0&&(Me(i,e,"trailing"),Ge(i,a)),i=void 0);const b=parseInt(x[3]),N=parseInt(x[1]),v=parseInt(x[4]??"1"),h=parseInt(x[2]??"1");isNaN(b)||isNaN(N)||isNaN(v)||isNaN(h)?a.push(u):i={additionStart:b,deletionStart:N,additionCount:0,deletionCount:0,hunkLines:[],contextLines:[]};continue}if(i==null){a.push(u);continue}if(u.startsWith(" "))i.contextLines.push(u);else if(u!==""){if(i.hunkLines.length>0&&i.contextLines.length>e*2){const b=i.contextLines.length-e*2,N=i.contextLines.slice(-e);Me(i,e,"trailing");const{additionCount:v,deletionCount:h}=i;Ge(i,a),i={additionStart:i.additionStart+v+b,deletionStart:i.deletionStart+h+b,deletionCount:0,additionCount:0,contextLines:N,hunkLines:[]}}Me(i,e,i.hunkLines.length===0?"leading":"before-change"),i.hunkLines.push(u),u.startsWith("+")?i.additionCount+=1:u.startsWith("-")&&(i.deletionCount+=1)}}i!=null&&i.hunkLines.length>0&&(Me(i,e,"trailing"),Ge(i,a));const c=a.join(`
|
|
3
3
|
`);return t.endsWith(`
|
|
4
4
|
`)?`${c}
|
|
@@ -15,4 +15,4 @@ ${e}`,bn=t=>{if(!t.startsWith("diff --git ")&&!/^--- [^\n]*\t?\r?\n\+\+\+ [^\n]*
|
|
|
15
15
|
new file mode `)?"added":b.includes(`
|
|
16
16
|
deleted file mode `)?"deleted":b.includes(`
|
|
17
17
|
rename from `)?"renamed":"modified";let v=0,h=0;for(const S of b.split(`
|
|
18
|
-
`))S.startsWith("+")&&!S.startsWith("+++")&&(v+=1),S.startsWith("-")&&!S.startsWith("---")&&(h+=1);return[{file:N==="deleted"?u:x,status:N,additions:v,deletions:h,patch:b}]}),En=t=>t==="added"?"A":t==="deleted"?"D":"M",Ue=(t,e,a)=>Dn(e)?{original:"",modified:"",isBinary:!0,patch:e,contextMode:a}:{original:"",modified:"",patch:e,fileDiff:gn(t,e),contextMode:a},yt=(t,e,a)=>{const i=t??0,c=e??0;return!i&&!c?null:n.jsxs("span",{className:P("typography-meta flex items-center gap-1 text-xs whitespace-nowrap","flex-shrink-0",a?.className),children:[i?n.jsxs("span",{style:{color:"var(--status-success)"},children:["+",i]}):null,c?n.jsxs("span",{style:{color:"var(--status-error)"},children:["-",c]}):null]})},An=o.memo(({scope:t,isGitRepo:e,branchAvailable:a,allCount:i,workingCount:c,stagedCount:u,turnCount:x,branchCount:b,onScopeChange:N})=>{const[v,h]=o.useState(!1),S=t==="all"?i:t==="staged"?u:t==="turn"?x:t==="branch"?b:c,g=t==="staged"?"Staged":t==="turn"?"Last turn":t==="branch"?"Branch":t==="all"?"All":"Changed";return n.jsxs(nn,{open:v,onOpenChange:h,children:[n.jsx(sn,{asChild:!0,children:n.jsxs("button",{type:"button",className:"flex h-7 flex-shrink-0 items-center gap-1.5 rounded-md px-2 typography-ui-label font-semibold text-foreground outline-none hover:bg-interactive-hover focus-visible:ring-2 focus-visible:ring-ring","aria-label":"Select change mode",children:[n.jsxs("span",{className:"whitespace-nowrap",children:[g,n.jsxs("span",{className:"diff-toolbar__scope-count",children:[": ",S]})]}),n.jsx(A,{name:"arrow-down-s",className:"size-4 flex-shrink-0 opacity-60"})]})}),n.jsx(rn,{align:"start",className:"w-40",children:n.jsxs(on,{value:t,onValueChange:w=>{(w==="all"||w==="working"||w==="staged"||w==="turn"||w==="branch")&&(N?.(w),h(!1))},children:[e!==!1?n.jsx(je,{value:"all",children:n.jsxs("span",{className:"flex min-w-0 flex-1 items-center justify-between gap-3",children:[n.jsx("span",{children:"All"}),n.jsx("span",{className:"typography-meta text-muted-foreground",children:i})]})}):null,e!==!1?n.jsx(je,{value:"working",children:n.jsxs("span",{className:"flex min-w-0 flex-1 items-center justify-between gap-3",children:[n.jsx("span",{children:"Changed"}),n.jsx("span",{className:"typography-meta text-muted-foreground",children:c})]})}):null,e!==!1?n.jsx(je,{value:"staged",children:n.jsxs("span",{className:"flex min-w-0 flex-1 items-center justify-between gap-3",children:[n.jsx("span",{children:"Staged"}),n.jsx("span",{className:"typography-meta text-muted-foreground",children:u})]})}):null,n.jsx(je,{value:"turn",children:n.jsxs("span",{className:"flex min-w-0 flex-1 items-center justify-between gap-3",children:[n.jsx("span",{children:"Last turn"}),n.jsx("span",{className:"typography-meta text-muted-foreground",children:x})]})}),a?n.jsx(je,{value:"branch",children:n.jsxs("span",{className:"flex min-w-0 flex-1 items-center justify-between gap-3",children:[n.jsx("span",{children:"Branch"}),n.jsx("span",{className:"typography-meta text-muted-foreground",children:b})]})}):null]})})]})}),Mn=o.memo(({changedFiles:t,selectedFile:e,onSelectFile:a})=>t.length===0?null:n.jsx(pt,{outerClassName:"flex-1 min-h-0",className:"px-2 py-2",children:n.jsx("ul",{className:"flex flex-col gap-1",children:t.map(i=>{const c=bt(i),u=e===i.path;return n.jsx("li",{children:n.jsxs("button",{type:"button",onClick:()=>a(i.path),className:P("flex w-full items-center gap-2 rounded-md px-2 py-1.5 text-left transition-colors",u?"bg-interactive-selection text-interactive-selection-foreground":"text-muted-foreground hover:bg-interactive-hover hover:text-foreground"),children:[n.jsx(ht,{filePath:i.path,className:"h-3.5 w-3.5 flex-shrink-0"}),n.jsx("span",{className:"typography-micro font-semibold w-4 text-center uppercase",style:{color:c.color},title:c.description,"aria-label":c.description,children:c.code}),n.jsx("span",{className:"min-w-0 flex-1 truncate typography-meta",style:{direction:"rtl",textAlign:"left",unicodeBidi:"plaintext"},title:i.path,children:i.path}),yt(i.insertions,i.deletions)]})},i.path)})})})),Tn=o.memo(({filePath:t,diff:e,renderSideBySide:a})=>{const i=e.original.length>0,c=e.modified.length>0,u=a?"flex flex-row gap-6 items-start justify-center":"flex flex-col gap-4 items-center",x=a?"flex flex-col items-center gap-2 flex-1 min-w-0":"flex flex-col items-center gap-2";return n.jsx("div",{className:"w-full overflow-auto p-4",style:{contain:"layout"},children:n.jsxs("div",{className:u,children:[i&&n.jsxs("div",{className:x,children:[n.jsx("span",{className:"typography-meta text-muted-foreground font-medium",children:"Original"}),n.jsx("img",{src:e.original,alt:`Original: ${t}`,className:a?"max-w-full max-h-[70vh] object-contain":"max-w-full object-contain",style:{imageRendering:"auto"}})]}),c&&n.jsxs("div",{className:x,children:[n.jsx("span",{className:"typography-meta text-muted-foreground font-medium",children:i?"Modified":"New"}),n.jsx("img",{src:e.modified,alt:`Modified: ${t}`,className:a?"max-w-full max-h-[70vh] object-contain":"max-w-full object-contain",style:{imageRendering:"auto"}})]})]})})}),In=o.memo(({filePath:t,diff:e,renderSideBySide:a,wrapLines:i})=>{const c=o.useMemo(()=>an(t)||"text",[t]);return e.isBinary?n.jsx(Nn,{}):ve(t)?n.jsx(Tn,{filePath:t,diff:e,renderSideBySide:a}):n.jsx("div",{className:"w-full",style:{contain:"layout"},children:n.jsx(ln,{original:e.original,modified:e.modified,fileDiff:e.fileDiff,language:c,fileName:t,renderSideBySide:a,wrapLines:i,layout:"inline"})})}),$n=o.memo(({filePath:t,staged:e,busyAction:a,disabled:i,onAction:c})=>n.jsx("div",{className:"flex items-center gap-0.5 rounded-full border border-[var(--interactive-border)]/45 bg-[var(--surface-background)]/95 px-1 py-0.5 shadow-sm backdrop-blur-md",children:e?n.jsx(He,{label:`Unstage ${t}`,icon:"arrow-go-back",loading:a==="unstage",disabled:i,onClick:()=>c("unstage")}):n.jsxs(n.Fragment,{children:[n.jsx(He,{label:`Revert changes in ${t}`,icon:"arrow-go-back",loading:a==="discard",disabled:i,tone:"failure",onClick:()=>c("discard")}),n.jsx(He,{label:`Stage ${t}`,icon:"add",loading:a==="stage",disabled:i,tone:"success",onClick:()=>c("stage")})]})})),He=({label:t,icon:e,loading:a,disabled:i,tone:c,onClick:u})=>n.jsx(Ne,{variant:"ghost",size:"sm",className:P("h-6 w-6 rounded-none bg-transparent p-0 text-muted-foreground opacity-70 hover:bg-transparent hover:text-foreground hover:opacity-100",c==="failure"&&"text-[var(--status-error)] hover:text-[var(--status-error)]",c==="success"&&"text-[var(--status-success)] hover:text-[var(--status-success)]"),disabled:i,title:t,"aria-label":t,onClick:x=>{x.stopPropagation(),u()},children:a?n.jsx(A,{name:"loader-4",className:"size-3.5 animate-spin"}):n.jsx(A,{name:e,className:e==="add"?"size-4":"size-3.5"})}),_n=o.memo(({directory:t,file:e,layout:a,wrapLines:i,isSelected:c,isExpanded:u,isMounted:x,onSelect:b,onExpandedChange:N,registerSectionRef:v,showOpenInEditorAction:h=!1,isOpeningInEditor:S=!1,onOpenInEditor:g,staged:w=!1,showFileActions:Te=!0,loadFullFiles:Y=!1,initialDiffData:C=null})=>{const{git:I}=dt(),H=J(o.useCallback(f=>f.directories.get(t)?.diffCache.get(e.path)??null,[t,e.path])),fe=J(f=>f.setDiff),me=J(f=>f.fetchStatus),Ce=_(f=>f.setDiffFileLayout),[pe,Q]=o.useState(0),[W,se]=o.useState(null),[re,ie]=o.useState(!1),[U,O]=o.useState(null),[Z,Ie]=o.useState(!1),[V,K]=o.useState(null),[Se,he]=o.useState(null),B=o.useRef(null),Fe=o.useRef(null),oe=o.useMemo(()=>bt(e),[e]),m=a==="side-by-side",q=Y?"full":"patch",z=`${e.index}:${e.working_dir}:${e.insertions}:${e.deletions}`,M=o.useMemo(()=>C||(w?Se:V||(H?{original:H.original,modified:H.modified,isBinary:H.isBinary,contextMode:"full"}:null)),[H,C,V,w,Se]),ge=M?.contextMode===q,xe=o.useCallback(f=>{Fe.current=f,v(e.path,f)},[e.path,v]),Le=o.useCallback(f=>{N(e.path,f)},[e.path,N]),ee=o.useCallback(()=>{b(e.path)},[e.path,b]);o.useEffect(()=>{w?he(null):K(null),se(null),B.current=null},[z,w]),o.useEffect(()=>{if(!u||!x)return;if(!t||C||M&&ge){B.current=null,ie(!1);return}const f=`${t}::${e.path}::${w?"staged":"unstaged"}::${z}::${q}::${pe}`;if(B.current===f)return;B.current=f,se(null),ie(!0);let F=!1;const G=ut(),ke=Y?jn:gt,Re=ve(e.path)?I.getGitFileDiff(t,{path:e.path,staged:w}):I.getGitDiff(t,{path:e.path,staged:w,contextLines:ke}),be=wn,$e=new Promise((R,$)=>{setTimeout(()=>$(new Error(`Timed out after ${be}ms`)),be)});return Promise.race([Re,$e]).then(R=>{if(!F){if("diff"in R){const $=Ue(e.path,R.diff,q);w?he($):K($)}else{const $={original:R.original??"",modified:R.modified??"",isBinary:R.isBinary,contextMode:"full"};w?he($):fe(t,e.path,$,G)}ie(!1)}}).catch(R=>{if(F)return;const $=R instanceof Error?R.message:String(R);se($),ie(!1)}),()=>{F=!0,B.current===f&&(B.current=null)}},[q,M,ge,pe,t,e.path,z,I,C,u,x,Y,fe,w]);const X=o.useCallback(()=>{Le(!u),ee()},[Le,ee,u]),De=o.useCallback(async f=>{if(!(!t||U!==null)){O(f);try{f==="stage"?await I.stageGitFile(t,e.path):f==="unstage"?await I.unstageGitFile(t,e.path):await I.revertGitFile(t,e.path,{scope:"working"}),Q(F=>F+1),await me(t,I)}catch(F){const G=f==="unstage"?"Failed to unstage changes":f==="stage"?"Failed to stage changes":"Failed to revert changes";ft.error(F instanceof Error?F.message:G)}finally{O(F=>F===f?null:F)}}},[t,me,e.path,U,I]);return n.jsxs("div",{ref:xe,className:P("scroll-mt-9 border-b border-[var(--interactive-border)]/40 last:border-b-0"),children:[n.jsx("div",{className:P("z-30 border-b border-[var(--interactive-border)]/35 bg-[var(--surface-elevated)]/90 backdrop-blur-md supports-[backdrop-filter]:bg-[var(--surface-elevated)]/80","sticky top-0"),children:n.jsxs("div",{role:"button",tabIndex:0,onClick:X,onKeyDown:f=>{f.target===f.currentTarget&&(f.key==="Enter"||f.key===" ")&&(f.preventDefault(),X())},className:P("cursor-pointer","group/header relative grid min-h-9 w-full min-w-0 grid-cols-[minmax(0,1fr)_auto] items-center gap-2 overflow-hidden px-3 py-2","bg-transparent","text-muted-foreground hover:text-foreground",c?"bg-[var(--interactive-selection)]/35":null),children:[n.jsx("div",{className:"absolute inset-0 pointer-events-none group-hover/header:bg-[var(--interactive-hover)]/50"}),n.jsxs("div",{className:"relative flex min-w-0 flex-1 items-center gap-2",children:[n.jsx("span",{className:"flex size-5 items-center justify-center opacity-70 group-hover/header:opacity-100",children:u?n.jsx(A,{name:"arrow-down-s",className:"size-4"}):n.jsx(A,{name:"arrow-right-s",className:"size-4"})}),n.jsx("span",{className:"typography-micro font-semibold leading-none w-4 text-center uppercase",style:{color:oe.color},title:oe.description,"aria-label":oe.description,children:oe.code}),n.jsx("span",{className:"min-w-0 flex-1 overflow-hidden typography-ui-label",title:e.path,children:n.jsxs("span",{className:"flex min-w-0 items-center gap-2",children:[n.jsx(ht,{filePath:e.path,className:"h-3.5 w-3.5 flex-shrink-0 align-middle"}),(()=>{const f=e.path.lastIndexOf("/");if(f===-1)return n.jsx("span",{className:"block min-w-0 truncate typography-ui-label text-foreground",style:{direction:"rtl",textAlign:"left",unicodeBidi:"plaintext"},children:e.path});const F=e.path.slice(0,f),G=e.path.slice(f+1);return n.jsxs("span",{className:"flex min-w-0 items-baseline overflow-hidden",children:[n.jsx("span",{className:"min-w-0 truncate typography-ui-label text-muted-foreground",style:{direction:"rtl",textAlign:"left",unicodeBidi:"plaintext"},children:F}),n.jsxs("span",{className:"flex-shrink-0 typography-ui-label",children:[n.jsx("span",{className:"text-muted-foreground",children:"/"}),n.jsx("span",{className:"text-foreground",children:G})]})]})})()]})})]}),n.jsxs("div",{className:"relative flex shrink-0 items-center justify-self-end gap-2",children:[yt(e.insertions,e.deletions),h&&g?n.jsx(Ne,{variant:"ghost",size:"sm",className:"h-5 w-5 p-0 opacity-70 hover:opacity-100",title:"Open this file in editor at change",onClick:f=>{f.stopPropagation(),g(e.path,M)},disabled:S,children:S?n.jsx(A,{name:"loader-4",className:"size-3.5 animate-spin"}):n.jsx(A,{name:"edit",className:"size-3.5"})}):null,n.jsx(mt,{mode:m?"side-by-side":"unified",onModeChange:f=>{const F=f==="side-by-side"?"side-by-side":"inline";Ce(e.path,F)},className:"opacity-70"})]})]})}),u&&n.jsxs("div",{className:"relative overflow-hidden bg-background",children:[!x&&!W?n.jsx("div",{className:"h-40 border border-border/40 bg-background/40"}):null,W?n.jsxs("div",{className:"flex flex-col items-center gap-2 px-4 py-8 text-sm text-muted-foreground",children:[n.jsx("div",{className:"typography-ui-label font-semibold text-foreground",children:"Failed to load diff"}),n.jsx("div",{className:"typography-meta text-muted-foreground max-w-[32rem] text-center",children:W}),n.jsx("button",{type:"button",className:"typography-ui-label text-primary hover:underline",onClick:()=>Q(f=>f+1),children:"Retry"})]}):null,x&&re&&!M&&!W?n.jsxs("div",{className:"flex items-center justify-center gap-2 px-4 py-8 text-sm text-muted-foreground",children:[n.jsx(A,{name:"loader-4",className:"size-4 animate-spin"}),"Loading diff..."]}):null,x&&M&&!Z&&e.insertions+e.deletions>rt?n.jsxs("div",{className:"flex flex-col items-center gap-2 px-4 py-8 text-sm text-muted-foreground",children:[n.jsx("div",{className:"typography-ui-label font-semibold text-foreground",children:`Large diff (${e.insertions+e.deletions} changed lines)`}),n.jsx("div",{className:"typography-meta text-muted-foreground",children:"Rendering may be slow. You can still view the diff by clicking below."}),n.jsx("button",{type:"button",className:"typography-ui-label text-primary hover:underline",onClick:()=>Ie(!0),children:"Render anyway"})]}):null,x&&M&&(Z||e.insertions+e.deletions<=rt)?n.jsxs(n.Fragment,{children:[n.jsx(In,{filePath:e.path,diff:M,renderSideBySide:m,wrapLines:i}),Te?n.jsx("div",{className:"pointer-events-none absolute bottom-3 right-3 z-20",children:n.jsx("div",{className:"pointer-events-auto",children:n.jsx($n,{filePath:e.path,staged:w,busyAction:U,disabled:U!==null,onAction:De})})}):null]}):null]})]})}),Vr=({hideStackedFileSidebar:t=!1,stackedDefaultCollapsedAll:e=!1,pinSelectedFileHeaderToTopOnNavigate:a=!1,showOpenInEditorAction:i=!1,diffScope:c="all",onDiffScopeChange:u,branchBase:x=null,branchHead:b=null,targetFilePath:N=null,flushContent:v=!1})=>{const{git:h,files:S}=dt(),g=zt(),{screenWidth:w,isMobile:Te}=Gt(),Y=Ht(g??null),C=Ut(g??null),I=Vt(g??null),H=J(s=>s.setActiveDirectory),fe=J(s=>s.ensureStatus),me=J(s=>s.fetchStatus),Ce=J(s=>s.clearDiffCache),pe=J(s=>s.setDiff),[Q,W]=o.useState(null),[se,re]=o.useState(!1),[ie,U]=o.useState(null),[O,Z]=o.useState(()=>new Set),[Ie,V]=o.useState(()=>new Set),[K,Se]=o.useState(!1),[he,B]=o.useState(0),[Fe,oe]=o.useState(()=>new Map),[m,q]=o.useState(c),[z,M]=o.useState([]),[ge,xe]=o.useState(null),[Le,ee]=o.useState(!1);o.useEffect(()=>{q(c)},[c]);const X=_(s=>s.pendingDiffFile),De=_(s=>s.pendingDiffStaged),f=_(s=>s.pendingDiffScope),F=_(s=>s.setPendingDiffFile),G=_(s=>s.diffLayoutPreference),ke=_(s=>s.diffFileLayout),Re=_(s=>s.setDiffFileLayout),be=_(s=>s.diffWrapLines),$e=_(s=>s.setDiffWrapLines),R=_(s=>s.openContextFileAtLine),$=Kt(s=>s.currentSessionId),Ve=qt($??""),_e=be,Be=m==="staged"?!0:m==="working"?!1:null,Ee=Be??se,wt=Te||w<=768,jt=!t&&!wt&&w>=1024,ae=o.useRef(null),ye=o.useRef(new Map),te=o.useRef(null),k=o.useRef(null),le=o.useRef(!1),ce=o.useRef(null),Ke=o.useRef(null),Pe=o.useRef(null),We=o.useRef(null),qe=o.useCallback(()=>{const s=ae.current;if(!s)return null;const r=s.getBoundingClientRect().top,l=[];for(const[d,p]of ye.current)p&&l.push({path:d,top:p.getBoundingClientRect().top});return et(r,l)},[]),ue=o.useCallback(()=>{te.current=null,le.current=!1,U(null),k.current!==null&&(window.cancelAnimationFrame(k.current),k.current=null)},[]),de=o.useCallback(s=>{Z(r=>{if(r.has(s))return r;const l=new Set(r);return l.add(s),l})},[]),we=o.useMemo(()=>{const s=Xt(Ve,{showTextJustificationActivity:!1,showTurnChangedFiles:!0,mergeHiddenUserTurns:!0});for(let r=s.turns.length-1;r>=0;r-=1){const l=s.turns[r];if(!l)continue;const d=l.activityParts.map(y=>y.part).filter(y=>y.type==="tool"),p=Jt(d);if(p.length>0)return p.map(y=>({file:y.path,status:"modified",additions:y.additions,deletions:y.deletions,patch:y.patch}));const D=kn(l.userMessage.info.summary?.diffs);if(D.length>0)return D}return[]},[Ve]);o.useEffect(()=>{if(m!=="branch"||!g||!x||!b||!h.getGitRangeDiff){M([]),xe(null),ee(!1);return}let s=!1;return ee(!0),xe(null),h.getGitRangeDiff(g,{base:x,head:b,contextLines:gt}).then(r=>{s||(M(Rn(r.diff??"")),ee(!1))}).catch(r=>{s||(M([]),ee(!1),xe(r instanceof Error?r.message:String(r)))}),()=>{s=!0}},[m,x,b,g,h]);const vt=o.useMemo(()=>{const s=new Map;for(const r of we)if(r.file){if(typeof r.patch=="string"){s.set(r.file,Ue(r.file,r.patch,"patch"));continue}s.set(r.file,{original:r.before??"",modified:r.after??"",contextMode:"full"})}return s},[we]),Nt=o.useMemo(()=>{const s=new Map;for(const r of z)!r.file||typeof r.patch!="string"||s.set(r.file,Ue(r.file,r.patch,"patch"));return s},[z]),j=o.useMemo(()=>{if(m==="turn"||m==="branch")return(m==="branch"?z:we).map(d=>({path:d.file??"",index:"",working_dir:En(d.status),insertions:d.additions??0,deletions:d.deletions??0,isNew:d.status==="added"})).filter(d=>d.path).sort((d,p)=>d.path.localeCompare(p.path));if(!C?.files)return[];const s=C.diffStats??{},r=m==="staged"?ot:m==="working"?at:()=>!0;return C.files.filter(r).map(l=>({...l,insertions:s[l.path]?.insertions??0,deletions:s[l.path]?.deletions??0,isNew:Fn(l)})).sort((l,d)=>l.path.localeCompare(d.path))},[m,z,we,C]),Ct=o.useMemo(()=>C?.files?C.files.filter(at).length:0,[C]),St=o.useMemo(()=>C?.files?C.files.filter(ot).length:0,[C]),Ft=we.length,Lt=C?.files?.length??0,Dt=z.length,Oe=o.useMemo(()=>j.map(s=>s.path).join("\0"),[j]);o.useEffect(()=>{const s=Oe?Oe.split("\0"):[],r=new Set(s),l=`${g??""}:${m}:${e?"collapsed":"default"}`,d=Ke.current!==l;Ke.current=l,Z(p=>{if(d){const L=e?0:vn(s.length);return new Set(s.slice(0,L))}let D=!1;const y=new Set;for(const L of p){if(!r.has(L)){D=!0;continue}y.add(L)}return D?y:p}),V(p=>{if(d)return new Set;let D=!1;const y=new Set;for(const L of p){if(!r.has(L)){D=!0;continue}y.add(L)}return D?y:p})},[m,Oe,g,e]);const Xe=o.useCallback(()=>{ce.current=null;const s=ae.current;if(!s)return;const r=s.getBoundingClientRect(),l=r.top-it,d=r.bottom+it,p={},D=[];for(const[y,L]of ye.current){if(!L)continue;const E=L.getBoundingClientRect();D.push({path:y,top:E.top}),O.has(y)&&(E.bottom<l||E.top>d||(p[y]=!0))}Pe.current=et(r.top,D),V(y=>{let L=!1;const E=new Set(y);for(const Qe of Object.keys(p))E.has(Qe)||(E.add(Qe),L=!0);return L?E:y})},[O]),T=o.useCallback(()=>{typeof window>"u"||ce.current===null&&(ce.current=window.requestAnimationFrame(Xe))},[Xe]);o.useEffect(()=>{const s=ae.current;if(s)return T(),s.addEventListener("scroll",T,{passive:!0}),window.addEventListener("resize",T),()=>{s.removeEventListener("scroll",T),window.removeEventListener("resize",T),ce.current!==null&&(window.cancelAnimationFrame(ce.current),ce.current=null)}},[j,O,T]);const ze=o.useCallback(s=>{const r=ke[s.path];if(r)return r;if(G==="inline")return"inline";if(G==="side-by-side")return"side-by-side";const l=w<yn;return s.isNew||l?"inline":"side-by-side"},[ke,G,w]),Je=o.useMemo(()=>j.length===0?null:j.every(s=>ze(s)==="side-by-side")?"side-by-side":"inline",[j,ze]);o.useEffect(()=>{g&&(H(g),fe(g,h))},[g,H,fe,h]),o.useEffect(()=>{if(g)return Yt.onGitRefreshHint(s=>{lt(s.directory)===lt(g)&&(s.paths?.length&&(We.current=qe()??Pe.current,Ce(g,s.paths),oe(r=>{const l=new Map(r);for(const d of s.paths??[])l.set(d,(l.get(d)??0)+1);return l})),me(g,h,{silent:!0}))})},[qe,Ce,g,me,h]),o.useLayoutEffect(()=>{const s=We.current;if(!s)return;We.current=null;const r=ae.current,l=ye.current.get(s.path);if(!r||!l)return;const d=r.getBoundingClientRect().top,p=l.getBoundingClientRect().top-d;r.scrollTop=mn(r.scrollTop,s.topOffset,p,r.scrollHeight-r.clientHeight),Pe.current=s},[Fe]),o.useEffect(()=>{m!=="all"&&!f||X&&(f&&q(f),W(X),re(f==="staged"||!f&&De),F(null),le.current=!0,te.current=X,de(X),B(s=>s+1))},[m,de,X,f,De,F]),o.useEffect(()=>{if(m==="all")return;const s=N?.trim();s&&(W(s),re(m==="staged"),le.current=!0,te.current=s,de(s),B(r=>r+1))},[m,de,N]),o.useEffect(()=>{if(!Q)return;j.some(r=>r.path===Q)||(W(null),re(!1))},[j,Q]);const kt=o.useCallback((s,r)=>{const l=ye.current;r?l.set(s,r):l.delete(s),T()},[T]),Rt=o.useCallback((s,r)=>{ue(),Z(l=>{const d=l.has(s);if(r===d)return l;const p=new Set(l);return r?p.add(s):p.delete(s),p}),r||V(l=>{if(!l.has(s))return l;const d=new Set(l);return d.delete(s),d}),T()},[ue,T]),Et=o.useCallback(()=>{ue(),Z(s=>s.size>0?new Set:new Set(j.map(r=>r.path))),V(new Set),T()},[ue,j,T]),Ae=o.useCallback(s=>{const r=ye.current.get(s),l=ae.current;if(!r||!l)return!1;const d=r.getBoundingClientRect().top-l.getBoundingClientRect().top;return l.scrollTo({top:l.scrollTop+d,behavior:"auto"}),!0},[]);o.useEffect(()=>{if(!te.current)return;let r=0;const l=20;let d=!1;const p=(y=!0)=>{d||(d=!0,te.current=null,le.current=!1,y&&U(null),k.current!==null&&(window.cancelAnimationFrame(k.current),k.current=null))},D=()=>{if(d){k.current=null;return}const y=te.current;if(!y){p(),k.current=null;return}if(!Ae(y)){r+=1,r<l?k.current=window.requestAnimationFrame(D):(p(),k.current=null);return}if(a&&le.current){U(y),p(!1);return}p()};return k.current=window.requestAnimationFrame(D),()=>{d=!0,k.current!==null&&(window.cancelAnimationFrame(k.current),k.current=null)}},[a,he,Ae]);const At=o.useCallback(s=>{},[]),Mt=o.useCallback(s=>{ue(),W(s),re(!1),le.current=!0,te.current=s,de(s),B(r=>r+1),Ae(s)},[ue,de,Ae]),Tt=o.useCallback(s=>{const r=s==="side-by-side"?"side-by-side":"inline";j.forEach(l=>{Re(l.path,r)})},[j,Re]),[It,Ye]=o.useState(null),$t=o.useCallback(async(s,r)=>{if(!g||!s)return;Ye(s);const l=ut();try{let d=null;if(r?.patch&&!r.isBinary&&!ve(s)?d=st(r.patch):r&&r.contextMode==="full"&&!r.isBinary&&!ve(s)&&(d=ct(r.original,r.modified)),d===null)try{const E=await h.getGitDiff(g,{path:s,staged:Ee,contextLines:3});d=st(E.diff)}catch{d=null}let p=r;if(d===null||!p){const E=await h.getGitFileDiff(g,{path:s,staged:Ee});p={original:E.original??"",modified:E.modified??"",isBinary:E.isBinary},Ee||pe(g,s,p,l)}const D=d??(p.isBinary||ve(s)?1:ct(p.original,p.modified)),y=Ln(g,s),L=await cn(S,y,{directory:g});if(!L.ok){ft.error(un(L.reason));return}R(g,y,D,1)}finally{Ye(d=>d===s?null:d)}},[Ee,g,S,h,R,pe]),_t=()=>{if(!g)return null;const s=r=>Be!==null?Be:se&&r===Q;return n.jsxs("div",{className:P("flex min-w-0 flex-1 min-h-0 h-full",v?"gap-0":"gap-3 px-3 pb-3 pt-2"),children:[jt&&n.jsxs("section",{className:"hidden lg:flex w-72 flex-col rounded-xl border border-border/60 bg-background/70 overflow-hidden",children:[n.jsxs("div",{className:"flex items-center justify-between px-3 py-1.5 border-b border-border/40",children:[n.jsx("span",{className:"typography-ui-header font-semibold text-foreground",children:"Files"}),n.jsx("span",{className:"typography-meta text-muted-foreground",children:j.length})]}),n.jsx(Mn,{changedFiles:j,selectedFile:null,onSelectFile:Mt})]}),n.jsx("div",{className:"relative flex-1 min-w-0 min-h-0 h-full",children:n.jsx(pt,{ref:ae,outerClassName:"min-h-0 h-full",className:"[overflow-anchor:none] pb-16",disableHorizontal:!0,observeMutations:!1,preventOverscroll:!0,"data-diff-virtual-root":!0,children:n.jsx("div",{className:"flex flex-col [overflow-anchor:none]","data-diff-virtual-content":!0,children:j.map(r=>n.jsx(_n,{directory:g,file:r,layout:ze(r),wrapLines:_e,isSelected:!1,isExpanded:O.has(r.path),isMounted:Ie.has(r.path)||r.path===ie,onSelect:At,onExpandedChange:Rt,registerSectionRef:kt,showOpenInEditorAction:i&&m!=="turn"&&m!=="branch",isOpeningInEditor:It===r.path,onOpenInEditor:(l,d)=>{$t(l,d)},staged:s(r.path),showFileActions:m!=="turn"&&m!=="branch",loadFullFiles:K,initialDiffData:m==="turn"?vt.get(r.path)??null:m==="branch"?Nt.get(r.path)??null:null},`${r.path}:${Fe.get(r.path)??0}`))})})})]})},Bt=()=>g?m!=="turn"&&I&&!C?n.jsxs("div",{className:"flex flex-1 items-center justify-center gap-2 text-sm text-muted-foreground",children:[n.jsx(A,{name:"loader-4",className:"size-4 animate-spin"}),"Loading repository status..."]}):m!=="turn"&&m!=="branch"&&Y===!1?n.jsx("div",{className:"flex flex-1 items-center justify-center text-sm text-muted-foreground",children:"Not a git repository. Use the Git tab to initialize or change directories."}):m==="branch"&&Le?n.jsxs("div",{className:"flex flex-1 items-center justify-center gap-2 text-sm text-muted-foreground",children:[n.jsx(A,{name:"loader-4",className:"size-4 animate-spin"}),"Loading branch changes..."]}):m==="branch"&&ge?n.jsx("div",{className:"flex flex-1 items-center justify-center px-4 text-center text-sm text-muted-foreground",children:`Failed to load branch changes: ${ge}`}):j.length===0?n.jsx("div",{className:"flex flex-1 items-center justify-center text-sm text-muted-foreground",children:m==="turn"?"No last turn changes to display":"Working tree clean, no changes to display"}):_t():n.jsx("div",{className:"flex flex-1 items-center justify-center text-sm text-muted-foreground",children:"Select a session directory to view diffs"});return n.jsxs("div",{className:"flex h-full flex-col overflow-hidden bg-background",children:[n.jsxs("div",{className:"@container/diff-toolbar flex min-w-0 items-center gap-2 px-3 py-2 bg-background",children:[(Y!==!1||m==="turn")&&(m==="all"||m==="working"||m==="staged"||m==="turn"||m==="branch")?n.jsx(An,{scope:m,isGitRepo:Y,branchAvailable:!!(x&&b),allCount:Lt,workingCount:Ct,stagedCount:St,turnCount:Ft,branchCount:Dt,onScopeChange:s=>{q(s),u?.(s)}}):n.jsx("div",{className:"flex items-center gap-1 rounded-md px-2 py-1 text-muted-foreground shrink-0",children:n.jsx("span",{className:"typography-ui-label font-semibold text-foreground",children:I&&!C?"Loading changes...":j.length===1?`${j.length} file changed`:`${j.length} files changed`})}),j.length>0&&n.jsxs(Ne,{variant:"ghost",size:"sm",onClick:Et,className:P("diff-toolbar__expand-button h-7 flex-shrink-0 gap-1 px-1.5 text-muted-foreground hover:text-foreground","ml-auto"),title:O.size>0?"Collapse all":"Expand all",children:[n.jsx(A,{name:"expand-up-down",className:"size-4"}),n.jsx("span",{className:"diff-toolbar__expand-label typography-ui-label",children:O.size>0?"Collapse all":"Expand all"})]}),j.length>0&&m!=="turn"&&m!=="branch"&&n.jsxs(Qt,{children:[n.jsx(Zt,{asChild:!0,children:n.jsx(Ne,{variant:"ghost",size:"sm",onClick:()=>Se(s=>!s),"aria-pressed":K,"aria-label":K?"Unload full files":"Load full files",className:P("h-7 w-7 flex-shrink-0 p-0 text-muted-foreground hover:text-foreground",K&&"bg-interactive-selection text-interactive-selection-foreground"),children:n.jsx(A,{name:"file-download",className:"size-4"})})}),n.jsx(en,{children:n.jsx("p",{children:K?"Unload full files":"Load full files"})})]}),j.length>0&&n.jsx(Ne,{variant:"ghost",size:"sm",onClick:()=>$e(!be),className:P("h-5 w-5 p-0 transition-opacity",_e?"text-foreground opacity-100":"text-muted-foreground opacity-60 hover:opacity-100"),title:_e?"Disable line wrap":"Enable line wrap",children:n.jsx(A,{name:"text-wrap",className:"size-4"})}),Je&&n.jsx(mt,{mode:Je==="side-by-side"?"side-by-side":"unified",onModeChange:Tt})]}),Bt()]})};export{Vr as DiffView};
|
|
18
|
+
`))S.startsWith("+")&&!S.startsWith("+++")&&(v+=1),S.startsWith("-")&&!S.startsWith("---")&&(h+=1);return[{file:N==="deleted"?u:x,status:N,additions:v,deletions:h,patch:b}]}),En=t=>t==="added"?"A":t==="deleted"?"D":"M",Ue=(t,e,a)=>Dn(e)?{original:"",modified:"",isBinary:!0,patch:e,contextMode:a}:{original:"",modified:"",patch:e,fileDiff:gn(t,e),contextMode:a},yt=(t,e,a)=>{const i=t??0,c=e??0;return!i&&!c?null:n.jsxs("span",{className:P("typography-meta flex items-center gap-1 text-xs whitespace-nowrap","flex-shrink-0",a?.className),children:[i?n.jsxs("span",{style:{color:"var(--status-success)"},children:["+",i]}):null,c?n.jsxs("span",{style:{color:"var(--status-error)"},children:["-",c]}):null]})},An=o.memo(({scope:t,isGitRepo:e,branchAvailable:a,allCount:i,workingCount:c,stagedCount:u,turnCount:x,branchCount:b,onScopeChange:N})=>{const[v,h]=o.useState(!1),S=t==="all"?i:t==="staged"?u:t==="turn"?x:t==="branch"?b:c,g=t==="staged"?"Staged":t==="turn"?"Last turn":t==="branch"?"Branch":t==="all"?"All":"Changed";return n.jsxs(nn,{open:v,onOpenChange:h,children:[n.jsx(sn,{asChild:!0,children:n.jsxs("button",{type:"button",className:"flex h-7 flex-shrink-0 items-center gap-1.5 rounded-md px-2 typography-ui-label font-semibold text-foreground outline-none hover:bg-interactive-hover focus-visible:ring-2 focus-visible:ring-ring","aria-label":"Select change mode",children:[n.jsxs("span",{className:"whitespace-nowrap",children:[g,n.jsxs("span",{className:"diff-toolbar__scope-count",children:[": ",S]})]}),n.jsx(A,{name:"arrow-down-s",className:"size-4 flex-shrink-0 opacity-60"})]})}),n.jsx(rn,{align:"start",className:"w-40",children:n.jsxs(on,{value:t,onValueChange:w=>{(w==="all"||w==="working"||w==="staged"||w==="turn"||w==="branch")&&(N?.(w),h(!1))},children:[e!==!1?n.jsx(je,{value:"all",children:n.jsxs("span",{className:"flex min-w-0 flex-1 items-center justify-between gap-3",children:[n.jsx("span",{children:"All"}),n.jsx("span",{className:"typography-meta text-muted-foreground",children:i})]})}):null,e!==!1?n.jsx(je,{value:"working",children:n.jsxs("span",{className:"flex min-w-0 flex-1 items-center justify-between gap-3",children:[n.jsx("span",{children:"Changed"}),n.jsx("span",{className:"typography-meta text-muted-foreground",children:c})]})}):null,e!==!1?n.jsx(je,{value:"staged",children:n.jsxs("span",{className:"flex min-w-0 flex-1 items-center justify-between gap-3",children:[n.jsx("span",{children:"Staged"}),n.jsx("span",{className:"typography-meta text-muted-foreground",children:u})]})}):null,n.jsx(je,{value:"turn",children:n.jsxs("span",{className:"flex min-w-0 flex-1 items-center justify-between gap-3",children:[n.jsx("span",{children:"Last turn"}),n.jsx("span",{className:"typography-meta text-muted-foreground",children:x})]})}),a?n.jsx(je,{value:"branch",children:n.jsxs("span",{className:"flex min-w-0 flex-1 items-center justify-between gap-3",children:[n.jsx("span",{children:"Branch"}),n.jsx("span",{className:"typography-meta text-muted-foreground",children:b})]})}):null]})})]})}),Mn=o.memo(({changedFiles:t,selectedFile:e,onSelectFile:a})=>t.length===0?null:n.jsx(pt,{outerClassName:"flex-1 min-h-0",className:"px-2 py-2",children:n.jsx("ul",{className:"flex flex-col gap-1",children:t.map(i=>{const c=bt(i),u=e===i.path;return n.jsx("li",{children:n.jsxs("button",{type:"button",onClick:()=>a(i.path),className:P("flex w-full items-center gap-2 rounded-md px-2 py-1.5 text-left transition-colors",u?"bg-interactive-selection text-interactive-selection-foreground":"text-muted-foreground hover:bg-interactive-hover hover:text-foreground"),children:[n.jsx(ht,{filePath:i.path,className:"h-3.5 w-3.5 flex-shrink-0"}),n.jsx("span",{className:"typography-micro font-semibold w-4 text-center uppercase",style:{color:c.color},title:c.description,"aria-label":c.description,children:c.code}),n.jsx("span",{className:"min-w-0 flex-1 truncate typography-meta",style:{direction:"rtl",textAlign:"left",unicodeBidi:"plaintext"},title:i.path,children:i.path}),yt(i.insertions,i.deletions)]})},i.path)})})})),Tn=o.memo(({filePath:t,diff:e,renderSideBySide:a})=>{const i=e.original.length>0,c=e.modified.length>0,u=a?"flex flex-row gap-6 items-start justify-center":"flex flex-col gap-4 items-center",x=a?"flex flex-col items-center gap-2 flex-1 min-w-0":"flex flex-col items-center gap-2";return n.jsx("div",{className:"w-full overflow-auto p-4",style:{contain:"layout"},children:n.jsxs("div",{className:u,children:[i&&n.jsxs("div",{className:x,children:[n.jsx("span",{className:"typography-meta text-muted-foreground font-medium",children:"Original"}),n.jsx("img",{src:e.original,alt:`Original: ${t}`,className:a?"max-w-full max-h-[70vh] object-contain":"max-w-full object-contain",style:{imageRendering:"auto"}})]}),c&&n.jsxs("div",{className:x,children:[n.jsx("span",{className:"typography-meta text-muted-foreground font-medium",children:i?"Modified":"New"}),n.jsx("img",{src:e.modified,alt:`Modified: ${t}`,className:a?"max-w-full max-h-[70vh] object-contain":"max-w-full object-contain",style:{imageRendering:"auto"}})]})]})})}),In=o.memo(({filePath:t,diff:e,renderSideBySide:a,wrapLines:i})=>{const c=o.useMemo(()=>an(t)||"text",[t]);return e.isBinary?n.jsx(Nn,{}):ve(t)?n.jsx(Tn,{filePath:t,diff:e,renderSideBySide:a}):n.jsx("div",{className:"w-full",style:{contain:"layout"},children:n.jsx(ln,{original:e.original,modified:e.modified,fileDiff:e.fileDiff,language:c,fileName:t,renderSideBySide:a,wrapLines:i,layout:"inline"})})}),$n=o.memo(({filePath:t,staged:e,busyAction:a,disabled:i,onAction:c})=>n.jsx("div",{className:"flex items-center gap-0.5 rounded-full border border-[var(--interactive-border)]/45 bg-[var(--surface-background)]/95 px-1 py-0.5 shadow-sm backdrop-blur-md",children:e?n.jsx(He,{label:`Unstage ${t}`,icon:"arrow-go-back",loading:a==="unstage",disabled:i,onClick:()=>c("unstage")}):n.jsxs(n.Fragment,{children:[n.jsx(He,{label:`Revert changes in ${t}`,icon:"arrow-go-back",loading:a==="discard",disabled:i,tone:"failure",onClick:()=>c("discard")}),n.jsx(He,{label:`Stage ${t}`,icon:"add",loading:a==="stage",disabled:i,tone:"success",onClick:()=>c("stage")})]})})),He=({label:t,icon:e,loading:a,disabled:i,tone:c,onClick:u})=>n.jsx(Ne,{variant:"ghost",size:"sm",className:P("h-6 w-6 rounded-none bg-transparent p-0 text-muted-foreground opacity-70 hover:bg-transparent hover:text-foreground hover:opacity-100",c==="failure"&&"text-[var(--status-error)] hover:text-[var(--status-error)]",c==="success"&&"text-[var(--status-success)] hover:text-[var(--status-success)]"),disabled:i,title:t,"aria-label":t,onClick:x=>{x.stopPropagation(),u()},children:a?n.jsx(A,{name:"loader-4",className:"size-3.5 animate-spin"}):n.jsx(A,{name:e,className:e==="add"?"size-4":"size-3.5"})}),_n=o.memo(({directory:t,file:e,layout:a,wrapLines:i,isSelected:c,isExpanded:u,isMounted:x,onSelect:b,onExpandedChange:N,registerSectionRef:v,showOpenInEditorAction:h=!1,isOpeningInEditor:S=!1,onOpenInEditor:g,staged:w=!1,showFileActions:Te=!0,loadFullFiles:Q=!1,initialDiffData:C=null})=>{const{git:I}=dt(),H=J(o.useCallback(f=>f.directories.get(t)?.diffCache.get(e.path)??null,[t,e.path])),fe=J(f=>f.setDiff),me=J(f=>f.fetchStatus),Ce=_(f=>f.setDiffFileLayout),[pe,Y]=o.useState(0),[W,se]=o.useState(null),[re,ie]=o.useState(!1),[U,O]=o.useState(null),[Z,Ie]=o.useState(!1),[K,V]=o.useState(null),[Se,he]=o.useState(null),B=o.useRef(null),Fe=o.useRef(null),oe=o.useMemo(()=>bt(e),[e]),m=a==="side-by-side",q=Q?"full":"patch",z=`${e.index}:${e.working_dir}:${e.insertions}:${e.deletions}`,M=o.useMemo(()=>C||(w?Se:K||(H?{original:H.original,modified:H.modified,isBinary:H.isBinary,contextMode:"full"}:null)),[H,C,K,w,Se]),ge=M?.contextMode===q,xe=o.useCallback(f=>{Fe.current=f,v(e.path,f)},[e.path,v]),Le=o.useCallback(f=>{N(e.path,f)},[e.path,N]),ee=o.useCallback(()=>{b(e.path)},[e.path,b]);o.useEffect(()=>{w?he(null):V(null),se(null),B.current=null},[z,w]),o.useEffect(()=>{if(!u||!x)return;if(!t||C||M&&ge){B.current=null,ie(!1);return}const f=`${t}::${e.path}::${w?"staged":"unstaged"}::${z}::${q}::${pe}`;if(B.current===f)return;B.current=f,se(null),ie(!0);let F=!1;const G=ut(),ke=Q?jn:gt,Re=ve(e.path)?I.getGitFileDiff(t,{path:e.path,staged:w}):I.getGitDiff(t,{path:e.path,staged:w,contextLines:ke}),be=wn,$e=new Promise((R,$)=>{setTimeout(()=>$(new Error(`Timed out after ${be}ms`)),be)});return Promise.race([Re,$e]).then(R=>{if(!F){if("diff"in R){const $=Ue(e.path,R.diff,q);w?he($):V($)}else{const $={original:R.original??"",modified:R.modified??"",isBinary:R.isBinary,contextMode:"full"};w?he($):fe(t,e.path,$,G)}ie(!1)}}).catch(R=>{if(F)return;const $=R instanceof Error?R.message:String(R);se($),ie(!1)}),()=>{F=!0,B.current===f&&(B.current=null)}},[q,M,ge,pe,t,e.path,z,I,C,u,x,Q,fe,w]);const X=o.useCallback(()=>{Le(!u),ee()},[Le,ee,u]),De=o.useCallback(async f=>{if(!(!t||U!==null)){O(f);try{f==="stage"?await I.stageGitFile(t,e.path):f==="unstage"?await I.unstageGitFile(t,e.path):await I.revertGitFile(t,e.path,{scope:"working"}),Y(F=>F+1),await me(t,I)}catch(F){const G=f==="unstage"?"Failed to unstage changes":f==="stage"?"Failed to stage changes":"Failed to revert changes";ft.error(F instanceof Error?F.message:G)}finally{O(F=>F===f?null:F)}}},[t,me,e.path,U,I]);return n.jsxs("div",{ref:xe,className:P("scroll-mt-9 border-b border-[var(--interactive-border)]/40 last:border-b-0"),children:[n.jsx("div",{className:P("z-30 border-b border-[var(--interactive-border)]/35 bg-[var(--surface-elevated)]/90 backdrop-blur-md supports-[backdrop-filter]:bg-[var(--surface-elevated)]/80","sticky top-0"),children:n.jsxs("div",{role:"button",tabIndex:0,onClick:X,onKeyDown:f=>{f.target===f.currentTarget&&(f.key==="Enter"||f.key===" ")&&(f.preventDefault(),X())},className:P("cursor-pointer","group/header relative grid min-h-9 w-full min-w-0 grid-cols-[minmax(0,1fr)_auto] items-center gap-2 overflow-hidden px-3 py-2","bg-transparent","text-muted-foreground hover:text-foreground",c?"bg-[var(--interactive-selection)]/35":null),children:[n.jsx("div",{className:"absolute inset-0 pointer-events-none group-hover/header:bg-[var(--interactive-hover)]/50"}),n.jsxs("div",{className:"relative flex min-w-0 flex-1 items-center gap-2",children:[n.jsx("span",{className:"flex size-5 items-center justify-center opacity-70 group-hover/header:opacity-100",children:u?n.jsx(A,{name:"arrow-down-s",className:"size-4"}):n.jsx(A,{name:"arrow-right-s",className:"size-4"})}),n.jsx("span",{className:"typography-micro font-semibold leading-none w-4 text-center uppercase",style:{color:oe.color},title:oe.description,"aria-label":oe.description,children:oe.code}),n.jsx("span",{className:"min-w-0 flex-1 overflow-hidden typography-ui-label",title:e.path,children:n.jsxs("span",{className:"flex min-w-0 items-center gap-2",children:[n.jsx(ht,{filePath:e.path,className:"h-3.5 w-3.5 flex-shrink-0 align-middle"}),(()=>{const f=e.path.lastIndexOf("/");if(f===-1)return n.jsx("span",{className:"block min-w-0 truncate typography-ui-label text-foreground",style:{direction:"rtl",textAlign:"left",unicodeBidi:"plaintext"},children:e.path});const F=e.path.slice(0,f),G=e.path.slice(f+1);return n.jsxs("span",{className:"flex min-w-0 items-baseline overflow-hidden",children:[n.jsx("span",{className:"min-w-0 truncate typography-ui-label text-muted-foreground",style:{direction:"rtl",textAlign:"left",unicodeBidi:"plaintext"},children:F}),n.jsxs("span",{className:"flex-shrink-0 typography-ui-label",children:[n.jsx("span",{className:"text-muted-foreground",children:"/"}),n.jsx("span",{className:"text-foreground",children:G})]})]})})()]})})]}),n.jsxs("div",{className:"relative flex shrink-0 items-center justify-self-end gap-2",children:[yt(e.insertions,e.deletions),h&&g?n.jsx(Ne,{variant:"ghost",size:"sm",className:"h-5 w-5 p-0 opacity-70 hover:opacity-100",title:"Open this file in editor at change",onClick:f=>{f.stopPropagation(),g(e.path,M)},disabled:S,children:S?n.jsx(A,{name:"loader-4",className:"size-3.5 animate-spin"}):n.jsx(A,{name:"edit",className:"size-3.5"})}):null,n.jsx(mt,{mode:m?"side-by-side":"unified",onModeChange:f=>{const F=f==="side-by-side"?"side-by-side":"inline";Ce(e.path,F)},className:"opacity-70"})]})]})}),u&&n.jsxs("div",{className:"relative overflow-hidden bg-background",children:[!x&&!W?n.jsx("div",{className:"h-40 border border-border/40 bg-background/40"}):null,W?n.jsxs("div",{className:"flex flex-col items-center gap-2 px-4 py-8 text-sm text-muted-foreground",children:[n.jsx("div",{className:"typography-ui-label font-semibold text-foreground",children:"Failed to load diff"}),n.jsx("div",{className:"typography-meta text-muted-foreground max-w-[32rem] text-center",children:W}),n.jsx("button",{type:"button",className:"typography-ui-label text-primary hover:underline",onClick:()=>Y(f=>f+1),children:"Retry"})]}):null,x&&re&&!M&&!W?n.jsxs("div",{className:"flex items-center justify-center gap-2 px-4 py-8 text-sm text-muted-foreground",children:[n.jsx(A,{name:"loader-4",className:"size-4 animate-spin"}),"Loading diff..."]}):null,x&&M&&!Z&&e.insertions+e.deletions>rt?n.jsxs("div",{className:"flex flex-col items-center gap-2 px-4 py-8 text-sm text-muted-foreground",children:[n.jsx("div",{className:"typography-ui-label font-semibold text-foreground",children:`Large diff (${e.insertions+e.deletions} changed lines)`}),n.jsx("div",{className:"typography-meta text-muted-foreground",children:"Rendering may be slow. You can still view the diff by clicking below."}),n.jsx("button",{type:"button",className:"typography-ui-label text-primary hover:underline",onClick:()=>Ie(!0),children:"Render anyway"})]}):null,x&&M&&(Z||e.insertions+e.deletions<=rt)?n.jsxs(n.Fragment,{children:[n.jsx(In,{filePath:e.path,diff:M,renderSideBySide:m,wrapLines:i}),Te?n.jsx("div",{className:"pointer-events-none absolute bottom-3 right-3 z-20",children:n.jsx("div",{className:"pointer-events-auto",children:n.jsx($n,{filePath:e.path,staged:w,busyAction:U,disabled:U!==null,onAction:De})})}):null]}):null]})]})}),Kr=({hideStackedFileSidebar:t=!1,stackedDefaultCollapsedAll:e=!1,pinSelectedFileHeaderToTopOnNavigate:a=!1,showOpenInEditorAction:i=!1,diffScope:c="all",onDiffScopeChange:u,branchBase:x=null,branchHead:b=null,targetFilePath:N=null,flushContent:v=!1})=>{const{git:h,files:S}=dt(),g=zt(),{screenWidth:w,isMobile:Te}=Gt(),Q=Ht(g??null),C=Ut(g??null),I=Kt(g??null),H=J(s=>s.setActiveDirectory),fe=J(s=>s.ensureStatus),me=J(s=>s.fetchStatus),Ce=J(s=>s.clearDiffCache),pe=J(s=>s.setDiff),[Y,W]=o.useState(null),[se,re]=o.useState(!1),[ie,U]=o.useState(null),[O,Z]=o.useState(()=>new Set),[Ie,K]=o.useState(()=>new Set),[V,Se]=o.useState(!1),[he,B]=o.useState(0),[Fe,oe]=o.useState(()=>new Map),[m,q]=o.useState(c),[z,M]=o.useState([]),[ge,xe]=o.useState(null),[Le,ee]=o.useState(!1);o.useEffect(()=>{q(c)},[c]);const X=_(s=>s.pendingDiffFile),De=_(s=>s.pendingDiffStaged),f=_(s=>s.pendingDiffScope),F=_(s=>s.setPendingDiffFile),G=_(s=>s.diffLayoutPreference),ke=_(s=>s.diffFileLayout),Re=_(s=>s.setDiffFileLayout),be=_(s=>s.diffWrapLines),$e=_(s=>s.setDiffWrapLines),R=_(s=>s.openContextFileAtLine),$=Vt(s=>s.currentSessionId),Ke=qt($??""),_e=be,Be=m==="staged"?!0:m==="working"?!1:null,Ee=Be??se,wt=Te||w<=768,jt=!t&&!wt&&w>=1024,ae=o.useRef(null),ye=o.useRef(new Map),te=o.useRef(null),k=o.useRef(null),le=o.useRef(!1),ce=o.useRef(null),Ve=o.useRef(null),Pe=o.useRef(null),We=o.useRef(null),qe=o.useCallback(()=>{const s=ae.current;if(!s)return null;const r=s.getBoundingClientRect().top,l=[];for(const[d,p]of ye.current)p&&l.push({path:d,top:p.getBoundingClientRect().top});return et(r,l)},[]),ue=o.useCallback(()=>{te.current=null,le.current=!1,U(null),k.current!==null&&(window.cancelAnimationFrame(k.current),k.current=null)},[]),de=o.useCallback(s=>{Z(r=>{if(r.has(s))return r;const l=new Set(r);return l.add(s),l})},[]),we=o.useMemo(()=>{const s=Xt(Ke,{showTextJustificationActivity:!1,showTurnChangedFiles:!0,mergeHiddenUserTurns:!0});for(let r=s.turns.length-1;r>=0;r-=1){const l=s.turns[r];if(!l)continue;const d=l.activityParts.map(y=>y.part).filter(y=>y.type==="tool"),p=Jt(d);if(p.length>0)return p.map(y=>({file:y.path,status:"modified",additions:y.additions,deletions:y.deletions,patch:y.patch}));const D=kn(l.userMessage.info.summary?.diffs);if(D.length>0)return D}return[]},[Ke]);o.useEffect(()=>{if(m!=="branch"||!g||!x||!b||!h.getGitRangeDiff){M([]),xe(null),ee(!1);return}let s=!1;return ee(!0),xe(null),h.getGitRangeDiff(g,{base:x,head:b,contextLines:gt}).then(r=>{s||(M(Rn(r.diff??"")),ee(!1))}).catch(r=>{s||(M([]),ee(!1),xe(r instanceof Error?r.message:String(r)))}),()=>{s=!0}},[m,x,b,g,h]);const vt=o.useMemo(()=>{const s=new Map;for(const r of we)if(r.file){if(typeof r.patch=="string"){s.set(r.file,Ue(r.file,r.patch,"patch"));continue}s.set(r.file,{original:r.before??"",modified:r.after??"",contextMode:"full"})}return s},[we]),Nt=o.useMemo(()=>{const s=new Map;for(const r of z)!r.file||typeof r.patch!="string"||s.set(r.file,Ue(r.file,r.patch,"patch"));return s},[z]),j=o.useMemo(()=>{if(m==="turn"||m==="branch")return(m==="branch"?z:we).map(d=>({path:d.file??"",index:"",working_dir:En(d.status),insertions:d.additions??0,deletions:d.deletions??0,isNew:d.status==="added"})).filter(d=>d.path).sort((d,p)=>d.path.localeCompare(p.path));if(!C?.files)return[];const s=C.diffStats??{},r=m==="staged"?ot:m==="working"?at:()=>!0;return C.files.filter(r).map(l=>({...l,insertions:s[l.path]?.insertions??0,deletions:s[l.path]?.deletions??0,isNew:Fn(l)})).sort((l,d)=>l.path.localeCompare(d.path))},[m,z,we,C]),Ct=o.useMemo(()=>C?.files?C.files.filter(at).length:0,[C]),St=o.useMemo(()=>C?.files?C.files.filter(ot).length:0,[C]),Ft=we.length,Lt=C?.files?.length??0,Dt=z.length,Oe=o.useMemo(()=>j.map(s=>s.path).join("\0"),[j]);o.useEffect(()=>{const s=Oe?Oe.split("\0"):[],r=new Set(s),l=`${g??""}:${m}:${e?"collapsed":"default"}`,d=Ve.current!==l;Ve.current=l,Z(p=>{if(d){const L=e?0:vn(s.length);return new Set(s.slice(0,L))}let D=!1;const y=new Set;for(const L of p){if(!r.has(L)){D=!0;continue}y.add(L)}return D?y:p}),K(p=>{if(d)return new Set;let D=!1;const y=new Set;for(const L of p){if(!r.has(L)){D=!0;continue}y.add(L)}return D?y:p})},[m,Oe,g,e]);const Xe=o.useCallback(()=>{ce.current=null;const s=ae.current;if(!s)return;const r=s.getBoundingClientRect(),l=r.top-it,d=r.bottom+it,p={},D=[];for(const[y,L]of ye.current){if(!L)continue;const E=L.getBoundingClientRect();D.push({path:y,top:E.top}),O.has(y)&&(E.bottom<l||E.top>d||(p[y]=!0))}Pe.current=et(r.top,D),K(y=>{let L=!1;const E=new Set(y);for(const Ye of Object.keys(p))E.has(Ye)||(E.add(Ye),L=!0);return L?E:y})},[O]),T=o.useCallback(()=>{typeof window>"u"||ce.current===null&&(ce.current=window.requestAnimationFrame(Xe))},[Xe]);o.useEffect(()=>{const s=ae.current;if(s)return T(),s.addEventListener("scroll",T,{passive:!0}),window.addEventListener("resize",T),()=>{s.removeEventListener("scroll",T),window.removeEventListener("resize",T),ce.current!==null&&(window.cancelAnimationFrame(ce.current),ce.current=null)}},[j,O,T]);const ze=o.useCallback(s=>{const r=ke[s.path];if(r)return r;if(G==="inline")return"inline";if(G==="side-by-side")return"side-by-side";const l=w<yn;return s.isNew||l?"inline":"side-by-side"},[ke,G,w]),Je=o.useMemo(()=>j.length===0?null:j.every(s=>ze(s)==="side-by-side")?"side-by-side":"inline",[j,ze]);o.useEffect(()=>{g&&(H(g),fe(g,h))},[g,H,fe,h]),o.useEffect(()=>{if(g)return Qt.onGitRefreshHint(s=>{lt(s.directory)===lt(g)&&(s.paths?.length&&(We.current=qe()??Pe.current,Ce(g,s.paths),oe(r=>{const l=new Map(r);for(const d of s.paths??[])l.set(d,(l.get(d)??0)+1);return l})),me(g,h,{silent:!0}))})},[qe,Ce,g,me,h]),o.useLayoutEffect(()=>{const s=We.current;if(!s)return;We.current=null;const r=ae.current,l=ye.current.get(s.path);if(!r||!l)return;const d=r.getBoundingClientRect().top,p=l.getBoundingClientRect().top-d;r.scrollTop=mn(r.scrollTop,s.topOffset,p,r.scrollHeight-r.clientHeight),Pe.current=s},[Fe]),o.useEffect(()=>{m!=="all"&&!f||X&&(f&&q(f),W(X),re(f==="staged"||!f&&De),F(null),le.current=!0,te.current=X,de(X),B(s=>s+1))},[m,de,X,f,De,F]),o.useEffect(()=>{if(m==="all")return;const s=N?.trim();s&&(W(s),re(m==="staged"),le.current=!0,te.current=s,de(s),B(r=>r+1))},[m,de,N]),o.useEffect(()=>{if(!Y)return;j.some(r=>r.path===Y)||(W(null),re(!1))},[j,Y]);const kt=o.useCallback((s,r)=>{const l=ye.current;r?l.set(s,r):l.delete(s),T()},[T]),Rt=o.useCallback((s,r)=>{ue(),Z(l=>{const d=l.has(s);if(r===d)return l;const p=new Set(l);return r?p.add(s):p.delete(s),p}),r||K(l=>{if(!l.has(s))return l;const d=new Set(l);return d.delete(s),d}),T()},[ue,T]),Et=o.useCallback(()=>{ue(),Z(s=>s.size>0?new Set:new Set(j.map(r=>r.path))),K(new Set),T()},[ue,j,T]),Ae=o.useCallback(s=>{const r=ye.current.get(s),l=ae.current;if(!r||!l)return!1;const d=r.getBoundingClientRect().top-l.getBoundingClientRect().top;return l.scrollTo({top:l.scrollTop+d,behavior:"auto"}),!0},[]);o.useEffect(()=>{if(!te.current)return;let r=0;const l=20;let d=!1;const p=(y=!0)=>{d||(d=!0,te.current=null,le.current=!1,y&&U(null),k.current!==null&&(window.cancelAnimationFrame(k.current),k.current=null))},D=()=>{if(d){k.current=null;return}const y=te.current;if(!y){p(),k.current=null;return}if(!Ae(y)){r+=1,r<l?k.current=window.requestAnimationFrame(D):(p(),k.current=null);return}if(a&&le.current){U(y),p(!1);return}p()};return k.current=window.requestAnimationFrame(D),()=>{d=!0,k.current!==null&&(window.cancelAnimationFrame(k.current),k.current=null)}},[a,he,Ae]);const At=o.useCallback(s=>{},[]),Mt=o.useCallback(s=>{ue(),W(s),re(!1),le.current=!0,te.current=s,de(s),B(r=>r+1),Ae(s)},[ue,de,Ae]),Tt=o.useCallback(s=>{const r=s==="side-by-side"?"side-by-side":"inline";j.forEach(l=>{Re(l.path,r)})},[j,Re]),[It,Qe]=o.useState(null),$t=o.useCallback(async(s,r)=>{if(!g||!s)return;Qe(s);const l=ut();try{let d=null;if(r?.patch&&!r.isBinary&&!ve(s)?d=st(r.patch):r&&r.contextMode==="full"&&!r.isBinary&&!ve(s)&&(d=ct(r.original,r.modified)),d===null)try{const E=await h.getGitDiff(g,{path:s,staged:Ee,contextLines:3});d=st(E.diff)}catch{d=null}let p=r;if(d===null||!p){const E=await h.getGitFileDiff(g,{path:s,staged:Ee});p={original:E.original??"",modified:E.modified??"",isBinary:E.isBinary},Ee||pe(g,s,p,l)}const D=d??(p.isBinary||ve(s)?1:ct(p.original,p.modified)),y=Ln(g,s),L=await cn(S,y,{directory:g});if(!L.ok){ft.error(un(L.reason));return}R(g,y,D,1)}finally{Qe(d=>d===s?null:d)}},[Ee,g,S,h,R,pe]),_t=()=>{if(!g)return null;const s=r=>Be!==null?Be:se&&r===Y;return n.jsxs("div",{className:P("flex min-w-0 flex-1 min-h-0 h-full",v?"gap-0":"gap-3 px-3 pb-3 pt-2"),children:[jt&&n.jsxs("section",{className:"hidden lg:flex w-72 flex-col rounded-xl border border-border/60 bg-background/70 overflow-hidden",children:[n.jsxs("div",{className:"flex items-center justify-between px-3 py-1.5 border-b border-border/40",children:[n.jsx("span",{className:"typography-ui-header font-semibold text-foreground",children:"Files"}),n.jsx("span",{className:"typography-meta text-muted-foreground",children:j.length})]}),n.jsx(Mn,{changedFiles:j,selectedFile:null,onSelectFile:Mt})]}),n.jsx("div",{className:"relative flex-1 min-w-0 min-h-0 h-full",children:n.jsx(pt,{ref:ae,outerClassName:"min-h-0 h-full",className:"[overflow-anchor:none] pb-16",disableHorizontal:!0,observeMutations:!1,preventOverscroll:!0,"data-diff-virtual-root":!0,children:n.jsx("div",{className:"flex flex-col [overflow-anchor:none]","data-diff-virtual-content":!0,children:j.map(r=>n.jsx(_n,{directory:g,file:r,layout:ze(r),wrapLines:_e,isSelected:!1,isExpanded:O.has(r.path),isMounted:Ie.has(r.path)||r.path===ie,onSelect:At,onExpandedChange:Rt,registerSectionRef:kt,showOpenInEditorAction:i&&m!=="turn"&&m!=="branch",isOpeningInEditor:It===r.path,onOpenInEditor:(l,d)=>{$t(l,d)},staged:s(r.path),showFileActions:m!=="turn"&&m!=="branch",loadFullFiles:V,initialDiffData:m==="turn"?vt.get(r.path)??null:m==="branch"?Nt.get(r.path)??null:null},`${r.path}:${Fe.get(r.path)??0}`))})})})]})},Bt=()=>g?m!=="turn"&&I&&!C?n.jsxs("div",{className:"flex flex-1 items-center justify-center gap-2 text-sm text-muted-foreground",children:[n.jsx(A,{name:"loader-4",className:"size-4 animate-spin"}),"Loading repository status..."]}):m!=="turn"&&m!=="branch"&&Q===!1?n.jsx("div",{className:"flex flex-1 items-center justify-center text-sm text-muted-foreground",children:"Not a git repository. Use the Git tab to initialize or change directories."}):m==="branch"&&Le?n.jsxs("div",{className:"flex flex-1 items-center justify-center gap-2 text-sm text-muted-foreground",children:[n.jsx(A,{name:"loader-4",className:"size-4 animate-spin"}),"Loading branch changes..."]}):m==="branch"&&ge?n.jsx("div",{className:"flex flex-1 items-center justify-center px-4 text-center text-sm text-muted-foreground",children:`Failed to load branch changes: ${ge}`}):j.length===0?n.jsx("div",{className:"flex flex-1 items-center justify-center text-sm text-muted-foreground",children:m==="turn"?"No last turn changes to display":"Working tree clean, no changes to display"}):_t():n.jsx("div",{className:"flex flex-1 items-center justify-center text-sm text-muted-foreground",children:"Select a session directory to view diffs"});return n.jsxs("div",{className:"flex h-full flex-col overflow-hidden bg-background",children:[n.jsxs("div",{className:"@container/diff-toolbar flex min-w-0 items-center gap-2 px-3 py-2 bg-background",children:[(Q!==!1||m==="turn")&&(m==="all"||m==="working"||m==="staged"||m==="turn"||m==="branch")?n.jsx(An,{scope:m,isGitRepo:Q,branchAvailable:!!(x&&b),allCount:Lt,workingCount:Ct,stagedCount:St,turnCount:Ft,branchCount:Dt,onScopeChange:s=>{q(s),u?.(s)}}):n.jsx("div",{className:"flex items-center gap-1 rounded-md px-2 py-1 text-muted-foreground shrink-0",children:n.jsx("span",{className:"typography-ui-label font-semibold text-foreground",children:I&&!C?"Loading changes...":j.length===1?`${j.length} file changed`:`${j.length} files changed`})}),j.length>0&&n.jsxs(Ne,{variant:"ghost",size:"sm",onClick:Et,className:P("diff-toolbar__expand-button h-7 flex-shrink-0 gap-1 px-1.5 text-muted-foreground hover:text-foreground","ml-auto"),title:O.size>0?"Collapse all":"Expand all",children:[n.jsx(A,{name:"expand-up-down",className:"size-4"}),n.jsx("span",{className:"diff-toolbar__expand-label typography-ui-label",children:O.size>0?"Collapse all":"Expand all"})]}),j.length>0&&m!=="turn"&&m!=="branch"&&n.jsxs(Yt,{children:[n.jsx(Zt,{asChild:!0,children:n.jsx(Ne,{variant:"ghost",size:"sm",onClick:()=>Se(s=>!s),"aria-pressed":V,"aria-label":V?"Unload full files":"Load full files",className:P("h-7 w-7 flex-shrink-0 p-0 text-muted-foreground hover:text-foreground",V&&"bg-interactive-selection text-interactive-selection-foreground"),children:n.jsx(A,{name:"file-download",className:"size-4"})})}),n.jsx(en,{children:n.jsx("p",{children:V?"Unload full files":"Load full files"})})]}),j.length>0&&n.jsx(Ne,{variant:"ghost",size:"sm",onClick:()=>$e(!be),className:P("h-5 w-5 p-0 transition-opacity",_e?"text-foreground opacity-100":"text-muted-foreground opacity-60 hover:opacity-100"),title:_e?"Disable line wrap":"Enable line wrap",children:n.jsx(A,{name:"text-wrap",className:"size-4"})}),Je&&n.jsx(mt,{mode:Je==="side-by-side"?"side-by-side":"unified",onModeChange:Tt})]}),Bt()]})};export{Kr as DiffView};
|