|
12 | 12 | import { DirectoryEntry, FileEntry, MultimodalFileInputState } from "$lib/components/files/index.svelte"; |
13 | 13 | import { SvelteSet } from "svelte/reactivity"; |
14 | 14 | import MultimodalFileInput from "$lib/components/files/MultimodalFileInput.svelte"; |
| 15 | + import { flip } from "svelte/animate"; |
15 | 16 |
|
16 | 17 | const viewer = MultiFileDiffViewerState.get(); |
17 | 18 | let modalOpen = $state(false); |
|
20 | 21 |
|
21 | 22 | let patchFile = $state<MultimodalFileInputState | undefined>(); |
22 | 23 |
|
23 | | - let fileA = $state<MultimodalFileInputState | undefined>(); |
24 | | - let fileB = $state<MultimodalFileInputState | undefined>(); |
| 24 | + let fileOne = $state<MultimodalFileInputState | undefined>(); |
| 25 | + let fileTwo = $state<MultimodalFileInputState | undefined>(); |
| 26 | + let flipFiles = $state(["1", "arrow", "2"]); |
25 | 27 |
|
26 | | - let dirA = $state<DirectoryEntry | undefined>(); |
27 | | - let dirB = $state<DirectoryEntry | undefined>(); |
| 28 | + let dirOne = $state<DirectoryEntry | undefined>(); |
| 29 | + let dirTwo = $state<DirectoryEntry | undefined>(); |
| 30 | + let flipDirs = $state(["1", "arrow", "2"]); |
28 | 31 | let dirBlacklistInput = $state<string>(""); |
29 | 32 | const defaultDirBlacklist = [".git/"]; |
30 | 33 | let dirBlacklist = new SvelteSet(defaultDirBlacklist); |
|
57 | 60 | }); |
58 | 61 |
|
59 | 62 | async function compareFiles() { |
| 63 | + const fileA = flipFiles[0] === "1" ? fileOne : fileTwo; |
| 64 | + const fileB = flipFiles[0] === "1" ? fileTwo : fileOne; |
60 | 65 | if (!fileA || !fileB || !fileA.metadata || !fileB.metadata) { |
61 | 66 | alert("Both files must be selected to compare."); |
62 | 67 | return; |
|
131 | 136 | }; |
132 | 137 |
|
133 | 138 | async function compareDirs() { |
| 139 | + const dirA = flipDirs[0] === "1" ? dirOne : dirTwo; |
| 140 | + const dirB = flipDirs[0] === "1" ? dirTwo : dirOne; |
134 | 141 | if (!dirA || !dirB) { |
135 | 142 | alert("Both directories must be selected to compare."); |
136 | 143 | return; |
|
378 | 385 | {/snippet} |
379 | 386 |
|
380 | 387 | <Dialog.Root bind:open={modalOpen}> |
381 | | - <Dialog.Trigger class="h-fit rounded-md btn-primary px-2 py-0.5">Load another diff</Dialog.Trigger> |
| 388 | + <Dialog.Trigger class="h-fit rounded-md btn-primary px-2 py-0.5">Open new diff</Dialog.Trigger> |
382 | 389 | <Dialog.Portal> |
383 | 390 | <Dialog.Overlay class="fixed inset-0 z-50 bg-black/50 dark:bg-white/20" /> |
384 | 391 | <Dialog.Content |
385 | 392 | class="fixed top-1/2 left-1/2 z-50 max-h-svh w-192 max-w-full -translate-x-1/2 -translate-y-1/2 overflow-y-auto rounded-md bg-neutral shadow-md sm:max-w-[95%]" |
386 | 393 | > |
387 | 394 | <header class="sticky top-0 z-10 flex flex-row items-center justify-between rounded-t-md bg-neutral-2 p-4"> |
388 | | - <Dialog.Title class="text-xl font-semibold">Load a diff</Dialog.Title> |
| 395 | + <Dialog.Title class="text-xl font-semibold">Open New Diff</Dialog.Title> |
389 | 396 | <Dialog.Close title="Close dialog" class="flex size-6 items-center justify-center rounded-md btn-ghost text-primary"> |
390 | 397 | <span class="iconify octicon--x-16" aria-hidden="true"></span> |
391 | 398 | </Dialog.Close> |
392 | 399 | </header> |
393 | 400 |
|
394 | 401 | <section class="flex flex-col p-4"> |
395 | | - <h3 class="mb-2 flex items-center gap-1 text-lg font-semibold"> |
| 402 | + <h3 class="mb-4 flex items-center gap-1 text-lg font-semibold"> |
396 | 403 | <span class="iconify size-6 shrink-0 octicon--mark-github-24"></span> |
397 | 404 | From GitHub |
398 | 405 | </h3> |
|
460 | 467 | handlePatchFile(); |
461 | 468 | }} |
462 | 469 | > |
463 | | - <h3 class="mb-2 flex items-center gap-1 text-lg font-semibold"> |
| 470 | + <h3 class="mb-4 flex items-center gap-1 text-lg font-semibold"> |
464 | 471 | <span class="iconify size-6 shrink-0 octicon--file-diff-24"></span> |
465 | 472 | From Patch File |
466 | 473 | </h3> |
467 | | - <MultimodalFileInput bind:state={patchFile} required fileTypeOverride={false} label="Patch File" /> |
| 474 | + <MultimodalFileInput bind:state={patchFile} required fileTypeOverride={false} defaultMode="file" label="Patch File" /> |
468 | 475 | <Button.Root type="submit" class="mt-2 rounded-md btn-primary px-2 py-1">Go</Button.Root> |
469 | 476 | </form> |
470 | 477 |
|
|
477 | 484 | compareFiles(); |
478 | 485 | }} |
479 | 486 | > |
480 | | - <h3 class="mb-2 flex items-center gap-1 text-lg font-semibold"> |
| 487 | + <h3 class="mb-4 flex items-center gap-1 text-lg font-semibold"> |
481 | 488 | <span class="iconify size-6 shrink-0 octicon--file-24"></span> |
482 | 489 | From Files |
483 | 490 | </h3> |
484 | | - <div class="mb-2 flex flex-wrap items-center gap-1"> |
485 | | - <MultimodalFileInput bind:state={fileA} required label="File A" /> |
486 | | - <div class="flex w-full"> |
487 | | - <span class="iconify size-4 shrink-0 octicon--arrow-down-16"></span> |
488 | | - </div> |
489 | | - <MultimodalFileInput bind:state={fileB} required label="File B" /> |
| 491 | + <div class="mb-2 flex flex-col gap-1"> |
| 492 | + {#each flipFiles as id, index (id)} |
| 493 | + <div animate:flip={{ duration: 250 }}> |
| 494 | + {#if id === "1"} |
| 495 | + <MultimodalFileInput bind:state={fileOne} required label={index === 0 ? "File A" : "File B"} /> |
| 496 | + {:else if id === "arrow"} |
| 497 | + <div class="flex w-full"> |
| 498 | + <span class="iconify size-4 shrink-0 octicon--arrow-down-16"></span> |
| 499 | + </div> |
| 500 | + {:else if id === "2"} |
| 501 | + <MultimodalFileInput bind:state={fileTwo} required label={index === 2 ? "File B" : "File A"} /> |
| 502 | + {/if} |
| 503 | + </div> |
| 504 | + {/each} |
490 | 505 | </div> |
491 | 506 | <div class="flex items-center gap-1"> |
492 | 507 | <Button.Root type="submit" class="rounded-md btn-primary px-2 py-1">Go</Button.Root> |
|
495 | 510 | type="button" |
496 | 511 | class="flex size-6 items-center justify-center rounded-md btn-primary" |
497 | 512 | onclick={() => { |
498 | | - if (!fileA || !fileB) return; |
499 | | - fileA.swapState(fileB); |
| 513 | + const a = flipFiles[0]; |
| 514 | + flipFiles[0] = flipFiles[2]; |
| 515 | + flipFiles[2] = a; |
500 | 516 | }} |
501 | 517 | > |
502 | 518 | <span class="iconify size-4 shrink-0 octicon--arrow-switch-16" aria-hidden="true"></span> |
|
513 | 529 | compareDirs(); |
514 | 530 | }} |
515 | 531 | > |
516 | | - <h3 class="mb-2 flex items-center gap-1 text-lg font-semibold"> |
| 532 | + <h3 class="mb-4 flex items-center gap-1 text-lg font-semibold"> |
517 | 533 | <span class="iconify size-6 shrink-0 octicon--file-directory-24"></span> |
518 | 534 | From Directories |
519 | 535 | <InfoPopup> |
|
522 | 538 | button should be preferred. |
523 | 539 | </InfoPopup> |
524 | 540 | </h3> |
525 | | - <div class="flex flex-wrap items-center gap-1"> |
526 | | - <DirectorySelect bind:directory={dirA} placeholder="Directory A" /> |
527 | | - <span class="iconify size-4 shrink-0 octicon--arrow-right-16"></span> |
528 | | - <DirectorySelect bind:directory={dirB} placeholder="Directory B" /> |
| 541 | + <div class="mb-2 flex w-full flex-col gap-1"> |
| 542 | + {#each flipDirs as id, index (id)} |
| 543 | + <div animate:flip={{ duration: 250 }} class="flex"> |
| 544 | + {#if id === "1"} |
| 545 | + <DirectorySelect bind:directory={dirOne} placeholder={index === 0 ? "Directory A" : "Directory B"} /> |
| 546 | + {:else if id === "arrow"} |
| 547 | + <span class="iconify size-4 shrink-0 octicon--arrow-down-16"></span> |
| 548 | + {:else if id === "2"} |
| 549 | + <DirectorySelect bind:directory={dirTwo} placeholder={index === 2 ? "Directory B" : "Directory A"} /> |
| 550 | + {/if} |
| 551 | + </div> |
| 552 | + {/each} |
| 553 | + </div> |
| 554 | + <div class="flex items-center gap-1"> |
529 | 555 | <Button.Root type="submit" class="rounded-md btn-primary px-2 py-1">Go</Button.Root> |
530 | 556 | <Popover.Root> |
531 | 557 | <Popover.Trigger |
|
541 | 567 | </Popover.Content> |
542 | 568 | </Popover.Portal> |
543 | 569 | </Popover.Root> |
| 570 | + <Button.Root |
| 571 | + title="Swap Directory A and Directory B" |
| 572 | + type="button" |
| 573 | + class="flex size-6 items-center justify-center rounded-md btn-primary" |
| 574 | + onclick={() => { |
| 575 | + const a = flipDirs[0]; |
| 576 | + flipDirs[0] = flipDirs[2]; |
| 577 | + flipDirs[2] = a; |
| 578 | + }} |
| 579 | + > |
| 580 | + <span class="iconify size-4 shrink-0 octicon--arrow-switch-16" aria-hidden="true"></span> |
| 581 | + </Button.Root> |
544 | 582 | </div> |
545 | 583 | </form> |
546 | 584 | </Dialog.Content> |
|
0 commit comments