jj-plus 0.10.10

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 (404) hide show
  1. package/CHANGELOG.md +30 -0
  2. package/README.md +102 -0
  3. package/assets/jj-plus-icon.png +0 -0
  4. package/dist/_virtual/_rolldown/runtime.cjs +23 -0
  5. package/dist/bin.cjs +112 -0
  6. package/dist/bin.cjs.map +1 -0
  7. package/dist/cli/options.cjs +376 -0
  8. package/dist/cli/options.cjs.map +1 -0
  9. package/dist/cli/timeline-json.cjs +29 -0
  10. package/dist/cli/timeline-json.cjs.map +1 -0
  11. package/dist/extension/blame-codelens.cjs +228 -0
  12. package/dist/extension/blame-codelens.cjs.map +1 -0
  13. package/dist/extension/command-runner.cjs +99 -0
  14. package/dist/extension/command-runner.cjs.map +1 -0
  15. package/dist/extension/constants.cjs +56 -0
  16. package/dist/extension/constants.cjs.map +1 -0
  17. package/dist/extension/editor-extra-features.cjs +464 -0
  18. package/dist/extension/editor-extra-features.cjs.map +1 -0
  19. package/dist/extension/history-adapters.cjs +702 -0
  20. package/dist/extension/history-adapters.cjs.map +1 -0
  21. package/dist/extension/index.cjs +657 -0
  22. package/dist/extension/index.cjs.map +1 -0
  23. package/dist/extension/repo-timeline-panel.cjs +402 -0
  24. package/dist/extension/repo-timeline-panel.cjs.map +1 -0
  25. package/dist/extension/resolve-file-path.cjs +16 -0
  26. package/dist/extension/resolve-file-path.cjs.map +1 -0
  27. package/dist/extension/revision-diff-nav.cjs +169 -0
  28. package/dist/extension/revision-diff-nav.cjs.map +1 -0
  29. package/dist/extension/settings.cjs +41 -0
  30. package/dist/extension/settings.cjs.map +1 -0
  31. package/dist/extension/timeline-at-line.cjs +72 -0
  32. package/dist/extension/timeline-at-line.cjs.map +1 -0
  33. package/dist/extension/timeline-panel.cjs +1113 -0
  34. package/dist/extension/timeline-panel.cjs.map +1 -0
  35. package/dist/extension/timeline-service.cjs +1154 -0
  36. package/dist/extension/timeline-service.cjs.map +1 -0
  37. package/dist/extension/uri-utils.cjs +75 -0
  38. package/dist/extension/uri-utils.cjs.map +1 -0
  39. package/dist/package.cjs +11 -0
  40. package/dist/package.cjs.map +1 -0
  41. package/dist/shared/blame.cjs +211 -0
  42. package/dist/shared/blame.cjs.map +1 -0
  43. package/dist/shared/diff-content-search.cjs +23 -0
  44. package/dist/shared/diff-content-search.cjs.map +1 -0
  45. package/dist/shared/diff-helpers.cjs +12 -0
  46. package/dist/shared/diff-helpers.cjs.map +1 -0
  47. package/dist/shared/diff-stats.cjs +129 -0
  48. package/dist/shared/diff-stats.cjs.map +1 -0
  49. package/dist/shared/file-oplog.cjs +82 -0
  50. package/dist/shared/file-oplog.cjs.map +1 -0
  51. package/dist/shared/history-helpers.cjs +257 -0
  52. package/dist/shared/history-helpers.cjs.map +1 -0
  53. package/dist/shared/history-search.cjs +85 -0
  54. package/dist/shared/history-search.cjs.map +1 -0
  55. package/dist/shared/jj-revset-suggestions.cjs +41 -0
  56. package/dist/shared/jj-revset-suggestions.cjs.map +1 -0
  57. package/dist/shared/line-history.cjs +181 -0
  58. package/dist/shared/line-history.cjs.map +1 -0
  59. package/dist/shared/list-file-revisions.cjs +36 -0
  60. package/dist/shared/list-file-revisions.cjs.map +1 -0
  61. package/dist/shared/non-textual-details.cjs +43 -0
  62. package/dist/shared/non-textual-details.cjs.map +1 -0
  63. package/dist/shared/resolve-file-path.cjs +14 -0
  64. package/dist/shared/resolve-file-path.cjs.map +1 -0
  65. package/dist/shared/revision-diff-availability.cjs +18 -0
  66. package/dist/shared/revision-diff-availability.cjs.map +1 -0
  67. package/dist/shared/revision-diff-pair.cjs +42 -0
  68. package/dist/shared/revision-diff-pair.cjs.map +1 -0
  69. package/dist/shared/revset.cjs +16 -0
  70. package/dist/shared/revset.cjs.map +1 -0
  71. package/dist/shared/timeline-model.cjs +29 -0
  72. package/dist/shared/timeline-model.cjs.map +1 -0
  73. package/dist/standalone/server.cjs +1733 -0
  74. package/dist/standalone/server.cjs.map +1 -0
  75. package/dist/webview/timeline-template.cjs +214 -0
  76. package/dist/webview/timeline-template.cjs.map +1 -0
  77. package/package.json +320 -0
  78. package/webview-dist/assets/worker-DuV13XDT.js +161 -0
  79. package/webview-dist/chunks/abap-CLvhMVsD.js +1 -0
  80. package/webview-dist/chunks/actionscript-3-Cs6JJXT5.js +1 -0
  81. package/webview-dist/chunks/ada-C5qYipkI.js +1 -0
  82. package/webview-dist/chunks/ahk-CA9gdOdF.js +1 -0
  83. package/webview-dist/chunks/ahk2-_6rzW9BS.js +1 -0
  84. package/webview-dist/chunks/andromeeda-vGVdxbeo.js +1 -0
  85. package/webview-dist/chunks/angular-html-DTpR04n4.js +1 -0
  86. package/webview-dist/chunks/angular-ts-BCtbMvbl.js +1 -0
  87. package/webview-dist/chunks/apache-U0d_L8uA.js +1 -0
  88. package/webview-dist/chunks/apex-KFGFyKwG.js +1 -0
  89. package/webview-dist/chunks/apl-BMZuN1Ql.js +1 -0
  90. package/webview-dist/chunks/applescript-CCn79oCD.js +1 -0
  91. package/webview-dist/chunks/ara-4CJ0cIlV.js +1 -0
  92. package/webview-dist/chunks/asciidoc-SCjQUq34.js +1 -0
  93. package/webview-dist/chunks/asm-Cmm7eHzH.js +1 -0
  94. package/webview-dist/chunks/astro-DrbV4Z7r.js +1 -0
  95. package/webview-dist/chunks/aurora-x-CDeNXAV0.js +1 -0
  96. package/webview-dist/chunks/awk-BWXHIvNe.js +1 -0
  97. package/webview-dist/chunks/ayu-dark-DluEY0Gj.js +1 -0
  98. package/webview-dist/chunks/ayu-light-C3h-C4tm.js +1 -0
  99. package/webview-dist/chunks/ayu-mirage-Bqwy1Gya.js +1 -0
  100. package/webview-dist/chunks/ballerina-B7ZEbQpA.js +1 -0
  101. package/webview-dist/chunks/bat-qdxAdBWQ.js +1 -0
  102. package/webview-dist/chunks/beancount-D-usSTwE.js +1 -0
  103. package/webview-dist/chunks/berry-DKpUyyne.js +1 -0
  104. package/webview-dist/chunks/bibtex-Ci_nEsc7.js +1 -0
  105. package/webview-dist/chunks/bicep-CUHmPFLl.js +1 -0
  106. package/webview-dist/chunks/bird2-CYIUgYqB.js +1 -0
  107. package/webview-dist/chunks/blade-oPV8S6rR.js +1 -0
  108. package/webview-dist/chunks/bsl-_VjlB9mv.js +1 -0
  109. package/webview-dist/chunks/c-DYf-3tob.js +1 -0
  110. package/webview-dist/chunks/c3-D0apG41V.js +1 -0
  111. package/webview-dist/chunks/cadence-CQ2zXKGN.js +1 -0
  112. package/webview-dist/chunks/cairo-DLTphjLi.js +1 -0
  113. package/webview-dist/chunks/catppuccin-frappe-C9Q5zVZY.js +1 -0
  114. package/webview-dist/chunks/catppuccin-latte-CtsyrtPq.js +1 -0
  115. package/webview-dist/chunks/catppuccin-macchiato-R8nAf1vR.js +1 -0
  116. package/webview-dist/chunks/catppuccin-mocha-DjuaAJKi.js +1 -0
  117. package/webview-dist/chunks/chapel-DY-WYB1D.js +1 -0
  118. package/webview-dist/chunks/clarity-CtfBBspg.js +1 -0
  119. package/webview-dist/chunks/clojure-DqKBuwfJ.js +1 -0
  120. package/webview-dist/chunks/cmake-Bj61d0ZC.js +1 -0
  121. package/webview-dist/chunks/cobol-DvdX_6CO.js +1 -0
  122. package/webview-dist/chunks/codeowners-C8r90Shi.js +1 -0
  123. package/webview-dist/chunks/codeql-oeQT6MSM.js +1 -0
  124. package/webview-dist/chunks/coffee-C1kO7jr_.js +1 -0
  125. package/webview-dist/chunks/common-lisp-Cv5bFMCO.js +1 -0
  126. package/webview-dist/chunks/coq-DuBRPxYg.js +1 -0
  127. package/webview-dist/chunks/cpp-CoSarUrI.js +1 -0
  128. package/webview-dist/chunks/crystal-SLJeZ5EP.js +1 -0
  129. package/webview-dist/chunks/csharp-oqKa8noW.js +1 -0
  130. package/webview-dist/chunks/css-cfScyrSP.js +1 -0
  131. package/webview-dist/chunks/csv-Dx-8-gkx.js +1 -0
  132. package/webview-dist/chunks/cue-CE9AQfxI.js +1 -0
  133. package/webview-dist/chunks/cypher-ClKdZ_lG.js +1 -0
  134. package/webview-dist/chunks/d-qD-0Kul2.js +1 -0
  135. package/webview-dist/chunks/dark-plus-Cs2F2srj.js +1 -0
  136. package/webview-dist/chunks/dart-CnvKMtbv.js +1 -0
  137. package/webview-dist/chunks/dax-BkyTk9wS.js +1 -0
  138. package/webview-dist/chunks/desktop-Dlh5hvp9.js +1 -0
  139. package/webview-dist/chunks/diff-woXpYk--.js +1 -0
  140. package/webview-dist/chunks/docker-IyjqRm3v.js +1 -0
  141. package/webview-dist/chunks/dotenv-_5a1GRtc.js +1 -0
  142. package/webview-dist/chunks/dracula-BHWKrbxM.js +1 -0
  143. package/webview-dist/chunks/dracula-soft-5eyTD99u.js +1 -0
  144. package/webview-dist/chunks/dream-maker-DW3nJb8Q.js +1 -0
  145. package/webview-dist/chunks/edge-lvBr3t3s.js +1 -0
  146. package/webview-dist/chunks/elixir-BLoPe0KG.js +1 -0
  147. package/webview-dist/chunks/elm-BveBINBn.js +1 -0
  148. package/webview-dist/chunks/emacs-lisp-c_oH4hRZ.js +1 -0
  149. package/webview-dist/chunks/erb-Bmf8z4ph.js +1 -0
  150. package/webview-dist/chunks/erlang-Cphh6RMH.js +1 -0
  151. package/webview-dist/chunks/everforest-dark-sB-x3p7T.js +1 -0
  152. package/webview-dist/chunks/everforest-light-Df2xbC6M.js +1 -0
  153. package/webview-dist/chunks/fennel-DQxkIbk2.js +1 -0
  154. package/webview-dist/chunks/fish-BJitypiv.js +1 -0
  155. package/webview-dist/chunks/fluent-C03EYrpw.js +1 -0
  156. package/webview-dist/chunks/fortran-fixed-form-DEKoE2YW.js +1 -0
  157. package/webview-dist/chunks/fortran-free-form-CYNrtFtB.js +1 -0
  158. package/webview-dist/chunks/fsharp-D13ZGOAj.js +1 -0
  159. package/webview-dist/chunks/gdresource-xMC7jr7x.js +1 -0
  160. package/webview-dist/chunks/gdscript-DYvRD3hg.js +1 -0
  161. package/webview-dist/chunks/gdshader-CBce3t8t.js +1 -0
  162. package/webview-dist/chunks/genie-CV2tkWYe.js +1 -0
  163. package/webview-dist/chunks/gherkin-DExj1W_8.js +1 -0
  164. package/webview-dist/chunks/git-commit-BSykSTBG.js +1 -0
  165. package/webview-dist/chunks/git-rebase-BBii7GBM.js +1 -0
  166. package/webview-dist/chunks/github-dark-C-LZuMrd.js +1 -0
  167. package/webview-dist/chunks/github-dark-default-DXG-b-1a.js +1 -0
  168. package/webview-dist/chunks/github-dark-dimmed-Bx1FflLF.js +1 -0
  169. package/webview-dist/chunks/github-dark-high-contrast-B_tTalzw.js +1 -0
  170. package/webview-dist/chunks/github-light-EUqPIrTm.js +1 -0
  171. package/webview-dist/chunks/github-light-default-BXViO-2h.js +1 -0
  172. package/webview-dist/chunks/github-light-high-contrast-B68TUdTA.js +1 -0
  173. package/webview-dist/chunks/gleam-CSRkHgEL.js +1 -0
  174. package/webview-dist/chunks/glimmer-js-CuCPna-X.js +1 -0
  175. package/webview-dist/chunks/glimmer-ts-DNAjZNDK.js +1 -0
  176. package/webview-dist/chunks/glsl-COQvRxdz.js +1 -0
  177. package/webview-dist/chunks/gn-ilITqXS6.js +1 -0
  178. package/webview-dist/chunks/gnuplot-7GGW24-e.js +1 -0
  179. package/webview-dist/chunks/go-rLFTqkRN.js +1 -0
  180. package/webview-dist/chunks/graphql-1cKCVreZ.js +1 -0
  181. package/webview-dist/chunks/groovy-CacY0gHj.js +1 -0
  182. package/webview-dist/chunks/gruvbox-dark-hard-C820rvS2.js +1 -0
  183. package/webview-dist/chunks/gruvbox-dark-medium-BPjhmG05.js +1 -0
  184. package/webview-dist/chunks/gruvbox-dark-soft-MrdJrrXF.js +1 -0
  185. package/webview-dist/chunks/gruvbox-light-hard-BC_s9l72.js +1 -0
  186. package/webview-dist/chunks/gruvbox-light-medium-BAWPOn9u.js +1 -0
  187. package/webview-dist/chunks/gruvbox-light-soft-BSMLrYjP.js +1 -0
  188. package/webview-dist/chunks/hack-7CXYxWGO.js +1 -0
  189. package/webview-dist/chunks/haml-CeE16iG9.js +1 -0
  190. package/webview-dist/chunks/handlebars-CLm7Miue.js +1 -0
  191. package/webview-dist/chunks/haskell-D8IpX4py.js +1 -0
  192. package/webview-dist/chunks/haxe-C8oCnwJJ.js +1 -0
  193. package/webview-dist/chunks/hcl-Dh228itO.js +1 -0
  194. package/webview-dist/chunks/hjson-CxZEssPk.js +1 -0
  195. package/webview-dist/chunks/hlsl-Cvrh5tZx.js +1 -0
  196. package/webview-dist/chunks/horizon-CE9ld1lL.js +1 -0
  197. package/webview-dist/chunks/horizon-bright-DSNQnXHK.js +1 -0
  198. package/webview-dist/chunks/houston-CsvMBhTu.js +1 -0
  199. package/webview-dist/chunks/html-EbCri-_j.js +1 -0
  200. package/webview-dist/chunks/html-derivative-DGcE2kQi.js +1 -0
  201. package/webview-dist/chunks/http-DpnqgCg2.js +1 -0
  202. package/webview-dist/chunks/hurl-B6NGpamo.js +1 -0
  203. package/webview-dist/chunks/hxml-Dcm88srW.js +1 -0
  204. package/webview-dist/chunks/hy-CZbG8q4J.js +1 -0
  205. package/webview-dist/chunks/imba-DsUTQ-LC.js +1 -0
  206. package/webview-dist/chunks/ini-B5eOa1yu.js +1 -0
  207. package/webview-dist/chunks/java-ZkUoUSJy.js +1 -0
  208. package/webview-dist/chunks/javascript-DLd0EIw7.js +1 -0
  209. package/webview-dist/chunks/jinja-WhIqNp3q.js +1 -0
  210. package/webview-dist/chunks/jison-CIn1t7S8.js +1 -0
  211. package/webview-dist/chunks/json-AHG_JuKN.js +1 -0
  212. package/webview-dist/chunks/json5-BR5RXkoi.js +1 -0
  213. package/webview-dist/chunks/jsonc-CYpm1nAK.js +1 -0
  214. package/webview-dist/chunks/jsonl-CmCQp5Yx.js +1 -0
  215. package/webview-dist/chunks/jsonnet-CJTPZ8u_.js +1 -0
  216. package/webview-dist/chunks/jssm-DXw9l8Rf.js +1 -0
  217. package/webview-dist/chunks/jsx-BLy2KGb2.js +1 -0
  218. package/webview-dist/chunks/julia-XrhdGMY0.js +1 -0
  219. package/webview-dist/chunks/just-CiO9rOBq.js +1 -0
  220. package/webview-dist/chunks/kanagawa-dragon-Bozd7klA.js +1 -0
  221. package/webview-dist/chunks/kanagawa-lotus-BmuOG9ZW.js +1 -0
  222. package/webview-dist/chunks/kanagawa-wave-BML5mF2J.js +1 -0
  223. package/webview-dist/chunks/kdl-CsD5j6eV.js +1 -0
  224. package/webview-dist/chunks/kotlin-DhhofPvG.js +1 -0
  225. package/webview-dist/chunks/kusto-C7mF5XQf.js +1 -0
  226. package/webview-dist/chunks/laserwave-C_8bwKvT.js +1 -0
  227. package/webview-dist/chunks/latex-4tqdYtbu.js +1 -0
  228. package/webview-dist/chunks/lean-CewbzKMR.js +1 -0
  229. package/webview-dist/chunks/less-DVTAwKKz.js +1 -0
  230. package/webview-dist/chunks/light-plus-DVQuIRkW.js +1 -0
  231. package/webview-dist/chunks/liquid-BiiWRCLG.js +1 -0
  232. package/webview-dist/chunks/llvm-DqHOMS-s.js +1 -0
  233. package/webview-dist/chunks/log-BNLmms1o.js +1 -0
  234. package/webview-dist/chunks/logo-Cluzi2Zq.js +1 -0
  235. package/webview-dist/chunks/lua-BPFdS2Mc.js +1 -0
  236. package/webview-dist/chunks/luau-C2pBCSgt.js +1 -0
  237. package/webview-dist/chunks/make-Dixweg8N.js +1 -0
  238. package/webview-dist/chunks/markdown-BYOwaDjH.js +1 -0
  239. package/webview-dist/chunks/marko-BLi1Yy1V.js +1 -0
  240. package/webview-dist/chunks/material-theme-Bm3Qr25_.js +1 -0
  241. package/webview-dist/chunks/material-theme-darker-2IIEA8gg.js +1 -0
  242. package/webview-dist/chunks/material-theme-lighter-uhdI0v04.js +1 -0
  243. package/webview-dist/chunks/material-theme-ocean-CHQ94UKr.js +1 -0
  244. package/webview-dist/chunks/material-theme-palenight-B5W6OYN7.js +1 -0
  245. package/webview-dist/chunks/matlab-D7qyCx1q.js +1 -0
  246. package/webview-dist/chunks/mdc-Dx-qyM1x.js +1 -0
  247. package/webview-dist/chunks/mdx-DQZ5AkYe.js +1 -0
  248. package/webview-dist/chunks/mermaid-BxpfTIzt.js +1 -0
  249. package/webview-dist/chunks/min-dark-BSWPekZh.js +1 -0
  250. package/webview-dist/chunks/min-light-DDpmG2fV.js +1 -0
  251. package/webview-dist/chunks/mipsasm-BMqwQI7S.js +1 -0
  252. package/webview-dist/chunks/mojo-fg40_ntQ.js +1 -0
  253. package/webview-dist/chunks/monokai-B_bV9PQ9.js +1 -0
  254. package/webview-dist/chunks/moonbit-DgjMoLWr.js +1 -0
  255. package/webview-dist/chunks/move-BYnGhZoM.js +1 -0
  256. package/webview-dist/chunks/narrat-_X_XdTYD.js +1 -0
  257. package/webview-dist/chunks/nextflow-BJtWHP5T.js +1 -0
  258. package/webview-dist/chunks/nextflow-groovy-DJMQeKeT.js +1 -0
  259. package/webview-dist/chunks/nginx-rnpjAIVq.js +1 -0
  260. package/webview-dist/chunks/night-owl-DhmEMT88.js +1 -0
  261. package/webview-dist/chunks/night-owl-light-eJ-hLW7d.js +1 -0
  262. package/webview-dist/chunks/nim-kKTJ2fIs.js +1 -0
  263. package/webview-dist/chunks/nix-IvuFDN5E.js +1 -0
  264. package/webview-dist/chunks/nord-Cb4Vim4T.js +1 -0
  265. package/webview-dist/chunks/nsis-CjNLYCLg.js +1 -0
  266. package/webview-dist/chunks/nushell-DHYfO66s.js +1 -0
  267. package/webview-dist/chunks/objective-c-D1A_Heim.js +1 -0
  268. package/webview-dist/chunks/objective-cpp-BsSzOQcm.js +1 -0
  269. package/webview-dist/chunks/ocaml-O90oeIOV.js +1 -0
  270. package/webview-dist/chunks/odin-B1RWQWA5.js +1 -0
  271. package/webview-dist/chunks/one-dark-pro-CLwyXe_n.js +1 -0
  272. package/webview-dist/chunks/one-light-D7Lr4KcI.js +1 -0
  273. package/webview-dist/chunks/openscad-BUDT5pXO.js +1 -0
  274. package/webview-dist/chunks/org-BGWCjkJX.js +1 -0
  275. package/webview-dist/chunks/pascal-4ZHwLPI5.js +1 -0
  276. package/webview-dist/chunks/perl-DEimDILQ.js +1 -0
  277. package/webview-dist/chunks/php-QnaNN--1.js +1 -0
  278. package/webview-dist/chunks/pierre-dark-CpLgRqie.js +1 -0
  279. package/webview-dist/chunks/pierre-dark-protanopia-deuteranopia-B35FxJx-.js +1 -0
  280. package/webview-dist/chunks/pierre-dark-soft-kZQmAZld.js +1 -0
  281. package/webview-dist/chunks/pierre-dark-tritanopia-CpjhbsIL.js +1 -0
  282. package/webview-dist/chunks/pierre-dark-vibrant-CpQYzh95.js +1 -0
  283. package/webview-dist/chunks/pierre-light-CoaEpmwp.js +1 -0
  284. package/webview-dist/chunks/pierre-light-protanopia-deuteranopia-0fSaH845.js +1 -0
  285. package/webview-dist/chunks/pierre-light-soft-lWLdNTOI.js +1 -0
  286. package/webview-dist/chunks/pierre-light-tritanopia-CEbqgOJL.js +1 -0
  287. package/webview-dist/chunks/pierre-light-vibrant-D80Fkn33.js +1 -0
  288. package/webview-dist/chunks/pkl-ot-7Btpt.js +1 -0
  289. package/webview-dist/chunks/plastic-DQwYfKfQ.js +1 -0
  290. package/webview-dist/chunks/plsql-DGHpHOYJ.js +1 -0
  291. package/webview-dist/chunks/po-BiJDBrnU.js +1 -0
  292. package/webview-dist/chunks/poimandres-DRFjx7u4.js +1 -0
  293. package/webview-dist/chunks/polar-C7UOKdEL.js +1 -0
  294. package/webview-dist/chunks/postcss-BXeXVLqQ.js +1 -0
  295. package/webview-dist/chunks/powerquery-DNMTfnFr.js +1 -0
  296. package/webview-dist/chunks/powershell-CCSX75yM.js +1 -0
  297. package/webview-dist/chunks/prisma-DMgNhnYS.js +1 -0
  298. package/webview-dist/chunks/prolog-iXnhIJG7.js +1 -0
  299. package/webview-dist/chunks/proto-DB4EqR-F.js +1 -0
  300. package/webview-dist/chunks/pug-D5rsKmMX.js +1 -0
  301. package/webview-dist/chunks/puppet-CDv2pdJW.js +1 -0
  302. package/webview-dist/chunks/purescript-9MfHhQsQ.js +1 -0
  303. package/webview-dist/chunks/python-gzcpVVnB.js +1 -0
  304. package/webview-dist/chunks/qml-wvbZb8UE.js +1 -0
  305. package/webview-dist/chunks/qmldir-DCQb3MpD.js +1 -0
  306. package/webview-dist/chunks/qss-Fe1Jh2GI.js +1 -0
  307. package/webview-dist/chunks/r-BNyBFaU1.js +1 -0
  308. package/webview-dist/chunks/racket-DcIDlBhZ.js +1 -0
  309. package/webview-dist/chunks/raku-B3gFvitq.js +1 -0
  310. package/webview-dist/chunks/razor-bKaHS6Kz.js +1 -0
  311. package/webview-dist/chunks/rbs-C0MpOrj4.js +1 -0
  312. package/webview-dist/chunks/red-DX1BQOs8.js +1 -0
  313. package/webview-dist/chunks/reg-CRGYupPL.js +1 -0
  314. package/webview-dist/chunks/regexp-B-mZuWUh.js +1 -0
  315. package/webview-dist/chunks/rel-BtDbiS_P.js +1 -0
  316. package/webview-dist/chunks/riscv-Ckw8ddFX.js +1 -0
  317. package/webview-dist/chunks/ron-VUp2lXgN.js +1 -0
  318. package/webview-dist/chunks/rose-pine-aMsaMD1D.js +1 -0
  319. package/webview-dist/chunks/rose-pine-dawn-8PwUyIlP.js +1 -0
  320. package/webview-dist/chunks/rose-pine-moon-DO-qXg-I.js +1 -0
  321. package/webview-dist/chunks/rosmsg-CAekHB0j.js +1 -0
  322. package/webview-dist/chunks/rst-Qq8ybXHe.js +1 -0
  323. package/webview-dist/chunks/ruby-U659LEwU.js +1 -0
  324. package/webview-dist/chunks/rust-Cfkwpbl8.js +1 -0
  325. package/webview-dist/chunks/sas-C4NtLApe.js +1 -0
  326. package/webview-dist/chunks/sass-DXrisJhu.js +1 -0
  327. package/webview-dist/chunks/scala-BiFt_7mu.js +1 -0
  328. package/webview-dist/chunks/scheme-DQCgrYNe.js +1 -0
  329. package/webview-dist/chunks/scss-KAaA4sHk.js +1 -0
  330. package/webview-dist/chunks/sdbl-bTVj8UrX.js +1 -0
  331. package/webview-dist/chunks/shaderlab-TOUzSsQk.js +1 -0
  332. package/webview-dist/chunks/shellscript-_7bOVsRC.js +1 -0
  333. package/webview-dist/chunks/shellsession-Bs_5k0qk.js +1 -0
  334. package/webview-dist/chunks/slack-dark-DnToyrRv.js +1 -0
  335. package/webview-dist/chunks/slack-ochin-B2OO5cIa.js +1 -0
  336. package/webview-dist/chunks/smalltalk-BHpQb5nM.js +1 -0
  337. package/webview-dist/chunks/smithy-Dgaz7aur.js +1 -0
  338. package/webview-dist/chunks/snazzy-light-4G7pJPwS.js +1 -0
  339. package/webview-dist/chunks/solarized-dark-UdsmMDCL.js +1 -0
  340. package/webview-dist/chunks/solarized-light-C1IUL_tW.js +1 -0
  341. package/webview-dist/chunks/solidity-Bj7E1mRn.js +1 -0
  342. package/webview-dist/chunks/soy-C5iuoFCh.js +1 -0
  343. package/webview-dist/chunks/sparql-D_iOobhT.js +1 -0
  344. package/webview-dist/chunks/splunk-BC2Px7Mm.js +1 -0
  345. package/webview-dist/chunks/sql-JX305rZh.js +1 -0
  346. package/webview-dist/chunks/ssh-config-BgfXC-Er.js +1 -0
  347. package/webview-dist/chunks/stata-2Rtik3TV.js +1 -0
  348. package/webview-dist/chunks/stylus-B6D30XZt.js +1 -0
  349. package/webview-dist/chunks/surrealql-IvpiLAIH.js +1 -0
  350. package/webview-dist/chunks/svelte-DeZcV_1u.js +1 -0
  351. package/webview-dist/chunks/swift-CyEgAFGc.js +1 -0
  352. package/webview-dist/chunks/synthwave-84-nFMaYfgc.js +1 -0
  353. package/webview-dist/chunks/system-verilog-Dh5ihWbf.js +1 -0
  354. package/webview-dist/chunks/systemd-BxMlprV5.js +1 -0
  355. package/webview-dist/chunks/talonscript-CohzipZa.js +1 -0
  356. package/webview-dist/chunks/tasl-DMoTqEGO.js +1 -0
  357. package/webview-dist/chunks/tcl-CZd0xW_V.js +1 -0
  358. package/webview-dist/chunks/templ-CcwjPXJr.js +1 -0
  359. package/webview-dist/chunks/terraform-DswuEJGm.js +1 -0
  360. package/webview-dist/chunks/tex-CZYHgHl8.js +1 -0
  361. package/webview-dist/chunks/tokyo-night-oM2G3aXe.js +1 -0
  362. package/webview-dist/chunks/toml-CcmNWLt0.js +1 -0
  363. package/webview-dist/chunks/ts-tags-DPINfEO_.js +1 -0
  364. package/webview-dist/chunks/tsv-sltzmVWM.js +1 -0
  365. package/webview-dist/chunks/tsx-Dq7pSIyE.js +1 -0
  366. package/webview-dist/chunks/turtle-ByJddavk.js +1 -0
  367. package/webview-dist/chunks/twig-DFpC8yDL.js +1 -0
  368. package/webview-dist/chunks/typescript-CN-guYmK.js +1 -0
  369. package/webview-dist/chunks/typespec-BRdr0IET.js +1 -0
  370. package/webview-dist/chunks/typst-hgW4q6mN.js +1 -0
  371. package/webview-dist/chunks/v-DBj4K9d_.js +1 -0
  372. package/webview-dist/chunks/vala-zf12oZj6.js +1 -0
  373. package/webview-dist/chunks/vb-DOwzaHZ0.js +1 -0
  374. package/webview-dist/chunks/verilog-B2gwz-sJ.js +1 -0
  375. package/webview-dist/chunks/vesper-DdrHHSXu.js +1 -0
  376. package/webview-dist/chunks/vhdl-BroJfC0k.js +1 -0
  377. package/webview-dist/chunks/viml-DvXPmvsu.js +1 -0
  378. package/webview-dist/chunks/vitesse-black-fwtXNY1n.js +1 -0
  379. package/webview-dist/chunks/vitesse-dark-BZCL-v6S.js +1 -0
  380. package/webview-dist/chunks/vitesse-light-VbXTXTou.js +1 -0
  381. package/webview-dist/chunks/vue-Dkz9ntel.js +1 -0
  382. package/webview-dist/chunks/vue-html-Dg8LQ5v3.js +1 -0
  383. package/webview-dist/chunks/vue-vine-CIEXICEN.js +1 -0
  384. package/webview-dist/chunks/vyper-CgoNMtux.js +1 -0
  385. package/webview-dist/chunks/wasm-BnjxR4X6.js +1 -0
  386. package/webview-dist/chunks/wasm-ByWQv1Qj.js +1 -0
  387. package/webview-dist/chunks/wenyan-C8pVoKbM.js +1 -0
  388. package/webview-dist/chunks/wgsl-BsKzXJz4.js +1 -0
  389. package/webview-dist/chunks/wikitext-ClFFjSW2.js +1 -0
  390. package/webview-dist/chunks/wit-DdvCle-K.js +1 -0
  391. package/webview-dist/chunks/wolfram-DLL8P-h_.js +1 -0
  392. package/webview-dist/chunks/worker-D52zl71O.js +1 -0
  393. package/webview-dist/chunks/worker-pool-lOjh8Q2A.js +1543 -0
  394. package/webview-dist/chunks/xml-X7YOen_c.js +1 -0
  395. package/webview-dist/chunks/xsl-h4d_Px-X.js +1 -0
  396. package/webview-dist/chunks/yaml-BRDpsfaj.js +1 -0
  397. package/webview-dist/chunks/zenscript-BnlCZFoB.js +1 -0
  398. package/webview-dist/chunks/zig-CMLA9XwU.js +1 -0
  399. package/webview-dist/index.html +18 -0
  400. package/webview-dist/pierre-worker-portable.js +13633 -0
  401. package/webview-dist/repo-timeline-app.js +7 -0
  402. package/webview-dist/repo-timeline.html +14 -0
  403. package/webview-dist/timeline-app.css +2 -0
  404. package/webview-dist/timeline-app.js +85 -0
@@ -0,0 +1,1113 @@
1
+ const require_runtime = require("../_virtual/_rolldown/runtime.cjs");
2
+ const require_constants = require("./constants.cjs");
3
+ const require_blame = require("../shared/blame.cjs");
4
+ const require_resolve_file_path = require("../shared/resolve-file-path.cjs");
5
+ require("./resolve-file-path.cjs");
6
+ const require_timeline_template = require("../webview/timeline-template.cjs");
7
+ const require_line_history = require("../shared/line-history.cjs");
8
+ const require_uri_utils = require("./uri-utils.cjs");
9
+ let node_fs = require("node:fs");
10
+ node_fs = require_runtime.__toESM(node_fs, 1);
11
+ let node_path = require("node:path");
12
+ node_path = require_runtime.__toESM(node_path, 1);
13
+ let vscode = require("vscode");
14
+ vscode = require_runtime.__toESM(vscode, 1);
15
+ //#region src/extension/timeline-panel.ts
16
+ const LARGE_MULTI_DIFF_CONFIRMATION_THRESHOLD = 200;
17
+ function collectPendingSnapshotHydrationIndexes(session) {
18
+ return session.entries.reduce((indexes, entry, index) => {
19
+ if (entry && !entry.isWorkingTree && entry.touchesFile && entry.changeId && !session.snapshotLoadedChangeIds.has(entry.changeId)) indexes.push(index);
20
+ return indexes;
21
+ }, []);
22
+ }
23
+ function postTimelineMessage(request) {
24
+ return Promise.resolve(request.panel.webview.postMessage(request.message));
25
+ }
26
+ async function buildSelectedEntryMultiDiffPlan(request) {
27
+ const files = [];
28
+ for (const entryIndex of request.entryIndexes) {
29
+ const entry = request.sourceEntries[entryIndex];
30
+ if (!entry) continue;
31
+ let plan = {
32
+ title: request.title,
33
+ files: []
34
+ };
35
+ if (entry.isWorkingTree) {
36
+ const previousEntry = request.sourceEntries[entryIndex - 1];
37
+ if (!previousEntry) continue;
38
+ plan = await request.adapter.buildRangeMultiDiffPlan({
39
+ workspacePath: request.workspacePath,
40
+ fromEntry: previousEntry,
41
+ toEntry: entry,
42
+ comparisonSource: request.comparisonSource,
43
+ sourceEntries: request.sourceEntries,
44
+ signal: request.signal
45
+ });
46
+ } else plan = await request.adapter.buildRevisionMultiDiffPlan({
47
+ workspacePath: request.workspacePath,
48
+ entry,
49
+ entryIndex,
50
+ comparisonSource: request.comparisonSource,
51
+ sourceEntries: request.sourceEntries,
52
+ signal: request.signal
53
+ });
54
+ files.push(...plan.files);
55
+ }
56
+ return {
57
+ title: request.title,
58
+ files
59
+ };
60
+ }
61
+ async function resolveTimelineSourcePath(request) {
62
+ const coerced = require_resolve_file_path.coerceFsPath(request.absolutePath);
63
+ if (coerced) return coerced;
64
+ const activeEditor = vscode.window.activeTextEditor;
65
+ if (activeEditor && isWorkspaceFileUri(activeEditor.document.uri)) return activeEditor.document.uri.fsPath;
66
+ return pickOpenWorkspaceEditorPath();
67
+ }
68
+ async function pickOpenWorkspaceEditorPath() {
69
+ const candidates = getOpenWorkspaceEditorCandidates();
70
+ if (!candidates.length) return;
71
+ return (await vscode.window.showQuickPick(candidates.map((candidate) => ({
72
+ label: candidate.label,
73
+ description: candidate.description,
74
+ detail: candidate.detail,
75
+ path: candidate.absolutePath
76
+ })), { placeHolder: "Select a workspace file to open its revision timeline" }))?.path;
77
+ }
78
+ function getOpenWorkspaceEditorCandidates() {
79
+ const candidates = [];
80
+ const seenPaths = /* @__PURE__ */ new Set();
81
+ for (const group of vscode.window.tabGroups?.all || []) for (const tab of group.tabs) {
82
+ const uri = getTabUri(tab);
83
+ if (!uri || uri.scheme !== "file") continue;
84
+ const workspaceFolder = vscode.workspace.getWorkspaceFolder(uri);
85
+ if (!workspaceFolder) continue;
86
+ const absolutePath = uri.fsPath;
87
+ if (seenPaths.has(absolutePath)) continue;
88
+ const relativePath = node_path.default.relative(workspaceFolder.uri.fsPath, absolutePath).replace(/\\/g, "/");
89
+ if (!relativePath || relativePath.startsWith("..")) continue;
90
+ seenPaths.add(absolutePath);
91
+ candidates.push({
92
+ label: node_path.default.basename(absolutePath),
93
+ description: relativePath,
94
+ detail: workspaceFolder.name,
95
+ absolutePath
96
+ });
97
+ }
98
+ return candidates;
99
+ }
100
+ function isWorkspaceFileUri(uri) {
101
+ return uri.scheme === "file" && Boolean(vscode.workspace.getWorkspaceFolder(uri));
102
+ }
103
+ function getTabUri(tab) {
104
+ return tab.input?.uri;
105
+ }
106
+ function createTimelinePanelController(args) {
107
+ const timelineSessions = /* @__PURE__ */ new Map();
108
+ const panelViewReady = /* @__PURE__ */ new WeakMap();
109
+ const panelLoadGeneration = /* @__PURE__ */ new WeakMap();
110
+ let activeTimelinePanel;
111
+ let timelineDebugState = createEmptyTimelineDebugState();
112
+ let timelinePreviewGeneration = 0;
113
+ const lineHistoryStatusBar = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Right, 90);
114
+ lineHistoryStatusBar.command = require_constants.CLEAR_LINE_HISTORY_COMMAND;
115
+ lineHistoryStatusBar.tooltip = "Clear line-history filter (show full file timeline)";
116
+ args.context.subscriptions.push(lineHistoryStatusBar);
117
+ function syncLineHistoryStatusBar(lineHistory) {
118
+ if (!lineHistory) {
119
+ lineHistoryStatusBar.hide();
120
+ return;
121
+ }
122
+ lineHistoryStatusBar.text = `$(git-commit) ${require_line_history.formatStatusBarLineHistoryChip(lineHistory)}`;
123
+ lineHistoryStatusBar.show();
124
+ }
125
+ return {
126
+ dispose() {
127
+ for (const panel of timelineSessions.keys()) panel.dispose();
128
+ timelineSessions.clear();
129
+ activeTimelinePanel = void 0;
130
+ timelineDebugState = createEmptyTimelineDebugState();
131
+ syncLineHistoryStatusBar(null);
132
+ },
133
+ async clearLineHistoryFilter() {
134
+ const panel = activeTimelinePanel;
135
+ const session = panel ? timelineSessions.get(panel) : void 0;
136
+ if (!panel || !session?.lineHistory) {
137
+ if (panel) panel.reveal(void 0, true);
138
+ return;
139
+ }
140
+ await loadSessionIntoPanel({
141
+ panel,
142
+ workspacePath: session.workspacePath,
143
+ absolutePath: session.absolutePath,
144
+ customRevset: session.customRevset
145
+ });
146
+ },
147
+ getDebugState() {
148
+ return { ...timelineDebugState };
149
+ },
150
+ async getDiffLayoutMetrics() {
151
+ const panel = activeTimelinePanel;
152
+ if (!panel) throw new Error("no active timeline panel");
153
+ return await new Promise((resolve, reject) => {
154
+ const timeout = setTimeout(() => {
155
+ subscription.dispose();
156
+ reject(/* @__PURE__ */ new Error("timed out waiting for webview layout metrics"));
157
+ }, 8e3);
158
+ const subscription = panel.webview.onDidReceiveMessage((message) => {
159
+ if (!message || typeof message !== "object") return;
160
+ if (Reflect.get(message, "command") !== "layout-metrics") return;
161
+ const metrics = Reflect.get(message, "metrics");
162
+ if (!metrics || typeof metrics !== "object") return;
163
+ clearTimeout(timeout);
164
+ subscription.dispose();
165
+ resolve(metrics);
166
+ });
167
+ panel.webview.postMessage({ type: "debug-measure-layout" });
168
+ });
169
+ },
170
+ async selectTimelineRange(request) {
171
+ const panel = activeTimelinePanel;
172
+ if (!panel) throw new Error("no active timeline panel");
173
+ const session = timelineSessions.get(panel);
174
+ if (!session) throw new Error("no active timeline session");
175
+ await handleTimelineMessage({
176
+ panel,
177
+ session,
178
+ message: {
179
+ command: "select-entry",
180
+ fromIndex: request.fromIndex,
181
+ toIndex: request.toIndex,
182
+ comparisonSource: request.comparisonSource || "revision"
183
+ }
184
+ });
185
+ },
186
+ async setLayoutMode(layoutMode) {
187
+ const panel = activeTimelinePanel;
188
+ if (!panel) throw new Error("no active timeline panel");
189
+ const nextPreferences = {
190
+ ...args.getPreferences(),
191
+ layoutMode: layoutMode === "unified" ? "unified" : "split"
192
+ };
193
+ await args.savePreferences(nextPreferences);
194
+ await postTimelineMessage({
195
+ panel,
196
+ message: {
197
+ type: "debug-set-layout-mode",
198
+ layoutMode: nextPreferences.layoutMode
199
+ }
200
+ });
201
+ },
202
+ async openFileRevisionTimeline({ absolutePath, lineHistory, focusRevision }) {
203
+ const initialPath = await resolveTimelineSourcePath({ absolutePath });
204
+ if (!initialPath) {
205
+ vscode.window.showErrorMessage("Open a workspace file to browse its revision timeline");
206
+ return;
207
+ }
208
+ const documentUri = vscode.Uri.file(initialPath);
209
+ const workspaceFolder = vscode.workspace.getWorkspaceFolder(documentUri);
210
+ if (!workspaceFolder) {
211
+ vscode.window.showErrorMessage("The active file must belong to a workspace folder");
212
+ return;
213
+ }
214
+ if (documentUri.scheme !== "file") {
215
+ vscode.window.showErrorMessage("The revision timeline only supports files on disk");
216
+ return;
217
+ }
218
+ const fileName = node_path.default.basename(documentUri.fsPath);
219
+ const hadExistingPanel = timelineSessions.size > 0;
220
+ const panel = createTimelinePanel({ fileName });
221
+ activeTimelinePanel = panel;
222
+ panel.webview.html = getTimelineWebviewHtml({
223
+ context: args.context,
224
+ webview: panel.webview
225
+ });
226
+ panel.title = lineHistory ? `Revision Timeline: ${fileName} (L${lineHistory.startLine}${lineHistory.endLine === lineHistory.startLine ? "" : `–${lineHistory.endLine}`})` : `Revision Timeline: ${fileName}`;
227
+ timelineDebugState = {
228
+ ...createEmptyTimelineDebugState(),
229
+ panelOpen: true,
230
+ panelCount: timelineSessions.size + 1,
231
+ panelTitle: panel.title,
232
+ workspacePath: workspaceFolder.uri.fsPath,
233
+ relativePath: node_path.default.relative(workspaceFolder.uri.fsPath, documentUri.fsPath).replace(/\\/g, "/"),
234
+ fileName,
235
+ lineHistory: lineHistory ? {
236
+ startLine: lineHistory.startLine,
237
+ endLine: lineHistory.endLine
238
+ } : null,
239
+ usesBundledWebview: hasBundledTimelineWebviewAssets({ context: args.context })
240
+ };
241
+ if (!hadExistingPanel && shouldMaximizeTimelinePanel()) await maximizeTimelinePanel();
242
+ await loadSessionIntoPanel({
243
+ panel,
244
+ workspacePath: workspaceFolder.uri.fsPath,
245
+ absolutePath: documentUri.fsPath,
246
+ lineHistory,
247
+ customRevset: args.getPreferences().customRevset || void 0,
248
+ focusRevision
249
+ });
250
+ syncLineHistoryStatusBar(lineHistory);
251
+ }
252
+ };
253
+ async function loadSessionIntoPanel(request) {
254
+ const generation = (panelLoadGeneration.get(request.panel) || 0) + 1;
255
+ panelLoadGeneration.set(request.panel, generation);
256
+ const session = await args.service.buildSession({
257
+ workspacePath: request.workspacePath,
258
+ absolutePath: request.absolutePath,
259
+ options: {
260
+ ...request.lineHistory ? { lineHistory: request.lineHistory } : {},
261
+ ...request.customRevset ? { customRevset: request.customRevset } : {}
262
+ }
263
+ });
264
+ if (panelLoadGeneration.get(request.panel) !== generation || request.panel.webview.html === "") return;
265
+ if (!session.entries.length) {
266
+ vscode.window.showInformationMessage("No file revisions were found for the active file");
267
+ if (!timelineSessions.has(request.panel)) request.panel.dispose();
268
+ return;
269
+ }
270
+ timelineSessions.set(request.panel, session);
271
+ activeTimelinePanel = request.panel;
272
+ request.panel.title = session.lineHistory ? `Revision Timeline: ${session.fileName} (L${session.lineHistory.startLine}${session.lineHistory.endLine === session.lineHistory.startLine ? "" : `–${session.lineHistory.endLine}`})` : `Revision Timeline: ${session.fileName}`;
273
+ syncLineHistoryStatusBar(session.lineHistory);
274
+ timelineDebugState = createDebugState({
275
+ panel: request.panel,
276
+ session,
277
+ lastMessageCommand: timelineDebugState.lastMessageCommand,
278
+ panelCount: timelineSessions.size
279
+ });
280
+ timelineDebugState = {
281
+ ...timelineDebugState,
282
+ viewReady: panelViewReady.get(request.panel) === true
283
+ };
284
+ if (panelViewReady.get(request.panel)) await eagerlyBootstrapTimeline({
285
+ panel: request.panel,
286
+ session
287
+ });
288
+ if (request.focusRevision) {
289
+ const match = args.service.mapEntriesForPayload(session.entries).find((entry) => !entry.isWorkingTree && require_blame.revisionMatchesBlame(entry.revision, request.focusRevision));
290
+ if (match && typeof match.index === "number") {
291
+ const fromIndex = Math.max(0, match.index - 1);
292
+ await handleTimelineMessage({
293
+ panel: request.panel,
294
+ session,
295
+ message: {
296
+ command: "select-entry",
297
+ fromIndex,
298
+ toIndex: match.index,
299
+ comparisonSource: "revision"
300
+ }
301
+ });
302
+ }
303
+ }
304
+ }
305
+ function createTimelinePanel(request) {
306
+ const panel = vscode.window.createWebviewPanel("jjRangeDiffTimeline", `Revision Timeline: ${request.fileName}`, getTimelineViewColumn(), {
307
+ enableScripts: true,
308
+ retainContextWhenHidden: true,
309
+ enableFindWidget: true,
310
+ localResourceRoots: [vscode.Uri.joinPath(args.context.extensionUri, "webview"), vscode.Uri.joinPath(args.context.extensionUri, "webview-dist")]
311
+ });
312
+ panel.onDidDispose(() => {
313
+ timelineSessions.get(panel)?.activeActionAbortController?.abort();
314
+ timelineSessions.delete(panel);
315
+ if (activeTimelinePanel === panel) {
316
+ const fallback = [...timelineSessions.entries()].at(-1);
317
+ if (!fallback) {
318
+ activeTimelinePanel = void 0;
319
+ timelineDebugState = createEmptyTimelineDebugState();
320
+ syncLineHistoryStatusBar(null);
321
+ return;
322
+ }
323
+ activeTimelinePanel = fallback[0];
324
+ timelineDebugState = createDebugState({
325
+ panel: fallback[0],
326
+ session: fallback[1],
327
+ lastMessageCommand: timelineDebugState.lastMessageCommand,
328
+ panelCount: timelineSessions.size
329
+ });
330
+ syncLineHistoryStatusBar(fallback[1].lineHistory);
331
+ return;
332
+ }
333
+ timelineDebugState = {
334
+ ...timelineDebugState,
335
+ panelCount: timelineSessions.size
336
+ };
337
+ }, void 0, args.context.subscriptions);
338
+ panel.webview.onDidReceiveMessage(async (message) => {
339
+ try {
340
+ activeTimelinePanel = panel;
341
+ if ((message && typeof message === "object" ? Reflect.get(message, "command") : void 0) === "ready") {
342
+ panelViewReady.set(panel, true);
343
+ const session = timelineSessions.get(panel);
344
+ timelineDebugState = {
345
+ ...session ? createDebugState({
346
+ panel,
347
+ session,
348
+ lastMessageCommand: "ready",
349
+ panelCount: timelineSessions.size
350
+ }) : timelineDebugState,
351
+ viewReady: true,
352
+ readyCount: (timelineDebugState.readyCount || 0) + 1,
353
+ lastReadyAt: Date.now(),
354
+ lastMessageCommand: "ready",
355
+ panelOpen: true,
356
+ panelTitle: panel.title
357
+ };
358
+ if (session?.entries.length) await eagerlyBootstrapTimeline({
359
+ panel,
360
+ session
361
+ });
362
+ return;
363
+ }
364
+ const session = timelineSessions.get(panel);
365
+ if (!session) return;
366
+ await handleTimelineMessage({
367
+ panel,
368
+ session,
369
+ message
370
+ });
371
+ } catch (error) {
372
+ const text = error instanceof Error ? error.message : String(error);
373
+ vscode.window.showErrorMessage(`Timeline action failed: ${text}`);
374
+ }
375
+ }, void 0, args.context.subscriptions);
376
+ return panel;
377
+ }
378
+ async function handleTimelineMessage(request) {
379
+ if (!request.message || typeof request.message !== "object") return;
380
+ const command = Reflect.get(request.message, "command");
381
+ if (typeof command !== "string") return;
382
+ if (command === "ready") return;
383
+ if (command === "layout-metrics") return;
384
+ if (command === "select-entry") {
385
+ const fromIndex = Number(Reflect.get(request.message, "fromIndex"));
386
+ const toIndex = Number(Reflect.get(request.message, "toIndex"));
387
+ const comparisonSource = normalizeComparisonSource(Reflect.get(request.message, "comparisonSource"));
388
+ if (!Number.isInteger(fromIndex) || !Number.isInteger(toIndex)) return;
389
+ await sendTimelinePreview({
390
+ panel: request.panel,
391
+ session: request.session,
392
+ fromIndex,
393
+ toIndex,
394
+ comparisonSource
395
+ });
396
+ return;
397
+ }
398
+ if (command === "load-range-overview") {
399
+ const fromIndex = Number(Reflect.get(request.message, "fromIndex"));
400
+ const toIndex = Number(Reflect.get(request.message, "toIndex"));
401
+ const comparisonSource = normalizeComparisonSource(Reflect.get(request.message, "comparisonSource"));
402
+ const selectedEntryIndexes = Array.isArray(Reflect.get(request.message, "selectedEntryIndexes")) ? Reflect.get(request.message, "selectedEntryIndexes").map((value) => Number(value)).filter((value) => Number.isInteger(value)) : [];
403
+ if (!Number.isInteger(fromIndex) || !Number.isInteger(toIndex)) return;
404
+ await sendRangeOverview({
405
+ panel: request.panel,
406
+ session: request.session,
407
+ fromIndex,
408
+ toIndex,
409
+ comparisonSource,
410
+ selectedEntryIndexes
411
+ });
412
+ return;
413
+ }
414
+ if (command === "load-range-stack") {
415
+ const fromIndex = Number(Reflect.get(request.message, "fromIndex"));
416
+ const toIndex = Number(Reflect.get(request.message, "toIndex"));
417
+ const comparisonSource = normalizeComparisonSource(Reflect.get(request.message, "comparisonSource"));
418
+ const relativePaths = Array.isArray(Reflect.get(request.message, "relativePaths")) ? Reflect.get(request.message, "relativePaths").map((value) => String(value || "").trim()).filter(Boolean) : [];
419
+ if (!Number.isInteger(fromIndex) || !Number.isInteger(toIndex) || !relativePaths.length) return;
420
+ const normalizedFromIndex = Math.max(0, Math.min(fromIndex, toIndex));
421
+ const normalizedToIndex = Math.max(normalizedFromIndex, Math.max(fromIndex, toIndex));
422
+ await postTimelineMessage({
423
+ panel: request.panel,
424
+ message: {
425
+ type: "range-stack-previews",
426
+ payload: {
427
+ fromIndex: normalizedFromIndex,
428
+ toIndex: normalizedToIndex,
429
+ comparisonSource,
430
+ items: await args.service.getRangeStackPreviews({
431
+ session: request.session,
432
+ fromIndex: normalizedFromIndex,
433
+ toIndex: normalizedToIndex,
434
+ comparisonSource,
435
+ relativePaths
436
+ })
437
+ }
438
+ }
439
+ });
440
+ return;
441
+ }
442
+ if (command === "load-diff-blame") {
443
+ const fromIndex = Number(Reflect.get(request.message, "fromIndex"));
444
+ const toIndex = Number(Reflect.get(request.message, "toIndex"));
445
+ const comparisonSource = normalizeComparisonSource(Reflect.get(request.message, "comparisonSource"));
446
+ if (!Number.isInteger(fromIndex) || !Number.isInteger(toIndex)) return;
447
+ const normalizedFromIndex = Math.max(0, Math.min(fromIndex, toIndex));
448
+ const normalizedToIndex = Math.max(normalizedFromIndex, Math.max(fromIndex, toIndex));
449
+ const blame = await args.service.getDiffBlame({
450
+ session: request.session,
451
+ fromIndex: normalizedFromIndex,
452
+ toIndex: normalizedToIndex,
453
+ comparisonSource
454
+ });
455
+ await postTimelineMessage({
456
+ panel: request.panel,
457
+ message: {
458
+ type: "diff-blame",
459
+ payload: {
460
+ fromIndex: normalizedFromIndex,
461
+ toIndex: normalizedToIndex,
462
+ comparisonSource,
463
+ relativePath: blame.relativePath,
464
+ lines: blame.lines
465
+ }
466
+ }
467
+ });
468
+ return;
469
+ }
470
+ if (command === "load-file-oplog") {
471
+ const oplog = await args.service.getFileOpLog({ session: request.session });
472
+ await postTimelineMessage({
473
+ panel: request.panel,
474
+ message: {
475
+ type: "file-oplog",
476
+ payload: {
477
+ relativePath: oplog.relativePath,
478
+ entries: oplog.entries
479
+ }
480
+ }
481
+ });
482
+ return;
483
+ }
484
+ if (command === "load-revision-tree-files") {
485
+ const revision = String(Reflect.get(request.message, "revision") || "@");
486
+ const files = await args.service.loadRevisionTreeFiles({
487
+ session: request.session,
488
+ revision
489
+ });
490
+ await postTimelineMessage({
491
+ panel: request.panel,
492
+ message: {
493
+ type: "revision-tree-files",
494
+ payload: {
495
+ revision,
496
+ files
497
+ }
498
+ }
499
+ });
500
+ return;
501
+ }
502
+ if (command === "search-history") {
503
+ const query = String(Reflect.get(request.message, "query") || "");
504
+ const purpose = Reflect.get(request.message, "purpose") === "sidebar" ? "sidebar" : "history";
505
+ const result = await args.service.searchFileHistory({
506
+ session: request.session,
507
+ query,
508
+ purpose
509
+ });
510
+ await postTimelineMessage({
511
+ panel: request.panel,
512
+ message: {
513
+ type: "history-search",
514
+ payload: {
515
+ ...result,
516
+ purpose
517
+ }
518
+ }
519
+ });
520
+ return;
521
+ }
522
+ if (command === "load-entry-diff-counts") {
523
+ const comparisonSource = normalizeComparisonSource(Reflect.get(request.message, "comparisonSource"));
524
+ const entryIndexes = Array.isArray(Reflect.get(request.message, "entryIndexes")) ? Reflect.get(request.message, "entryIndexes").map((value) => Number(value)).filter((value) => Number.isInteger(value)) : [];
525
+ if (!entryIndexes.length) return;
526
+ await postTimelineMessage({
527
+ panel: request.panel,
528
+ message: {
529
+ type: "entry-diff-counts",
530
+ payload: {
531
+ comparisonSource,
532
+ counts: await args.service.getEntryDiffCounts({
533
+ session: request.session,
534
+ entryIndexes,
535
+ comparisonSource
536
+ })
537
+ }
538
+ }
539
+ });
540
+ return;
541
+ }
542
+ if (command === "hydrate-snapshot-entries") {
543
+ const revisionIndexes = Reflect.get(request.message, "revisionIndexes");
544
+ if (!Array.isArray(revisionIndexes)) return;
545
+ if (!await args.service.hydrateSnapshotEntries({
546
+ session: request.session,
547
+ revisionIndexes: revisionIndexes.map((value) => Number(value)).filter((value) => Number.isInteger(value))
548
+ })) return;
549
+ const payload = buildPayload(request.session);
550
+ await postTimelineMessage({
551
+ panel: request.panel,
552
+ message: {
553
+ type: "snapshot-entries",
554
+ payload: {
555
+ snapshotEntries: payload.snapshotEntries,
556
+ snapshotState: payload.snapshotState
557
+ }
558
+ }
559
+ });
560
+ return;
561
+ }
562
+ if (command === "resolve-nonempty-range") {
563
+ const candidateIndexes = Reflect.get(request.message, "candidateIndexes");
564
+ if (!Array.isArray(candidateIndexes)) return;
565
+ const resolvedRange = await args.service.findNearestNonEmptyVisibleRange({
566
+ session: request.session,
567
+ candidateIndexes: candidateIndexes.map((value) => Number(value)).filter((value) => Number.isInteger(value))
568
+ });
569
+ await postTimelineMessage({
570
+ panel: request.panel,
571
+ message: {
572
+ type: "resolved-range",
573
+ payload: resolvedRange
574
+ }
575
+ });
576
+ return;
577
+ }
578
+ if (command === "open-editor-diff") {
579
+ const fromIndex = Number(Reflect.get(request.message, "fromIndex"));
580
+ const toIndex = Number(Reflect.get(request.message, "toIndex"));
581
+ const comparisonSource = normalizeComparisonSource(Reflect.get(request.message, "comparisonSource"));
582
+ if (!Number.isInteger(fromIndex) || !Number.isInteger(toIndex)) return;
583
+ await openRangeDiffInEditor({
584
+ session: request.session,
585
+ fromIndex,
586
+ toIndex,
587
+ comparisonSource
588
+ });
589
+ return;
590
+ }
591
+ if (command === "open-current-file") {
592
+ await vscode.commands.executeCommand("vscode.open", vscode.Uri.file(request.session.absolutePath), { preview: true });
593
+ return;
594
+ }
595
+ if (command === "open-range-files-diff") {
596
+ const fromIndex = Number(Reflect.get(request.message, "fromIndex"));
597
+ const toIndex = Number(Reflect.get(request.message, "toIndex"));
598
+ const comparisonSource = normalizeComparisonSource(Reflect.get(request.message, "comparisonSource"));
599
+ const selectedEntryIndexes = Array.isArray(Reflect.get(request.message, "selectedEntryIndexes")) ? Reflect.get(request.message, "selectedEntryIndexes").map((value) => Number(value)).filter((value) => Number.isInteger(value)) : [];
600
+ if (!Number.isInteger(fromIndex) || !Number.isInteger(toIndex)) return;
601
+ await openRangeFilesDiff({
602
+ session: request.session,
603
+ fromIndex,
604
+ toIndex,
605
+ comparisonSource,
606
+ selectedEntryIndexes
607
+ });
608
+ return;
609
+ }
610
+ if (command === "open-revision-files-diff") {
611
+ const entryIndex = Number(Reflect.get(request.message, "entryIndex"));
612
+ const comparisonSource = normalizeComparisonSource(Reflect.get(request.message, "comparisonSource"));
613
+ if (!Number.isInteger(entryIndex)) return;
614
+ await openRevisionFilesDiff({
615
+ session: request.session,
616
+ entryIndex,
617
+ comparisonSource
618
+ });
619
+ return;
620
+ }
621
+ if (command === "open-revision-remote") {
622
+ const entryIndex = Number(Reflect.get(request.message, "entryIndex"));
623
+ const comparisonSource = normalizeComparisonSource(Reflect.get(request.message, "comparisonSource"));
624
+ if (!Number.isInteger(entryIndex)) return;
625
+ await openRevisionOnRemote({
626
+ session: request.session,
627
+ entryIndex,
628
+ comparisonSource
629
+ });
630
+ return;
631
+ }
632
+ if (command === "cancel-active-request") {
633
+ request.session.activeActionAbortController?.abort();
634
+ return;
635
+ }
636
+ if (command === "switch-file") {
637
+ const relativePath = String(Reflect.get(request.message, "relativePath") || "").trim();
638
+ if (!relativePath) return;
639
+ await loadSessionIntoPanel({
640
+ panel: request.panel,
641
+ workspacePath: request.session.workspacePath,
642
+ absolutePath: node_path.default.join(request.session.workspacePath, relativePath),
643
+ lineHistory: request.session.lineHistory,
644
+ customRevset: request.session.customRevset
645
+ });
646
+ return;
647
+ }
648
+ if (command === "clear-line-history") {
649
+ await loadSessionIntoPanel({
650
+ panel: request.panel,
651
+ workspacePath: request.session.workspacePath,
652
+ absolutePath: request.session.absolutePath,
653
+ customRevset: request.session.customRevset
654
+ });
655
+ syncLineHistoryStatusBar(null);
656
+ return;
657
+ }
658
+ if (command === "set-custom-revset") {
659
+ const customRevset = String(Reflect.get(request.message, "customRevset") || "").trim();
660
+ const nextPreferences = {
661
+ ...args.getPreferences(),
662
+ customRevset
663
+ };
664
+ await args.savePreferences(nextPreferences);
665
+ await loadSessionIntoPanel({
666
+ panel: request.panel,
667
+ workspacePath: request.session.workspacePath,
668
+ absolutePath: request.session.absolutePath,
669
+ lineHistory: request.session.lineHistory,
670
+ customRevset: customRevset || void 0
671
+ });
672
+ return;
673
+ }
674
+ if (command === "persist-state") {
675
+ await args.savePreferences({
676
+ sidebarWidth: Number(Reflect.get(request.message, "sidebarWidth")),
677
+ sidebarCollapsed: Boolean(Reflect.get(request.message, "sidebarCollapsed")),
678
+ timelinePaneHeight: Number(Reflect.get(request.message, "timelinePaneHeight")),
679
+ timelinePaneCollapsed: Boolean(Reflect.get(request.message, "timelinePaneCollapsed")),
680
+ layoutMode: Reflect.get(request.message, "layoutMode") === "unified" ? "unified" : "split",
681
+ contentMode: Reflect.get(request.message, "contentMode") === "full" ? "full" : "diffs",
682
+ comparisonMode: Reflect.get(request.message, "comparisonMode") === "step" ? "step" : "range",
683
+ comparisonSource: normalizeComparisonSource(Reflect.get(request.message, "comparisonSource")),
684
+ showIntermediateRevisions: Boolean(Reflect.get(request.message, "showIntermediateRevisions")),
685
+ preset: normalizeTimelinePreset(Reflect.get(request.message, "preset")),
686
+ customRevset: String(Reflect.get(request.message, "customRevset") || args.getPreferences().customRevset || ""),
687
+ themePreference: normalizeThemePreference(Reflect.get(request.message, "themePreference")),
688
+ heatmapOpen: Boolean(Reflect.get(request.message, "heatmapOpen")),
689
+ lineDiffType: normalizeLineDiffType(Reflect.get(request.message, "lineDiffType"))
690
+ });
691
+ return;
692
+ }
693
+ if (command === "refresh") {
694
+ await loadSessionIntoPanel({
695
+ panel: request.panel,
696
+ workspacePath: request.session.workspacePath,
697
+ absolutePath: request.session.absolutePath,
698
+ lineHistory: request.session.lineHistory,
699
+ customRevset: request.session.customRevset
700
+ });
701
+ return;
702
+ }
703
+ }
704
+ async function eagerlyBootstrapTimeline(request) {
705
+ const comparisonSource = normalizeComparisonSource(args.getPreferences().comparisonSource);
706
+ if (comparisonSource === "snapshot" && request.session.backend === "jj" && request.session.snapshotLoadedChangeIds.size === 0) await args.service.hydrateSnapshotEntries({
707
+ session: request.session,
708
+ revisionIndexes: collectPendingSnapshotHydrationIndexes(request.session)
709
+ });
710
+ const payload = buildPayload(request.session);
711
+ await postTimelineMessage({
712
+ panel: request.panel,
713
+ message: {
714
+ type: "timeline-data",
715
+ payload
716
+ }
717
+ });
718
+ const defaultFromIndex = Math.max(0, payload.defaultIndex - 1);
719
+ await sendTimelinePreview({
720
+ panel: request.panel,
721
+ session: request.session,
722
+ fromIndex: defaultFromIndex,
723
+ toIndex: payload.defaultIndex,
724
+ comparisonSource
725
+ });
726
+ enrichSessionInBackground({
727
+ panel: request.panel,
728
+ session: request.session
729
+ });
730
+ }
731
+ async function enrichSessionInBackground(request) {
732
+ const generation = panelLoadGeneration.get(request.panel);
733
+ const isCurrent = () => panelLoadGeneration.get(request.panel) === generation && timelineSessions.get(request.panel) === request.session;
734
+ try {
735
+ if (await args.service.ensureWorkspaceFiles({ session: request.session })) {
736
+ if (!isCurrent()) return;
737
+ await postTimelineMessage({
738
+ panel: request.panel,
739
+ message: {
740
+ type: "workspace-files",
741
+ payload: { workspaceFiles: request.session.workspaceFiles }
742
+ }
743
+ });
744
+ }
745
+ const expanded = await args.service.expandFileHistory({ session: request.session });
746
+ const intermediates = await args.service.ensureIntermediateRevisions({ session: request.session });
747
+ if (!isCurrent() || !expanded && !intermediates) return;
748
+ await postTimelineMessage({
749
+ panel: request.panel,
750
+ message: {
751
+ type: "entries-updated",
752
+ payload: {
753
+ entries: args.service.mapEntriesForPayload(request.session.entries),
754
+ hasIntermediateRevisions: request.session.entries.some((entry) => !entry.touchesFile)
755
+ }
756
+ }
757
+ });
758
+ } catch {}
759
+ }
760
+ function buildPayload(session) {
761
+ return args.service.buildPayload({
762
+ session,
763
+ preferences: args.getPreferences(),
764
+ version: args.version,
765
+ presets: require_constants.TIMELINE_PRESET_DAYS
766
+ });
767
+ }
768
+ async function sendTimelinePreview(request) {
769
+ const generation = ++timelinePreviewGeneration;
770
+ const preview = await args.service.getDiffPreview(request);
771
+ if (generation !== timelinePreviewGeneration) return;
772
+ await postTimelineMessage({
773
+ panel: request.panel,
774
+ message: {
775
+ type: "diff-preview",
776
+ payload: preview
777
+ }
778
+ });
779
+ }
780
+ async function sendRangeOverview(request) {
781
+ const normalizedFromIndex = Math.max(0, Math.min(request.fromIndex, request.toIndex));
782
+ const normalizedToIndex = Math.max(normalizedFromIndex, Math.max(request.fromIndex, request.toIndex));
783
+ const selectedEntryIndexes = request.selectedEntryIndexes || [];
784
+ await postTimelineMessage({
785
+ panel: request.panel,
786
+ message: {
787
+ type: "range-overview",
788
+ payload: {
789
+ fromIndex: normalizedFromIndex,
790
+ toIndex: normalizedToIndex,
791
+ comparisonSource: request.comparisonSource,
792
+ selectedEntryIndexes,
793
+ items: await args.service.getRangeOverview({
794
+ session: request.session,
795
+ fromIndex: normalizedFromIndex,
796
+ toIndex: normalizedToIndex,
797
+ comparisonSource: request.comparisonSource,
798
+ selectedEntryIndexes
799
+ })
800
+ }
801
+ }
802
+ });
803
+ }
804
+ async function openRangeDiffInEditor(request) {
805
+ const sourceEntries = args.service.getEntriesForSource({
806
+ session: request.session,
807
+ comparisonSource: request.comparisonSource
808
+ });
809
+ const comparison = args.service.getComparisonEntries({
810
+ entries: sourceEntries,
811
+ fromIndex: request.fromIndex,
812
+ toIndex: request.toIndex
813
+ });
814
+ if (!comparison) return;
815
+ if (!comparison.fromEntry) {
816
+ const uri = await createRevisionUri({
817
+ session: request.session,
818
+ entry: comparison.toEntry
819
+ });
820
+ await vscode.commands.executeCommand("vscode.open", uri, { preview: true });
821
+ return;
822
+ }
823
+ const originalUri = require_uri_utils.createSnapshotUri({
824
+ workspacePath: request.session.workspacePath,
825
+ revset: comparison.fromEntry.revision,
826
+ relativePath: await args.service.resolveEntryFilePath({
827
+ session: request.session,
828
+ entry: comparison.fromEntry,
829
+ entryIndex: Math.max(0, Math.min(request.fromIndex, request.toIndex))
830
+ }),
831
+ backend: request.session.backend
832
+ });
833
+ const modifiedUri = require_uri_utils.createSnapshotUri({
834
+ workspacePath: request.session.workspacePath,
835
+ revset: comparison.toEntry.revision,
836
+ relativePath: await args.service.resolveEntryFilePath({
837
+ session: request.session,
838
+ entry: comparison.toEntry,
839
+ entryIndex: Math.max(request.fromIndex, request.toIndex)
840
+ }),
841
+ backend: request.session.backend
842
+ });
843
+ const title = `${request.session.fileName}: ${comparison.fromEntry.shortRevision} -> ${comparison.toEntry.shortRevision}`;
844
+ await vscode.commands.executeCommand("vscode.diff", originalUri, modifiedUri, title, { preview: true });
845
+ }
846
+ async function openRangeFilesDiff(request) {
847
+ await args.service.runSessionAction({
848
+ session: request.session,
849
+ action: async (signal) => {
850
+ const sourceEntries = args.service.getEntriesForSource({
851
+ session: request.session,
852
+ comparisonSource: request.comparisonSource
853
+ });
854
+ const comparison = args.service.getComparisonEntries({
855
+ entries: sourceEntries,
856
+ fromIndex: request.fromIndex,
857
+ toIndex: request.toIndex
858
+ });
859
+ if (!comparison) return;
860
+ const plan = request.selectedEntryIndexes?.length ? await buildSelectedEntryMultiDiffPlan({
861
+ adapter: request.session.adapter,
862
+ workspacePath: request.session.workspacePath,
863
+ sourceEntries,
864
+ comparisonSource: request.comparisonSource,
865
+ entryIndexes: request.selectedEntryIndexes,
866
+ title: `${comparison.fromEntry.shortRevision}..${comparison.toEntry.shortRevision}`,
867
+ signal
868
+ }) : await request.session.adapter.buildRangeMultiDiffPlan({
869
+ workspacePath: request.session.workspacePath,
870
+ fromEntry: comparison.fromEntry,
871
+ toEntry: comparison.toEntry,
872
+ comparisonSource: request.comparisonSource,
873
+ sourceEntries,
874
+ signal
875
+ });
876
+ if (!plan.files.length) {
877
+ vscode.window.showInformationMessage(`No changes found for ${plan.title}`);
878
+ return;
879
+ }
880
+ if (!await confirmMultiDiffOpen({
881
+ title: plan.title,
882
+ fileCount: plan.files.length
883
+ })) return;
884
+ if (signal.aborted) return;
885
+ await vscode.commands.executeCommand(require_constants.OPEN_MULTI_DIFF_COMMAND, {
886
+ title: plan.title,
887
+ resources: await buildMultiDiffResources({
888
+ workspacePath: request.session.workspacePath,
889
+ files: plan.files
890
+ })
891
+ });
892
+ }
893
+ });
894
+ }
895
+ async function openRevisionFilesDiff(request) {
896
+ await args.service.runSessionAction({
897
+ session: request.session,
898
+ action: async (signal) => {
899
+ const sourceEntries = args.service.getEntriesForSource({
900
+ session: request.session,
901
+ comparisonSource: request.comparisonSource
902
+ });
903
+ const entry = sourceEntries[request.entryIndex];
904
+ if (!entry) return;
905
+ if (entry.isWorkingTree) {
906
+ await openRangeFilesDiff({
907
+ session: request.session,
908
+ fromIndex: Math.max(0, request.entryIndex - 1),
909
+ toIndex: request.entryIndex,
910
+ comparisonSource: request.comparisonSource
911
+ });
912
+ return;
913
+ }
914
+ const plan = await request.session.adapter.buildRevisionMultiDiffPlan({
915
+ workspacePath: request.session.workspacePath,
916
+ entry,
917
+ entryIndex: request.entryIndex,
918
+ comparisonSource: request.comparisonSource,
919
+ sourceEntries,
920
+ signal
921
+ });
922
+ if (!plan.files.length) {
923
+ vscode.window.showInformationMessage(`No files changed in ${entry.shortRevision}`);
924
+ return;
925
+ }
926
+ if (!await confirmMultiDiffOpen({
927
+ title: plan.title,
928
+ fileCount: plan.files.length
929
+ })) return;
930
+ if (signal.aborted) return;
931
+ await vscode.commands.executeCommand(require_constants.OPEN_MULTI_DIFF_COMMAND, {
932
+ title: plan.title,
933
+ resources: await buildMultiDiffResources({
934
+ workspacePath: request.session.workspacePath,
935
+ files: plan.files
936
+ })
937
+ });
938
+ }
939
+ });
940
+ }
941
+ async function openRevisionOnRemote(request) {
942
+ const entry = args.service.getEntriesForSource({
943
+ session: request.session,
944
+ comparisonSource: request.comparisonSource
945
+ })[request.entryIndex];
946
+ if (!entry?.remoteUrl) {
947
+ vscode.window.showInformationMessage("No GitHub remote URL is available for this revision.");
948
+ return;
949
+ }
950
+ await vscode.env.openExternal(vscode.Uri.parse(entry.remoteUrl));
951
+ }
952
+ async function buildMultiDiffResources(request) {
953
+ return Promise.all(request.files.map(async (file) => ({
954
+ originalUri: require_uri_utils.createSnapshotUri({
955
+ workspacePath: request.workspacePath,
956
+ revset: file.originalRevset,
957
+ relativePath: file.relativePath,
958
+ backend: file.backend
959
+ }),
960
+ modifiedUri: await createTargetUri({
961
+ workspacePath: request.workspacePath,
962
+ revset: file.modifiedRevset,
963
+ relativePath: file.relativePath,
964
+ backend: file.backend
965
+ })
966
+ })));
967
+ }
968
+ async function confirmMultiDiffOpen(request) {
969
+ if (request.fileCount <= LARGE_MULTI_DIFF_CONFIRMATION_THRESHOLD) return true;
970
+ const confirmLabel = `Open ${request.fileCount} diffs`;
971
+ return await vscode.window.showWarningMessage(`Open ${request.fileCount} file diffs?`, {
972
+ modal: true,
973
+ detail: `${request.title} touches a large number of files. Opening every diff at once may be slow and create a lot of editors.`
974
+ }, confirmLabel) === confirmLabel;
975
+ }
976
+ async function createTargetUri(request) {
977
+ if (request.revset === "@") {
978
+ const fileUri = vscode.Uri.file(node_path.default.join(request.workspacePath, request.relativePath));
979
+ if (await vscode.workspace.fs.stat(fileUri).then(() => true, () => false)) return fileUri;
980
+ }
981
+ return require_uri_utils.createSnapshotUri({
982
+ workspacePath: request.workspacePath,
983
+ revset: request.revset,
984
+ relativePath: request.relativePath,
985
+ backend: request.backend
986
+ });
987
+ }
988
+ async function createRevisionUri(request) {
989
+ if (request.entry.isWorkingTree) {
990
+ const fileUri = vscode.Uri.file(request.session.absolutePath);
991
+ if (await vscode.workspace.fs.stat(fileUri).then(() => true, () => false)) return fileUri;
992
+ }
993
+ const entryIndex = request.session.entries.findIndex((candidate) => candidate.id === request.entry.id);
994
+ const resolvedPath = await args.service.resolveEntryFilePath({
995
+ session: request.session,
996
+ entry: request.entry,
997
+ entryIndex
998
+ });
999
+ return require_uri_utils.createSnapshotUri({
1000
+ workspacePath: request.session.workspacePath,
1001
+ revset: request.entry.revision,
1002
+ relativePath: resolvedPath,
1003
+ backend: request.session.backend
1004
+ });
1005
+ }
1006
+ }
1007
+ function getTimelineWebviewHtml(args) {
1008
+ if (!hasBundledTimelineWebviewAssets({ context: args.context })) return `<!DOCTYPE html>
1009
+ <html lang="en">
1010
+ <head>
1011
+ <meta charset="UTF-8" />
1012
+ <meta http-equiv="Content-Security-Policy" content="default-src 'none';" />
1013
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
1014
+ <title>Revision Timeline</title>
1015
+ </head>
1016
+ <body>
1017
+ <p>Webview bundle is missing. Run pnpm build:webview and reopen the timeline.</p>
1018
+ </body>
1019
+ </html>`;
1020
+ const appStylePath = vscode.Uri.joinPath(args.context.extensionUri, "webview-dist", "timeline-app.css");
1021
+ const appScriptPath = vscode.Uri.joinPath(args.context.extensionUri, "webview-dist", "timeline-app.js");
1022
+ const workerPath = vscode.Uri.joinPath(args.context.extensionUri, "webview-dist", "pierre-worker-portable.js");
1023
+ return require_timeline_template.renderTimelineDocumentHtml({
1024
+ title: "Revision Timeline",
1025
+ cspSource: args.webview.cspSource,
1026
+ styleHref: String(args.webview.asWebviewUri(appStylePath)),
1027
+ appSrc: String(args.webview.asWebviewUri(appScriptPath)),
1028
+ workerSrc: String(args.webview.asWebviewUri(workerPath))
1029
+ });
1030
+ }
1031
+ function hasBundledTimelineWebviewAssets(args) {
1032
+ const appStylePath = vscode.Uri.joinPath(args.context.extensionUri, "webview-dist", "timeline-app.css");
1033
+ const appScriptPath = vscode.Uri.joinPath(args.context.extensionUri, "webview-dist", "timeline-app.js");
1034
+ return node_fs.default.existsSync(appStylePath.fsPath) && node_fs.default.existsSync(appScriptPath.fsPath);
1035
+ }
1036
+ function createEmptyTimelineDebugState() {
1037
+ return {
1038
+ panelOpen: false,
1039
+ panelCount: 0,
1040
+ panelTitle: "",
1041
+ backend: "",
1042
+ workspacePath: "",
1043
+ relativePath: "",
1044
+ fileName: "",
1045
+ entryCount: 0,
1046
+ snapshotEntryCount: 0,
1047
+ lineHistory: null,
1048
+ usesBundledWebview: false,
1049
+ viewReady: false,
1050
+ readyCount: 0,
1051
+ lastMessageCommand: "",
1052
+ lastReadyAt: 0,
1053
+ entries: []
1054
+ };
1055
+ }
1056
+ function createDebugState(args) {
1057
+ return {
1058
+ panelOpen: true,
1059
+ panelCount: args.panelCount,
1060
+ panelTitle: args.panel.title,
1061
+ backend: args.session.backend,
1062
+ workspacePath: args.session.workspacePath,
1063
+ relativePath: args.session.relativePath,
1064
+ fileName: args.session.fileName,
1065
+ entryCount: args.session.entries.length,
1066
+ snapshotEntryCount: args.session.snapshotEntries.length,
1067
+ lineHistory: args.session.lineHistory ? {
1068
+ startLine: args.session.lineHistory.startLine,
1069
+ endLine: args.session.lineHistory.endLine
1070
+ } : null,
1071
+ usesBundledWebview: true,
1072
+ viewReady: false,
1073
+ readyCount: 0,
1074
+ lastMessageCommand: args.lastMessageCommand,
1075
+ lastReadyAt: 0,
1076
+ entries: args.session.entries.map((entry) => ({
1077
+ index: entry.index ?? 0,
1078
+ description: entry.description,
1079
+ shortRevision: entry.shortRevision
1080
+ }))
1081
+ };
1082
+ }
1083
+ function normalizeComparisonSource(value) {
1084
+ return value === "snapshot" ? "snapshot" : "revision";
1085
+ }
1086
+ function normalizeThemePreference(value) {
1087
+ return value === "light" || value === "dark" ? value : "auto";
1088
+ }
1089
+ function normalizeLineDiffType(value) {
1090
+ return value === "word" || value === "char" || value === "none" || value === "word-alt" ? value : "word-alt";
1091
+ }
1092
+ function normalizeTimelinePreset(value) {
1093
+ return typeof value === "string" && value in require_constants.TIMELINE_PRESET_DAYS ? value : "year";
1094
+ }
1095
+ async function maximizeTimelinePanel() {
1096
+ try {
1097
+ await vscode.commands.executeCommand("workbench.action.toggleMaximizeEditorGroup");
1098
+ } catch {}
1099
+ }
1100
+ function shouldMaximizeTimelinePanel() {
1101
+ return getEditorGroupCount() > 1;
1102
+ }
1103
+ function getTimelineViewColumn() {
1104
+ return shouldMaximizeTimelinePanel() ? vscode.ViewColumn.Beside : vscode.ViewColumn.Active;
1105
+ }
1106
+ function getEditorGroupCount() {
1107
+ const groups = vscode.window.tabGroups?.all;
1108
+ return Array.isArray(groups) && groups.length ? groups.length : 1;
1109
+ }
1110
+ //#endregion
1111
+ exports.createTimelinePanelController = createTimelinePanelController;
1112
+
1113
+ //# sourceMappingURL=timeline-panel.cjs.map