@thxgg/steward 0.1.19 → 0.1.21

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.
Files changed (111) hide show
  1. package/.output/nitro.json +1 -1
  2. package/.output/public/_nuxt/{CCruYste.js → B3PShd4B.js} +1 -1
  3. package/.output/public/_nuxt/{C9jB6HQI.js → B7kcsnX1.js} +1 -1
  4. package/.output/public/_nuxt/{CIIE0-WR.js → B9j1BHt9.js} +1 -1
  5. package/.output/public/_nuxt/{xc3v2JZH.js → BGSfDLaX.js} +1 -1
  6. package/.output/public/_nuxt/{BfV4oCiT.js → BTHAQvnA.js} +1 -1
  7. package/.output/public/_nuxt/{f7vKgp5U.js → C2LWefrW.js} +1 -1
  8. package/.output/public/_nuxt/{DddVAa3N.js → CV5HFGKm.js} +1 -1
  9. package/.output/public/_nuxt/{Bs6UO7IT.js → ClxxfTZn.js} +1 -1
  10. package/.output/public/_nuxt/{DEekox9p.js → CzCDTesu.js} +1 -1
  11. package/.output/public/_nuxt/{D30YtxUg.js → D6aZT905.js} +1 -1
  12. package/.output/public/_nuxt/{MO41rxll.js → D9fz0wy8.js} +1 -1
  13. package/.output/public/_nuxt/{BfUfZSFp.js → DDV2bymk.js} +1 -1
  14. package/.output/public/_nuxt/{C9AsKFSQ.js → DK5VWQk7.js} +1 -1
  15. package/.output/public/_nuxt/{D2RLSKEu.js → DSqaInP-.js} +1 -1
  16. package/.output/public/_nuxt/Detail.CYc96mGf.css +1 -0
  17. package/.output/public/_nuxt/{BCiXS3ZV.js → Dn6yoG20.js} +2 -2
  18. package/.output/public/_nuxt/{Cg4hnDua.js → a87LfEfa.js} +1 -1
  19. package/.output/public/_nuxt/builds/latest.json +1 -1
  20. package/.output/public/_nuxt/builds/meta/c98d132b-2ccd-4cf3-88e6-4f203447e539.json +1 -0
  21. package/.output/public/_nuxt/zhOijcjw.js +30 -0
  22. package/.output/server/chunks/_/git-api.mjs +10 -23
  23. package/.output/server/chunks/_/git-api.mjs.map +1 -1
  24. package/.output/server/chunks/_/prd-service.mjs +1 -3
  25. package/.output/server/chunks/_/prd-service.mjs.map +1 -1
  26. package/.output/server/chunks/_/watcher.mjs +1 -2
  27. package/.output/server/chunks/_/watcher.mjs.map +1 -1
  28. package/.output/server/chunks/build/{Detail-BcQGdJY5.mjs → Detail-B7yBNjgp.mjs} +321 -136
  29. package/.output/server/chunks/build/Detail-B7yBNjgp.mjs.map +1 -0
  30. package/.output/server/chunks/build/DiffViewer-styles-1.mjs-d2dQvARr.mjs +4 -0
  31. package/.output/server/chunks/build/DiffViewer-styles-1.mjs-d2dQvARr.mjs.map +1 -0
  32. package/.output/server/chunks/build/DiffViewer-styles.BDwAqkTk.mjs +8 -0
  33. package/.output/server/chunks/build/DiffViewer-styles.BDwAqkTk.mjs.map +1 -0
  34. package/.output/server/chunks/build/DiffViewer-styles.DRJh5Ui4.mjs +10 -0
  35. package/.output/server/chunks/build/DiffViewer-styles.DRJh5Ui4.mjs.map +1 -0
  36. package/.output/server/chunks/build/{_prd_-CD_Bds_B.mjs → _prd_-DY25apyl.mjs} +4 -3
  37. package/.output/server/chunks/build/_prd_-DY25apyl.mjs.map +1 -0
  38. package/.output/server/chunks/build/client.precomputed.mjs +1 -1
  39. package/.output/server/chunks/build/default-BKKgG7HJ.mjs +2 -1
  40. package/.output/server/chunks/build/error-404-Bf6kdO80.mjs +2 -1
  41. package/.output/server/chunks/build/error-500-D_bcARXN.mjs +2 -1
  42. package/.output/server/chunks/build/index-DE1tjHAd.mjs +2 -1
  43. package/.output/server/chunks/build/nuxt-link-SvT1nf8Z.mjs +1 -1
  44. package/.output/server/chunks/build/{repo-graph-CBfhpnd5.mjs → repo-graph-CUcJKW1F.mjs} +4 -3
  45. package/.output/server/chunks/build/repo-graph-CUcJKW1F.mjs.map +1 -0
  46. package/.output/server/chunks/build/server.mjs +5 -4
  47. package/.output/server/chunks/build/styles.mjs +4 -4
  48. package/.output/server/chunks/build/usePrd-hXZOmvAv.mjs +1 -1
  49. package/.output/server/chunks/nitro/nitro.mjs +1514 -694
  50. package/.output/server/chunks/nitro/nitro.mjs.map +1 -1
  51. package/.output/server/chunks/routes/api/browse.get.mjs +1 -0
  52. package/.output/server/chunks/routes/api/browse.get.mjs.map +1 -1
  53. package/.output/server/chunks/routes/api/index.get.mjs +3 -3
  54. package/.output/server/chunks/routes/api/index.post.mjs +2 -2
  55. package/.output/server/chunks/routes/api/repos/_repoId/git/commits.get.mjs +3 -5
  56. package/.output/server/chunks/routes/api/repos/_repoId/git/commits.get.mjs.map +1 -1
  57. package/.output/server/chunks/routes/api/repos/_repoId/git/diff.get.mjs +3 -5
  58. package/.output/server/chunks/routes/api/repos/_repoId/git/diff.get.mjs.map +1 -1
  59. package/.output/server/chunks/routes/api/repos/_repoId/git/file-content.get.mjs +3 -5
  60. package/.output/server/chunks/routes/api/repos/_repoId/git/file-content.get.mjs.map +1 -1
  61. package/.output/server/chunks/routes/api/repos/_repoId/git/file-diff.get.mjs +3 -5
  62. package/.output/server/chunks/routes/api/repos/_repoId/git/file-diff.get.mjs.map +1 -1
  63. package/.output/server/chunks/routes/api/repos/_repoId/graph.get.mjs +3 -5
  64. package/.output/server/chunks/routes/api/repos/_repoId/graph.get.mjs.map +1 -1
  65. package/.output/server/chunks/routes/api/repos/_repoId/prd/_prdSlug/archive.post.mjs +2 -4
  66. package/.output/server/chunks/routes/api/repos/_repoId/prd/_prdSlug/archive.post.mjs.map +1 -1
  67. package/.output/server/chunks/routes/api/repos/_repoId/prd/_prdSlug/graph.get.mjs +3 -5
  68. package/.output/server/chunks/routes/api/repos/_repoId/prd/_prdSlug/graph.get.mjs.map +1 -1
  69. package/.output/server/chunks/routes/api/repos/_repoId/prd/_prdSlug/progress.get.mjs +3 -5
  70. package/.output/server/chunks/routes/api/repos/_repoId/prd/_prdSlug/progress.get.mjs.map +1 -1
  71. package/.output/server/chunks/routes/api/repos/_repoId/prd/_prdSlug/tasks/_taskId/commits.get.mjs +3 -5
  72. package/.output/server/chunks/routes/api/repos/_repoId/prd/_prdSlug/tasks/_taskId/commits.get.mjs.map +1 -1
  73. package/.output/server/chunks/routes/api/repos/_repoId/prd/_prdSlug/tasks.get.mjs +3 -5
  74. package/.output/server/chunks/routes/api/repos/_repoId/prd/_prdSlug/tasks.get.mjs.map +1 -1
  75. package/.output/server/chunks/routes/api/repos/_repoId/prd/_prdSlug_.get.mjs +3 -5
  76. package/.output/server/chunks/routes/api/repos/_repoId/prd/_prdSlug_.get.mjs.map +1 -1
  77. package/.output/server/chunks/routes/api/repos/_repoId/prds.get.mjs +3 -5
  78. package/.output/server/chunks/routes/api/repos/_repoId/prds.get.mjs.map +1 -1
  79. package/.output/server/chunks/routes/api/repos/_repoId/refresh-git-repos.post.mjs +3 -3
  80. package/.output/server/chunks/routes/api/repos/_repoId_.delete.mjs +3 -3
  81. package/.output/server/chunks/routes/api/runtime.get.mjs +3 -2
  82. package/.output/server/chunks/routes/api/runtime.get.mjs.map +1 -1
  83. package/.output/server/chunks/routes/api/state-migration/status.get.mjs +3 -2
  84. package/.output/server/chunks/routes/api/state-migration/status.get.mjs.map +1 -1
  85. package/.output/server/chunks/routes/api/watch.get.mjs +3 -3
  86. package/.output/server/chunks/routes/renderer.mjs +1 -1
  87. package/.output/server/index.mjs +3 -2
  88. package/.output/server/index.mjs.map +1 -1
  89. package/.output/server/package.json +1 -1
  90. package/dist/app/lib/async-request.js +39 -0
  91. package/dist/host/src/api/git.js +14 -7
  92. package/dist/server/utils/git-repo-path.js +63 -0
  93. package/dist/server/utils/git.js +26 -9
  94. package/dist/server/utils/state-migration.js +206 -0
  95. package/package.json +1 -1
  96. package/.output/public/_nuxt/CwdD8083.js +0 -30
  97. package/.output/public/_nuxt/Detail.DSyVQNdr.css +0 -1
  98. package/.output/public/_nuxt/builds/meta/627332c0-2e14-4849-8cac-e350f64ed513.json +0 -1
  99. package/.output/server/chunks/_/git.mjs +0 -296
  100. package/.output/server/chunks/_/git.mjs.map +0 -1
  101. package/.output/server/chunks/_/repos.mjs +0 -272
  102. package/.output/server/chunks/_/repos.mjs.map +0 -1
  103. package/.output/server/chunks/build/Detail-BcQGdJY5.mjs.map +0 -1
  104. package/.output/server/chunks/build/DiffViewer-styles-1.mjs-BFsE2PCW.mjs +0 -4
  105. package/.output/server/chunks/build/DiffViewer-styles-1.mjs-BFsE2PCW.mjs.map +0 -1
  106. package/.output/server/chunks/build/DiffViewer-styles.D2bqX3nK.mjs +0 -8
  107. package/.output/server/chunks/build/DiffViewer-styles.D2bqX3nK.mjs.map +0 -1
  108. package/.output/server/chunks/build/DiffViewer-styles.FoV36wuV.mjs +0 -10
  109. package/.output/server/chunks/build/DiffViewer-styles.FoV36wuV.mjs.map +0 -1
  110. package/.output/server/chunks/build/_prd_-CD_Bds_B.mjs.map +0 -1
  111. package/.output/server/chunks/build/repo-graph-CBfhpnd5.mjs.map +0 -1
@@ -1,4 +1,4 @@
1
- import { defineComponent, unref, mergeProps, withCtx, renderSlot, markRaw, ref, watch, computed, createVNode, useModel, createTextVNode, toDisplayString, openBlock, createBlock, createCommentVNode, resolveDynamicComponent, Fragment, renderList, mergeModels, readonly, useSSRContext } from 'vue';
1
+ import { defineComponent, unref, mergeProps, withCtx, renderSlot, markRaw, ref, watch, computed, createVNode, useModel, createTextVNode, toDisplayString, openBlock, createBlock, createCommentVNode, resolveDynamicComponent, Fragment, renderList, mergeModels, useSSRContext } from 'vue';
2
2
  import { ssrRenderComponent, ssrRenderSlot, ssrRenderAttrs, ssrInterpolate, ssrRenderVNode, ssrRenderList, ssrRenderClass, ssrRenderAttr, ssrRenderStyle } from 'vue/server-renderer';
3
3
  import { reactiveOmit, useMediaQuery } from '@vueuse/core';
4
4
  import { Background } from '@vue-flow/background';
@@ -582,6 +582,14 @@ const _sfc_main$j = /* @__PURE__ */ defineComponent({
582
582
  ref(null);
583
583
  ref(null);
584
584
  ref(false);
585
+ let fullFileHighlightRunVersion = 0;
586
+ let diffHighlightRunVersion = 0;
587
+ watch(
588
+ () => props.filePath,
589
+ () => {
590
+ showAll.value = false;
591
+ }
592
+ );
585
593
  const totalLines = computed(() => {
586
594
  let count = 0;
587
595
  for (const hunk of props.hunks) {
@@ -671,6 +679,7 @@ const _sfc_main$j = /* @__PURE__ */ defineComponent({
671
679
  }
672
680
  const displayItems = computed(() => {
673
681
  const items = [];
682
+ const idPrefix = props.filePath;
674
683
  for (let hunkIndex = 0; hunkIndex < props.hunks.length; hunkIndex++) {
675
684
  const hunk = props.hunks[hunkIndex];
676
685
  if (hunkIndex > 0) {
@@ -684,7 +693,7 @@ const _sfc_main$j = /* @__PURE__ */ defineComponent({
684
693
  items.push({
685
694
  type: "line",
686
695
  pair: {
687
- id: `${hunkIndex}-${i}`,
696
+ id: `${idPrefix}:${hunkIndex}-${i}`,
688
697
  left: {
689
698
  lineNum: line.oldNumber,
690
699
  content: line.content,
@@ -716,7 +725,7 @@ const _sfc_main$j = /* @__PURE__ */ defineComponent({
716
725
  items.push({
717
726
  type: "line",
718
727
  pair: {
719
- id: `${hunkIndex}-${i - maxLen + j}`,
728
+ id: `${idPrefix}:${hunkIndex}-${i - maxLen + j}`,
720
729
  left: removeLine ? {
721
730
  lineNum: removeLine.oldNumber,
722
731
  content: removeLine.content,
@@ -734,7 +743,7 @@ const _sfc_main$j = /* @__PURE__ */ defineComponent({
734
743
  items.push({
735
744
  type: "line",
736
745
  pair: {
737
- id: `${hunkIndex}-${i}`,
746
+ id: `${idPrefix}:${hunkIndex}-${i}`,
738
747
  left: { content: "", type: "empty" },
739
748
  right: {
740
749
  lineNum: line.newNumber,
@@ -813,72 +822,109 @@ const _sfc_main$j = /* @__PURE__ */ defineComponent({
813
822
  const isLoadingFullFile = ref(false);
814
823
  watch(
815
824
  () => [props.fileContent, props.filePath],
816
- async ([content]) => {
825
+ async ([content], _, onCleanup) => {
826
+ const runVersion = ++fullFileHighlightRunVersion;
827
+ let invalidated = false;
828
+ onCleanup(() => {
829
+ invalidated = true;
830
+ });
831
+ highlightedFullFile.value = [];
817
832
  if (!content) {
818
- highlightedFullFile.value = [];
833
+ isLoadingFullFile.value = false;
819
834
  return;
820
835
  }
821
836
  isLoadingFullFile.value = true;
822
- const lang = language.value;
823
- highlightedFullFile.value = await highlightFullContent(content, lang);
824
- isLoadingFullFile.value = false;
837
+ try {
838
+ const highlighted = await highlightFullContent(content, language.value);
839
+ if (invalidated || runVersion !== fullFileHighlightRunVersion) {
840
+ return;
841
+ }
842
+ highlightedFullFile.value = highlighted;
843
+ } finally {
844
+ if (!invalidated && runVersion === fullFileHighlightRunVersion) {
845
+ isLoadingFullFile.value = false;
846
+ }
847
+ }
825
848
  },
826
849
  { immediate: true }
827
850
  );
828
851
  watch(
829
852
  () => [props.hunks, props.filePath, highlightedFullFile.value],
830
- async () => {
853
+ async (_, __, onCleanup) => {
854
+ const runVersion = ++diffHighlightRunVersion;
855
+ let invalidated = false;
856
+ onCleanup(() => {
857
+ invalidated = true;
858
+ });
831
859
  isLoading.value = true;
860
+ highlightedLines.value = /* @__PURE__ */ new Map();
832
861
  const lang = language.value;
833
862
  const newHighlighted = /* @__PURE__ */ new Map();
834
863
  const fullFileLines2 = highlightedFullFile.value;
835
864
  const linesToHighlight = [];
836
- for (const item of displayItems.value) {
837
- if (item.type === "line" && item.pair) {
838
- if (item.pair.left.content && item.pair.left.type !== "empty") {
839
- const key = `${item.pair.id}-old`;
840
- if (item.pair.left.type === "context" && item.pair.left.lineNum && fullFileLines2.length > 0) {
841
- const lineIndex = item.pair.right.lineNum ? item.pair.right.lineNum - 1 : -1;
842
- if (lineIndex >= 0 && lineIndex < fullFileLines2.length) {
843
- newHighlighted.set(key, fullFileLines2[lineIndex] || "");
865
+ try {
866
+ for (const item of displayItems.value) {
867
+ if (invalidated || runVersion !== diffHighlightRunVersion) {
868
+ return;
869
+ }
870
+ if (item.type === "line" && item.pair) {
871
+ if (item.pair.left.content && item.pair.left.type !== "empty") {
872
+ const key = `${item.pair.id}-old`;
873
+ if (item.pair.left.type === "context" && item.pair.left.lineNum && fullFileLines2.length > 0) {
874
+ const lineIndex = item.pair.right.lineNum ? item.pair.right.lineNum - 1 : -1;
875
+ if (lineIndex >= 0 && lineIndex < fullFileLines2.length) {
876
+ newHighlighted.set(key, fullFileLines2[lineIndex] || "");
877
+ } else {
878
+ linesToHighlight.push({ key, content: item.pair.left.content });
879
+ }
844
880
  } else {
845
881
  linesToHighlight.push({ key, content: item.pair.left.content });
846
882
  }
847
- } else {
848
- linesToHighlight.push({ key, content: item.pair.left.content });
849
883
  }
850
- }
851
- if (item.pair.right.content && item.pair.right.type !== "empty") {
852
- const key = `${item.pair.id}-new`;
853
- const lineNum = item.pair.right.lineNum;
854
- if (lineNum && fullFileLines2.length > 0 && lineNum <= fullFileLines2.length) {
855
- newHighlighted.set(key, fullFileLines2[lineNum - 1] || "");
856
- } else {
857
- linesToHighlight.push({ key, content: item.pair.right.content });
884
+ if (item.pair.right.content && item.pair.right.type !== "empty") {
885
+ const key = `${item.pair.id}-new`;
886
+ const lineNum = item.pair.right.lineNum;
887
+ if (lineNum && fullFileLines2.length > 0 && lineNum <= fullFileLines2.length) {
888
+ newHighlighted.set(key, fullFileLines2[lineNum - 1] || "");
889
+ } else {
890
+ linesToHighlight.push({ key, content: item.pair.right.content });
891
+ }
858
892
  }
859
893
  }
860
894
  }
861
- }
862
- const limitedLines = linesToHighlight.slice(0, MAX_DIFF_HIGHLIGHT_LINES);
863
- const overflowLines = linesToHighlight.slice(MAX_DIFF_HIGHLIGHT_LINES);
864
- for (const { key, content } of overflowLines) {
865
- newHighlighted.set(key, escapeHtml(content));
866
- }
867
- const batchSize = 50;
868
- for (let i = 0; i < limitedLines.length; i += batchSize) {
869
- const batch = limitedLines.slice(i, i + batchSize);
870
- const results = await Promise.all(
871
- batch.map(async ({ key, content }) => {
872
- const result = await highlightLine(content, lang);
873
- return { key, result };
874
- })
875
- );
876
- for (const { key, result } of results) {
877
- newHighlighted.set(key, result);
895
+ const limitedLines = linesToHighlight.slice(0, MAX_DIFF_HIGHLIGHT_LINES);
896
+ const overflowLines = linesToHighlight.slice(MAX_DIFF_HIGHLIGHT_LINES);
897
+ for (const { key, content } of overflowLines) {
898
+ newHighlighted.set(key, escapeHtml(content));
899
+ }
900
+ const batchSize = 50;
901
+ for (let i = 0; i < limitedLines.length; i += batchSize) {
902
+ if (invalidated || runVersion !== diffHighlightRunVersion) {
903
+ return;
904
+ }
905
+ const batch = limitedLines.slice(i, i + batchSize);
906
+ const results = await Promise.all(
907
+ batch.map(async ({ key, content }) => {
908
+ const result = await highlightLine(content, lang);
909
+ return { key, result };
910
+ })
911
+ );
912
+ if (invalidated || runVersion !== diffHighlightRunVersion) {
913
+ return;
914
+ }
915
+ for (const { key, result } of results) {
916
+ newHighlighted.set(key, result);
917
+ }
918
+ }
919
+ if (invalidated || runVersion !== diffHighlightRunVersion) {
920
+ return;
921
+ }
922
+ highlightedLines.value = newHighlighted;
923
+ } finally {
924
+ if (!invalidated && runVersion === diffHighlightRunVersion) {
925
+ isLoading.value = false;
878
926
  }
879
927
  }
880
- highlightedLines.value = newHighlighted;
881
- isLoading.value = false;
882
928
  },
883
929
  { immediate: true }
884
930
  );
@@ -890,21 +936,21 @@ const _sfc_main$j = /* @__PURE__ */ defineComponent({
890
936
  return "context";
891
937
  }
892
938
  return (_ctx, _push, _parent, _attrs) => {
893
- _push(`<div${ssrRenderAttrs(mergeProps({ class: "diff-viewer" }, _attrs))} data-v-a5da7e6e>`);
939
+ _push(`<div${ssrRenderAttrs(mergeProps({ class: "diff-viewer" }, _attrs))} data-v-9eb8ced7>`);
894
940
  if ((unref(isLoading) || __props.isLoadingContent || unref(isLoadingFullFile)) && !__props.binary) {
895
- _push(`<div class="flex items-center justify-center py-8" data-v-a5da7e6e><div class="size-6 animate-spin rounded-full border-2 border-primary border-t-transparent" data-v-a5da7e6e></div></div>`);
941
+ _push(`<div class="flex items-center justify-center py-8" data-v-9eb8ced7><div class="size-6 animate-spin rounded-full border-2 border-primary border-t-transparent" data-v-9eb8ced7></div></div>`);
896
942
  } else if (__props.binary) {
897
- _push(`<div class="flex flex-col items-center justify-center gap-3 py-12 text-muted-foreground" data-v-a5da7e6e>`);
943
+ _push(`<div class="flex flex-col items-center justify-center gap-3 py-12 text-muted-foreground" data-v-9eb8ced7>`);
898
944
  _push(ssrRenderComponent(unref(FileWarning), { class: "size-10 opacity-50" }, null, _parent));
899
- _push(`<div class="text-center" data-v-a5da7e6e><p class="font-medium" data-v-a5da7e6e>Binary file</p><p class="text-sm" data-v-a5da7e6e>This file cannot be displayed as a diff</p></div></div>`);
945
+ _push(`<div class="text-center" data-v-9eb8ced7><p class="font-medium" data-v-9eb8ced7>Binary file</p><p class="text-sm" data-v-9eb8ced7>This file cannot be displayed as a diff</p></div></div>`);
900
946
  } else if (unref(isEmpty) && !__props.showFullFile) {
901
- _push(`<div class="flex flex-col items-center justify-center gap-3 py-12 text-muted-foreground" data-v-a5da7e6e>`);
947
+ _push(`<div class="flex flex-col items-center justify-center gap-3 py-12 text-muted-foreground" data-v-9eb8ced7>`);
902
948
  _push(ssrRenderComponent(unref(AlertTriangle), { class: "size-10 opacity-50" }, null, _parent));
903
- _push(`<div class="text-center" data-v-a5da7e6e><p class="font-medium" data-v-a5da7e6e>No changes</p><p class="text-sm" data-v-a5da7e6e>This file was touched but has no content changes</p></div></div>`);
949
+ _push(`<div class="text-center" data-v-9eb8ced7><p class="font-medium" data-v-9eb8ced7>No changes</p><p class="text-sm" data-v-9eb8ced7>This file was touched but has no content changes</p></div></div>`);
904
950
  } else if (unref(isLargeFile) && !unref(showAll) && !__props.showFullFile) {
905
- _push(`<div class="diff-container" data-v-a5da7e6e><div class="flex flex-col items-center justify-center gap-3 border-b border-border bg-muted/30 py-6" data-v-a5da7e6e>`);
951
+ _push(`<div class="diff-container" data-v-9eb8ced7><div class="flex flex-col items-center justify-center gap-3 border-b border-border bg-muted/30 py-6" data-v-9eb8ced7>`);
906
952
  _push(ssrRenderComponent(unref(AlertTriangle), { class: "size-8 text-yellow-500" }, null, _parent));
907
- _push(`<div class="text-center" data-v-a5da7e6e><p class="font-medium" data-v-a5da7e6e>Large file</p><p class="text-sm text-muted-foreground" data-v-a5da7e6e> This file has ${ssrInterpolate(unref(totalLines).toLocaleString())} lines (threshold: ${ssrInterpolate(LINE_LIMIT.toLocaleString())}) </p></div>`);
953
+ _push(`<div class="text-center" data-v-9eb8ced7><p class="font-medium" data-v-9eb8ced7>Large file</p><p class="text-sm text-muted-foreground" data-v-9eb8ced7> This file has ${ssrInterpolate(unref(totalLines).toLocaleString())} lines (threshold: ${ssrInterpolate(LINE_LIMIT.toLocaleString())}) </p></div>`);
908
954
  _push(ssrRenderComponent(unref(Button), {
909
955
  variant: "outline",
910
956
  size: "sm",
@@ -925,15 +971,15 @@ const _sfc_main$j = /* @__PURE__ */ defineComponent({
925
971
  }, _parent));
926
972
  _push(`</div></div>`);
927
973
  } else if (__props.showFullFile && __props.fileContent) {
928
- _push(`<div class="diff-container" data-v-a5da7e6e><div class="full-file-view" data-v-a5da7e6e><!--[-->`);
974
+ _push(`<div class="diff-container" data-v-9eb8ced7><div class="full-file-view" data-v-9eb8ced7><!--[-->`);
929
975
  ssrRenderList(unref(fullFileLines), (line, index) => {
930
976
  _push(`<div class="${ssrRenderClass([{
931
977
  "diff-add": getFullFileLineType(index + 1) === "add"
932
- }, "full-file-line"])}" data-v-a5da7e6e><div class="diff-gutter" data-v-a5da7e6e><span class="line-number" data-v-a5da7e6e>${ssrInterpolate(index + 1)}</span></div><div class="diff-content" data-v-a5da7e6e><span class="diff-code" data-v-a5da7e6e>${(unref(highlightedFullFile)[index] || escapeHtml(line)) ?? ""}</span></div></div>`);
978
+ }, "full-file-line"])}" data-v-9eb8ced7><div class="diff-gutter" data-v-9eb8ced7><span class="line-number" data-v-9eb8ced7>${ssrInterpolate(index + 1)}</span></div><div class="diff-content" data-v-9eb8ced7><span class="diff-code" data-v-9eb8ced7>${(unref(highlightedFullFile)[index] || escapeHtml(line)) ?? ""}</span></div></div>`);
933
979
  });
934
980
  _push(`<!--]--></div></div>`);
935
981
  } else {
936
- _push(`<div class="diff-container" data-v-a5da7e6e><div class="diff-toolbar" data-v-a5da7e6e>`);
982
+ _push(`<div class="diff-container" data-v-9eb8ced7><div class="diff-toolbar" data-v-9eb8ced7>`);
937
983
  _push(ssrRenderComponent(unref(Button), {
938
984
  variant: "ghost",
939
985
  size: "sm",
@@ -953,25 +999,25 @@ const _sfc_main$j = /* @__PURE__ */ defineComponent({
953
999
  }),
954
1000
  _: 1
955
1001
  }, _parent));
956
- _push(`</div><div class="diff-split" data-v-a5da7e6e><div class="diff-column diff-column-left" data-v-a5da7e6e><div class="diff-column-content" data-v-a5da7e6e><!--[-->`);
1002
+ _push(`</div><div class="diff-split" data-v-9eb8ced7><div class="diff-column diff-column-left" data-v-9eb8ced7><div class="diff-column-content" data-v-9eb8ced7><!--[-->`);
957
1003
  ssrRenderList(unref(displayItems), (item) => {
958
1004
  _push(`<!--[-->`);
959
1005
  if (item.type === "separator") {
960
- _push(`<div class="diff-separator-half" data-v-a5da7e6e><div class="separator-line" data-v-a5da7e6e></div><span class="separator-text" data-v-a5da7e6e>···</span></div>`);
1006
+ _push(`<div class="diff-separator-half" data-v-9eb8ced7><div class="separator-line" data-v-9eb8ced7></div><span class="separator-text" data-v-9eb8ced7>···</span></div>`);
961
1007
  } else if (item.pair) {
962
1008
  _push(`<div class="${ssrRenderClass([{
963
1009
  "diff-remove": item.pair.left.type === "remove",
964
1010
  "diff-empty": item.pair.left.type === "empty",
965
1011
  "diff-context": item.pair.left.type === "context"
966
- }, "diff-line"])}" data-v-a5da7e6e><div class="diff-gutter" data-v-a5da7e6e>`);
1012
+ }, "diff-line"])}" data-v-9eb8ced7><div class="diff-gutter" data-v-9eb8ced7>`);
967
1013
  if (item.pair.left.lineNum) {
968
- _push(`<span class="line-number" data-v-a5da7e6e>${ssrInterpolate(item.pair.left.lineNum)}</span>`);
1014
+ _push(`<span class="line-number" data-v-9eb8ced7>${ssrInterpolate(item.pair.left.lineNum)}</span>`);
969
1015
  } else {
970
1016
  _push(`<!---->`);
971
1017
  }
972
- _push(`</div><div class="diff-content" data-v-a5da7e6e>`);
1018
+ _push(`</div><div class="diff-content" data-v-9eb8ced7>`);
973
1019
  if (item.pair.left.type !== "empty") {
974
- _push(`<span class="diff-code" data-v-a5da7e6e>${(getHighlightedContent(item.pair.id, "old") || escapeHtml(item.pair.left.content)) ?? ""}</span>`);
1020
+ _push(`<span class="diff-code" data-v-9eb8ced7>${(getHighlightedContent(item.pair.id, "old") || escapeHtml(item.pair.left.content)) ?? ""}</span>`);
975
1021
  } else {
976
1022
  _push(`<!---->`);
977
1023
  }
@@ -981,25 +1027,25 @@ const _sfc_main$j = /* @__PURE__ */ defineComponent({
981
1027
  }
982
1028
  _push(`<!--]-->`);
983
1029
  });
984
- _push(`<!--]--></div></div><div class="diff-column diff-column-right" data-v-a5da7e6e><div class="diff-column-content" data-v-a5da7e6e><!--[-->`);
1030
+ _push(`<!--]--></div></div><div class="diff-column diff-column-right" data-v-9eb8ced7><div class="diff-column-content" data-v-9eb8ced7><!--[-->`);
985
1031
  ssrRenderList(unref(displayItems), (item) => {
986
1032
  _push(`<!--[-->`);
987
1033
  if (item.type === "separator") {
988
- _push(`<div class="diff-separator-half" data-v-a5da7e6e><span class="separator-text" data-v-a5da7e6e>···</span><div class="separator-line" data-v-a5da7e6e></div></div>`);
1034
+ _push(`<div class="diff-separator-half" data-v-9eb8ced7><span class="separator-text" data-v-9eb8ced7>···</span><div class="separator-line" data-v-9eb8ced7></div></div>`);
989
1035
  } else if (item.pair) {
990
1036
  _push(`<div class="${ssrRenderClass([{
991
1037
  "diff-add": item.pair.right.type === "add",
992
1038
  "diff-empty": item.pair.right.type === "empty",
993
1039
  "diff-context": item.pair.right.type === "context"
994
- }, "diff-line"])}" data-v-a5da7e6e><div class="diff-gutter" data-v-a5da7e6e>`);
1040
+ }, "diff-line"])}" data-v-9eb8ced7><div class="diff-gutter" data-v-9eb8ced7>`);
995
1041
  if (item.pair.right.lineNum) {
996
- _push(`<span class="line-number" data-v-a5da7e6e>${ssrInterpolate(item.pair.right.lineNum)}</span>`);
1042
+ _push(`<span class="line-number" data-v-9eb8ced7>${ssrInterpolate(item.pair.right.lineNum)}</span>`);
997
1043
  } else {
998
1044
  _push(`<!---->`);
999
1045
  }
1000
- _push(`</div><div class="diff-content" data-v-a5da7e6e>`);
1046
+ _push(`</div><div class="diff-content" data-v-9eb8ced7>`);
1001
1047
  if (item.pair.right.type !== "empty") {
1002
- _push(`<span class="diff-code" data-v-a5da7e6e>${(getHighlightedContent(item.pair.id, "new") || escapeHtml(item.pair.right.content)) ?? ""}</span>`);
1048
+ _push(`<span class="diff-code" data-v-9eb8ced7>${(getHighlightedContent(item.pair.id, "new") || escapeHtml(item.pair.right.content)) ?? ""}</span>`);
1003
1049
  } else {
1004
1050
  _push(`<!---->`);
1005
1051
  }
@@ -1021,7 +1067,7 @@ _sfc_main$j.setup = (props, ctx) => {
1021
1067
  (ssrContext.modules || (ssrContext.modules = /* @__PURE__ */ new Set())).add("components/git/DiffViewer.vue");
1022
1068
  return _sfc_setup$j ? _sfc_setup$j(props, ctx) : void 0;
1023
1069
  };
1024
- const __nuxt_component_1$2 = /* @__PURE__ */ Object.assign(_export_sfc(_sfc_main$j, [["__scopeId", "data-v-a5da7e6e"]]), { __name: "GitDiffViewer" });
1070
+ const __nuxt_component_1$2 = /* @__PURE__ */ Object.assign(_export_sfc(_sfc_main$j, [["__scopeId", "data-v-9eb8ced7"]]), { __name: "GitDiffViewer" });
1025
1071
  const _sfc_main$i = /* @__PURE__ */ defineComponent({
1026
1072
  __name: "ScrollBar",
1027
1073
  __ssrInlineRender: true,
@@ -1322,6 +1368,45 @@ _sfc_main$d.setup = (props, ctx) => {
1322
1368
  return _sfc_setup$d ? _sfc_setup$d(props, ctx) : void 0;
1323
1369
  };
1324
1370
  const TooltipTrigger = Object.assign(_sfc_main$d, { __name: "UiTooltipTrigger" });
1371
+ function createLatestRequestManager() {
1372
+ let activeTicket = null;
1373
+ function begin() {
1374
+ activeTicket?.controller.abort();
1375
+ const controller = new AbortController();
1376
+ const ticket = {
1377
+ controller,
1378
+ signal: controller.signal,
1379
+ isCurrent: () => activeTicket === ticket && !controller.signal.aborted
1380
+ };
1381
+ activeTicket = ticket;
1382
+ return ticket;
1383
+ }
1384
+ function clear(ticket) {
1385
+ if (activeTicket === ticket) {
1386
+ activeTicket = null;
1387
+ }
1388
+ }
1389
+ function cancel() {
1390
+ activeTicket?.controller.abort();
1391
+ activeTicket = null;
1392
+ }
1393
+ return {
1394
+ begin,
1395
+ clear,
1396
+ cancel
1397
+ };
1398
+ }
1399
+ function isAbortError(error) {
1400
+ if (!error || typeof error !== "object") {
1401
+ return false;
1402
+ }
1403
+ const abortLike = error;
1404
+ if (abortLike.name === "AbortError" || abortLike.cause?.name === "AbortError") {
1405
+ return true;
1406
+ }
1407
+ const message = abortLike.message || abortLike.cause?.message;
1408
+ return typeof message === "string" && message.toLowerCase().includes("aborted");
1409
+ }
1325
1410
  function useGit() {
1326
1411
  const { showError } = useToast();
1327
1412
  function getErrorMessage(error) {
@@ -1331,23 +1416,36 @@ function useGit() {
1331
1416
  }
1332
1417
  return "Unknown error";
1333
1418
  }
1334
- const isLoadingCommits = ref(false);
1335
- const isLoadingDiff = ref(false);
1336
- const isLoadingFileDiff = ref(false);
1337
- const isLoadingFileContent = ref(false);
1338
- async function fetchCommits(repoId, shas, repoPath) {
1419
+ const loadingCommitsCount = ref(0);
1420
+ const loadingDiffCount = ref(0);
1421
+ const loadingFileDiffCount = ref(0);
1422
+ const loadingFileContentCount = ref(0);
1423
+ const isLoadingCommits = computed(() => loadingCommitsCount.value > 0);
1424
+ const isLoadingDiff = computed(() => loadingDiffCount.value > 0);
1425
+ const isLoadingFileDiff = computed(() => loadingFileDiffCount.value > 0);
1426
+ const isLoadingFileContent = computed(() => loadingFileContentCount.value > 0);
1427
+ function startLoading(counter) {
1428
+ counter.value += 1;
1429
+ }
1430
+ function stopLoading(counter) {
1431
+ counter.value = Math.max(0, counter.value - 1);
1432
+ }
1433
+ async function fetchCommits(repoId, shas, options) {
1339
1434
  if (!repoId || shas.length === 0) {
1340
1435
  return { commits: [], failedShas: [] };
1341
1436
  }
1342
- isLoadingCommits.value = true;
1437
+ startLoading(loadingCommitsCount);
1343
1438
  try {
1344
1439
  const query = { shas: shas.join(",") };
1345
- if (repoPath) {
1346
- query.repo = repoPath;
1440
+ if (options?.repoPath) {
1441
+ query.repo = options.repoPath;
1347
1442
  }
1348
1443
  const commits = await $fetch(
1349
1444
  `/api/repos/${repoId}/git/commits`,
1350
- { query }
1445
+ {
1446
+ query,
1447
+ signal: options?.signal
1448
+ }
1351
1449
  );
1352
1450
  const returnedShortShas = commits.map((c) => c.shortSha);
1353
1451
  const failedShas = shas.filter((sha) => {
@@ -1355,76 +1453,96 @@ function useGit() {
1355
1453
  });
1356
1454
  return { commits, failedShas };
1357
1455
  } catch (error) {
1358
- showError("Failed to fetch commits", getErrorMessage(error));
1456
+ if (isAbortError(error)) {
1457
+ return { commits: [], failedShas: [] };
1458
+ }
1459
+ if (!options?.suppressError) {
1460
+ showError("Failed to fetch commits", getErrorMessage(error));
1461
+ }
1359
1462
  return { commits: [], failedShas: shas };
1360
1463
  } finally {
1361
- isLoadingCommits.value = false;
1464
+ stopLoading(loadingCommitsCount);
1362
1465
  }
1363
1466
  }
1364
- async function fetchDiff(repoId, commitSha, repoPath) {
1467
+ async function fetchDiff(repoId, commitSha, options) {
1365
1468
  if (!repoId || !commitSha) {
1366
1469
  return [];
1367
1470
  }
1368
- isLoadingDiff.value = true;
1471
+ startLoading(loadingDiffCount);
1369
1472
  try {
1370
1473
  const query = { commit: commitSha };
1371
- if (repoPath) {
1372
- query.repo = repoPath;
1474
+ if (options?.repoPath) {
1475
+ query.repo = options.repoPath;
1373
1476
  }
1374
1477
  const files = await $fetch(
1375
1478
  `/api/repos/${repoId}/git/diff`,
1376
- { query }
1479
+ {
1480
+ query,
1481
+ signal: options?.signal
1482
+ }
1377
1483
  );
1378
1484
  return files;
1379
1485
  } catch (error) {
1380
- showError("Failed to fetch diff", getErrorMessage(error));
1486
+ if (!isAbortError(error) && !options?.suppressError) {
1487
+ showError("Failed to fetch diff", getErrorMessage(error));
1488
+ }
1381
1489
  throw error;
1382
1490
  } finally {
1383
- isLoadingDiff.value = false;
1491
+ stopLoading(loadingDiffCount);
1384
1492
  }
1385
1493
  }
1386
- async function fetchFileDiff(repoId, commitSha, filePath, repoPath) {
1494
+ async function fetchFileDiff(repoId, commitSha, filePath, options) {
1387
1495
  if (!repoId || !commitSha || !filePath) {
1388
1496
  return [];
1389
1497
  }
1390
- isLoadingFileDiff.value = true;
1498
+ startLoading(loadingFileDiffCount);
1391
1499
  try {
1392
1500
  const query = { commit: commitSha, file: filePath };
1393
- if (repoPath) {
1394
- query.repo = repoPath;
1501
+ if (options?.repoPath) {
1502
+ query.repo = options.repoPath;
1395
1503
  }
1396
1504
  const hunks = await $fetch(
1397
1505
  `/api/repos/${repoId}/git/file-diff`,
1398
- { query }
1506
+ {
1507
+ query,
1508
+ signal: options?.signal
1509
+ }
1399
1510
  );
1400
1511
  return hunks;
1401
1512
  } catch (error) {
1402
- showError("Failed to fetch file diff", getErrorMessage(error));
1513
+ if (!isAbortError(error) && !options?.suppressError) {
1514
+ showError("Failed to fetch file diff", getErrorMessage(error));
1515
+ }
1403
1516
  throw error;
1404
1517
  } finally {
1405
- isLoadingFileDiff.value = false;
1518
+ stopLoading(loadingFileDiffCount);
1406
1519
  }
1407
1520
  }
1408
- async function fetchFileContent(repoId, commitSha, filePath, repoPath) {
1521
+ async function fetchFileContent(repoId, commitSha, filePath, options) {
1409
1522
  if (!repoId || !commitSha || !filePath) {
1410
1523
  return null;
1411
1524
  }
1412
- isLoadingFileContent.value = true;
1525
+ startLoading(loadingFileContentCount);
1413
1526
  try {
1414
1527
  const query = { commit: commitSha, file: filePath };
1415
- if (repoPath) {
1416
- query.repo = repoPath;
1528
+ if (options?.repoPath) {
1529
+ query.repo = options.repoPath;
1417
1530
  }
1418
1531
  const result = await $fetch(
1419
1532
  `/api/repos/${repoId}/git/file-content`,
1420
- { query }
1533
+ {
1534
+ query,
1535
+ signal: options?.signal
1536
+ }
1421
1537
  );
1422
1538
  return result.content;
1423
1539
  } catch (error) {
1424
- showError("Failed to fetch file content", getErrorMessage(error));
1540
+ if (!isAbortError(error) && !options?.suppressError) {
1541
+ showError("Failed to fetch file content", getErrorMessage(error));
1542
+ }
1425
1543
  throw error;
1426
1544
  } finally {
1427
- isLoadingFileContent.value = false;
1545
+ stopLoading(loadingFileContentCount);
1428
1546
  }
1429
1547
  }
1430
1548
  return {
@@ -1434,10 +1552,10 @@ function useGit() {
1434
1552
  fetchFileDiff,
1435
1553
  fetchFileContent,
1436
1554
  // Loading states
1437
- isLoadingCommits: readonly(isLoadingCommits),
1438
- isLoadingDiff: readonly(isLoadingDiff),
1439
- isLoadingFileDiff: readonly(isLoadingFileDiff),
1440
- isLoadingFileContent: readonly(isLoadingFileContent)
1555
+ isLoadingCommits,
1556
+ isLoadingDiff,
1557
+ isLoadingFileDiff,
1558
+ isLoadingFileContent
1441
1559
  };
1442
1560
  }
1443
1561
  const _sfc_main$c = /* @__PURE__ */ defineComponent({
@@ -1459,6 +1577,8 @@ const _sfc_main$c = /* @__PURE__ */ defineComponent({
1459
1577
  const error = ref(null);
1460
1578
  const fileDiffError = ref(null);
1461
1579
  const viewMode = ref("changes");
1580
+ const diffRequestManager = createLatestRequestManager();
1581
+ const fileRequestManager = createLatestRequestManager();
1462
1582
  function getErrorMessage(error2, fallback) {
1463
1583
  if (error2 && typeof error2 === "object") {
1464
1584
  const fetchError = error2;
@@ -1467,72 +1587,124 @@ const _sfc_main$c = /* @__PURE__ */ defineComponent({
1467
1587
  return fallback;
1468
1588
  }
1469
1589
  const selectedFileDiff = computed(() => files.value.find((f) => f.path === selectedFile.value));
1470
- async function loadDiff() {
1590
+ const diffViewerKey = computed(() => `${props.repoPath || ""}:${props.commitSha}:${selectedFile.value || ""}`);
1591
+ function resetDiffState() {
1471
1592
  error.value = null;
1472
1593
  files.value = [];
1473
1594
  selectedFile.value = void 0;
1474
1595
  hunks.value = [];
1475
1596
  fileContent.value = null;
1597
+ fileDiffError.value = null;
1598
+ }
1599
+ async function loadDiff() {
1600
+ const requestRepoId = props.repoId;
1601
+ const requestCommitSha = props.commitSha;
1602
+ const requestRepoPath = props.repoPath;
1603
+ const ticket = diffRequestManager.begin();
1604
+ fileRequestManager.cancel();
1605
+ resetDiffState();
1476
1606
  try {
1477
- const result = await fetchDiff(props.repoId, props.commitSha, props.repoPath);
1607
+ const result = await fetchDiff(requestRepoId, requestCommitSha, {
1608
+ repoPath: requestRepoPath,
1609
+ signal: ticket.signal,
1610
+ suppressError: true
1611
+ });
1612
+ const isCurrentRequest = ticket.isCurrent() && props.repoId === requestRepoId && props.commitSha === requestCommitSha && props.repoPath === requestRepoPath;
1613
+ if (!isCurrentRequest) {
1614
+ return;
1615
+ }
1478
1616
  files.value = result;
1479
1617
  if (result.length > 0) {
1480
1618
  selectedFile.value = result[0].path;
1481
1619
  }
1482
1620
  } catch (loadError) {
1621
+ if (isAbortError(loadError) || !ticket.isCurrent()) {
1622
+ return;
1623
+ }
1483
1624
  error.value = getErrorMessage(loadError, "Could not load commit diff.");
1625
+ } finally {
1626
+ diffRequestManager.clear(ticket);
1484
1627
  }
1485
1628
  }
1486
1629
  async function loadFileDiff() {
1487
- if (!selectedFile.value) {
1630
+ const selectedPath = selectedFile.value;
1631
+ if (!selectedPath) {
1632
+ fileDiffError.value = null;
1488
1633
  hunks.value = [];
1489
1634
  fileContent.value = null;
1490
1635
  return;
1491
1636
  }
1637
+ const requestRepoId = props.repoId;
1638
+ const requestCommitSha = props.commitSha;
1639
+ const requestRepoPath = props.repoPath;
1640
+ const requestMode = viewMode.value;
1641
+ const requestPath = selectedPath;
1642
+ const ticket = fileRequestManager.begin();
1492
1643
  fileDiffError.value = null;
1644
+ hunks.value = [];
1645
+ fileContent.value = null;
1646
+ const isCurrentRequest = () => {
1647
+ return ticket.isCurrent() && props.repoId === requestRepoId && props.commitSha === requestCommitSha && props.repoPath === requestRepoPath && viewMode.value === requestMode && selectedFile.value === requestPath;
1648
+ };
1493
1649
  try {
1494
- const result = await fetchFileDiff(props.repoId, props.commitSha, selectedFile.value, props.repoPath);
1495
- hunks.value = result;
1496
- if (viewMode.value === "full") {
1497
- const content = await fetchFileContent(props.repoId, props.commitSha, selectedFile.value, props.repoPath);
1650
+ const diffPromise = fetchFileDiff(requestRepoId, requestCommitSha, requestPath, {
1651
+ repoPath: requestRepoPath,
1652
+ signal: ticket.signal,
1653
+ suppressError: true
1654
+ });
1655
+ if (requestMode === "full") {
1656
+ const [result, content] = await Promise.all([
1657
+ diffPromise,
1658
+ fetchFileContent(requestRepoId, requestCommitSha, requestPath, {
1659
+ repoPath: requestRepoPath,
1660
+ signal: ticket.signal,
1661
+ suppressError: true
1662
+ })
1663
+ ]);
1664
+ if (!isCurrentRequest()) {
1665
+ return;
1666
+ }
1667
+ hunks.value = result;
1498
1668
  fileContent.value = content;
1499
1669
  } else {
1670
+ const result = await diffPromise;
1671
+ if (!isCurrentRequest()) {
1672
+ return;
1673
+ }
1674
+ hunks.value = result;
1500
1675
  fileContent.value = null;
1501
1676
  }
1502
1677
  } catch (loadError) {
1678
+ if (!isCurrentRequest() || isAbortError(loadError)) {
1679
+ return;
1680
+ }
1503
1681
  fileDiffError.value = getErrorMessage(loadError, "Could not load file diff.");
1682
+ } finally {
1683
+ fileRequestManager.clear(ticket);
1504
1684
  }
1505
1685
  }
1506
1686
  function toggleViewMode() {
1507
1687
  viewMode.value = viewMode.value === "changes" ? "full" : "changes";
1508
1688
  }
1509
- watch(viewMode, async (mode) => {
1510
- if (mode === "full" && selectedFile.value && !fileContent.value) {
1511
- try {
1512
- const content = await fetchFileContent(props.repoId, props.commitSha, selectedFile.value, props.repoPath);
1513
- fileContent.value = content;
1514
- fileDiffError.value = null;
1515
- } catch (loadError) {
1516
- fileDiffError.value = getErrorMessage(loadError, "Could not load file content.");
1517
- }
1518
- }
1519
- });
1520
1689
  function handleFileSelect(path) {
1521
1690
  selectedFile.value = path;
1522
1691
  }
1523
1692
  function retry() {
1524
- loadDiff();
1693
+ void loadDiff();
1525
1694
  }
1526
1695
  function retryFileDiff() {
1527
- loadFileDiff();
1696
+ void loadFileDiff();
1528
1697
  }
1529
- watch(selectedFile, () => {
1530
- loadFileDiff();
1531
- });
1698
+ watch(
1699
+ () => [selectedFile.value, viewMode.value],
1700
+ () => {
1701
+ void loadFileDiff();
1702
+ }
1703
+ );
1532
1704
  watch(
1533
1705
  () => [props.repoId, props.commitSha, props.repoPath],
1534
1706
  () => {
1535
- loadDiff();
1707
+ void loadDiff();
1536
1708
  },
1537
1709
  { immediate: true }
1538
1710
  );
@@ -1894,6 +2066,7 @@ const _sfc_main$c = /* @__PURE__ */ defineComponent({
1894
2066
  if (_push2) {
1895
2067
  _push2(`<div${_scopeId}>`);
1896
2068
  _push2(ssrRenderComponent(_component_GitDiffViewer, {
2069
+ key: unref(diffViewerKey),
1897
2070
  hunks: unref(hunks),
1898
2071
  "file-path": unref(selectedFile),
1899
2072
  binary: unref(selectedFileDiff)?.binary,
@@ -1909,7 +2082,8 @@ const _sfc_main$c = /* @__PURE__ */ defineComponent({
1909
2082
  ref_key: "diffViewerRef",
1910
2083
  ref: diffViewerRef
1911
2084
  }, [
1912
- createVNode(_component_GitDiffViewer, {
2085
+ (openBlock(), createBlock(_component_GitDiffViewer, {
2086
+ key: unref(diffViewerKey),
1913
2087
  hunks: unref(hunks),
1914
2088
  "file-path": unref(selectedFile),
1915
2089
  binary: unref(selectedFileDiff)?.binary,
@@ -1917,7 +2091,7 @@ const _sfc_main$c = /* @__PURE__ */ defineComponent({
1917
2091
  "file-content": unref(fileContent),
1918
2092
  "show-full-file": unref(viewMode) === "full",
1919
2093
  "is-loading-content": unref(isLoadingFileContent)
1920
- }, null, 8, ["hunks", "file-path", "binary", "old-path", "file-content", "show-full-file", "is-loading-content"])
2094
+ }, null, 8, ["hunks", "file-path", "binary", "old-path", "file-content", "show-full-file", "is-loading-content"]))
1921
2095
  ], 512)
1922
2096
  ];
1923
2097
  }
@@ -1972,9 +2146,14 @@ const _sfc_main$b = /* @__PURE__ */ defineComponent({
1972
2146
  const repos = new Set(props.commits.map((c) => c.repo).filter(Boolean));
1973
2147
  return repos.size > 1;
1974
2148
  });
2149
+ const commitsRequestManager = createLatestRequestManager();
1975
2150
  watch(
1976
2151
  () => ({ commits: props.commits, repoId: props.repoId }),
1977
- async ({ commits, repoId }) => {
2152
+ async ({ commits, repoId }, _, onCleanup) => {
2153
+ const ticket = commitsRequestManager.begin();
2154
+ onCleanup(() => {
2155
+ commitsRequestManager.clear(ticket);
2156
+ });
1978
2157
  if (commits.length === 0 || !repoId) {
1979
2158
  commitDetails.value = /* @__PURE__ */ new Map();
1980
2159
  failedCommits.value = /* @__PURE__ */ new Set();
@@ -1990,7 +2169,10 @@ const _sfc_main$b = /* @__PURE__ */ defineComponent({
1990
2169
  }
1991
2170
  const results = await Promise.all(
1992
2171
  Array.from(commitsByRepo.entries()).map(async ([repoPath, shas]) => {
1993
- const result = await fetchCommits(repoId, shas, repoPath || void 0);
2172
+ const result = await fetchCommits(repoId, shas, {
2173
+ repoPath: repoPath || void 0,
2174
+ signal: ticket.signal
2175
+ });
1994
2176
  return {
1995
2177
  repoPath,
1996
2178
  requestedShas: [...shas],
@@ -2022,6 +2204,9 @@ const _sfc_main$b = /* @__PURE__ */ defineComponent({
2022
2204
  failed.add(createCommitKey(sha, repoPath));
2023
2205
  }
2024
2206
  }
2207
+ if (!ticket.isCurrent()) {
2208
+ return;
2209
+ }
2025
2210
  commitDetails.value = detailsMap;
2026
2211
  failedCommits.value = failed;
2027
2212
  },
@@ -3540,4 +3725,4 @@ _sfc_main.setup = (props, ctx) => {
3540
3725
  const __nuxt_component_1 = Object.assign(_sfc_main, { __name: "TasksDetail" });
3541
3726
 
3542
3727
  export { Badge as B, __nuxt_component_0$2 as _, __nuxt_component_1 as a };
3543
- //# sourceMappingURL=Detail-BcQGdJY5.mjs.map
3728
+ //# sourceMappingURL=Detail-B7yBNjgp.mjs.map