@hienlh/ppm 0.22.0 → 0.22.1

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 (92) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/CLAUDE.md +1 -1
  3. package/assets/skills/ppm/SKILL.md +1 -1
  4. package/assets/skills/ppm/references/cli-reference.md +4 -4
  5. package/assets/skills/ppm/references/http-api.md +1 -1
  6. package/dist/web/assets/accounts-settings-section-D3BylchP.js +1 -0
  7. package/dist/web/assets/{ai-resource-editor-CdDpOwjh.js → ai-resource-editor-BLPcnhTM.js} +1 -1
  8. package/dist/web/assets/{ai-settings-section-X2UOfSaS.js → ai-settings-section-BtR7rF-T.js} +1 -1
  9. package/dist/web/assets/{ai-settings-section-B1hQyjAd.js → ai-settings-section-r9JctHNM.js} +1 -1
  10. package/dist/web/assets/{appearance-settings-section-DLoPK0LD.js → appearance-settings-section-CiMdk3sb.js} +1 -1
  11. package/dist/web/assets/{branch-review-tab-G84Ojzae.js → branch-review-tab-B1pFjlKM.js} +1 -1
  12. package/dist/web/assets/chat-tab-DZagX06m.js +15 -0
  13. package/dist/web/assets/{code-editor-D04iUPsZ.js → code-editor-BJhOEsnZ.js} +4 -4
  14. package/dist/web/assets/{codex-daily-guard-BSccLRGT.js → codex-daily-guard-CaCQJ4r_.js} +1 -1
  15. package/dist/web/assets/{conflict-editor-C4ay676e.js → conflict-editor-B7u_p49h.js} +3 -3
  16. package/dist/web/assets/{csv-preview-DbwEmG7o.js → csv-preview-CttjJU1e.js} +1 -1
  17. package/dist/web/assets/{database-viewer-S6LsALjX.js → database-viewer-Ca4HxIfx.js} +1 -1
  18. package/dist/web/assets/{diff-viewer-3oBA7vgQ.js → diff-viewer-9-XjLIwa.js} +1 -1
  19. package/dist/web/assets/{editor-language-service-DJmaKVY0.js → editor-language-service-D0DuEOs_.js} +1 -1
  20. package/dist/web/assets/{explorer-body-BQ0jyAGv.js → explorer-body-VdCBqcZu.js} +2 -2
  21. package/dist/web/assets/{explorer-window-content-jdkWt34J.js → explorer-window-content-BIsbl7Th.js} +1 -1
  22. package/dist/web/assets/extension-manager-section-HkY7geS5.js +1 -0
  23. package/dist/web/assets/{extension-webview-BGSDUbdK.js → extension-webview-DZG8YHX9.js} +1 -1
  24. package/dist/web/assets/{files-settings-section-Gnyd7han.js → files-settings-section-qnRtkX05.js} +1 -1
  25. package/dist/web/assets/{general-settings-section-V6Khh15V.js → general-settings-section-BAFSZmCE.js} +1 -1
  26. package/dist/web/assets/{git-log-panel-Bi513qjT.js → git-log-panel-2sGpfEla.js} +1 -1
  27. package/dist/web/assets/{glide-data-grid-DnQwYSmQ.js → glide-data-grid-f0hyITiF.js} +1 -1
  28. package/dist/web/assets/{group-chat-tab-DpczdwyV.js → group-chat-tab-Ck6sk7yY.js} +1 -1
  29. package/dist/web/assets/index-CEZVxM4G.js +52 -0
  30. package/dist/web/assets/{jira-watcher-section-f2HUbGDY.js → jira-watcher-section-CeLmhvu1.js} +1 -1
  31. package/dist/web/assets/keybindings-store-C_3ChOEf.js +1 -0
  32. package/dist/web/assets/{keyboard-shortcuts-section-BpvVEw_Y.js → keyboard-shortcuts-section-PVz6kuh2.js} +1 -1
  33. package/dist/web/assets/markdown-renderer-C140Ijk0.js +3 -0
  34. package/dist/web/assets/{markdown-renderer-Bcaf9_bA.js → markdown-renderer-Dz7-DYUg.js} +1 -1
  35. package/dist/web/assets/{mobile-explorer-sheet-Bol3XAO1.js → mobile-explorer-sheet-CUG_owdf.js} +1 -1
  36. package/dist/web/assets/notification-store-6vib1ISy.js +1 -0
  37. package/dist/web/assets/{ppmbot-settings-section-DKJUA3Kq.js → ppmbot-settings-section-Cji-Mil-.js} +1 -1
  38. package/dist/web/assets/{problems-panel-CFcoUx8h.js → problems-panel-a6_hrWvl.js} +1 -1
  39. package/dist/web/assets/{process-table-EKr2dqG6.js → process-table-CiIqlOIK.js} +1 -1
  40. package/dist/web/assets/{proxy-settings-section-B7qRVl8w.js → proxy-settings-section-BjI4IFgp.js} +1 -1
  41. package/dist/web/assets/{remote-desktop-clipboard-notice-0WDYsyCA.js → remote-desktop-clipboard-notice-eXYvwgx7.js} +1 -1
  42. package/dist/web/assets/{remote-desktop-mobile-sheet-COYDg16H.js → remote-desktop-mobile-sheet-Doh-fci-.js} +2 -2
  43. package/dist/web/assets/{remote-desktop-mobile-view-2DqSuS2U.js → remote-desktop-mobile-view-Dt8Akc3p.js} +1 -1
  44. package/dist/web/assets/{remote-desktop-readiness-gate-Dm_qMJMH.js → remote-desktop-readiness-gate-t83fqbID.js} +1 -1
  45. package/dist/web/assets/{remote-desktop-window-content-UodhsF7W.js → remote-desktop-window-content-CguhZMmx.js} +1 -1
  46. package/dist/web/assets/{schedules-settings-section-bG2lYfGv.js → schedules-settings-section-BVkpW5ms.js} +1 -1
  47. package/dist/web/assets/{settings-body-C06bFarv.js → settings-body-CoIxYAh6.js} +2 -2
  48. package/dist/web/assets/{settings-tab-34RSaASd.js → settings-tab-7DKVUTbM.js} +1 -1
  49. package/dist/web/assets/{settings-window-content-Dr_2lmHH.js → settings-window-content-3_39TeX-.js} +1 -1
  50. package/dist/web/assets/{sql-query-editor-BgRH0cHD.js → sql-query-editor-CQB7Yp7U.js} +1 -1
  51. package/dist/web/assets/{sqlite-viewer-DUxGslpa.js → sqlite-viewer-Bd7rjr1D.js} +1 -1
  52. package/dist/web/assets/{system-monitor-body-IZuLn7Qh.js → system-monitor-body-DsRXeMyU.js} +2 -2
  53. package/dist/web/assets/{system-monitor-tab-DiSA490Z.js → system-monitor-tab-DdSZgux3.js} +1 -1
  54. package/dist/web/assets/{system-monitor-window-content-CEaFISgj.js → system-monitor-window-content-ClPo4-El.js} +1 -1
  55. package/dist/web/assets/{tab-host-window-content-D0TN8Wrq.js → tab-host-window-content-d2TAD4PU.js} +1 -1
  56. package/dist/web/assets/{team-member-sheet-DDPNcCjd.js → team-member-sheet-7d2Qp-ie.js} +2 -2
  57. package/dist/web/assets/{team-member-window-content-DCiW_1-E.js → team-member-window-content-Bctg2gmg.js} +1 -1
  58. package/dist/web/assets/{terminal-tab-4ypP0NDY.js → terminal-tab-0HQic25V.js} +3 -3
  59. package/dist/web/assets/{tool-cards-Dd6E7Q3k.js → tool-cards-CmLLRACd.js} +2 -2
  60. package/dist/web/assets/{use-inline-blame-vrfFHuaR.js → use-inline-blame-sDMjcz1-.js} +3 -3
  61. package/dist/web/assets/{use-lsp-CsuZu49X.js → use-lsp-CBgID-EU.js} +1 -1
  62. package/dist/web/assets/{use-monaco-theme-BIVYJBIn.js → use-monaco-theme-gvhJ_jZh.js} +1 -1
  63. package/dist/web/assets/{use-websocket-BMbufhX7.js → use-websocket-C9wlRliB.js} +1 -1
  64. package/dist/web/assets/{video-preview-Byj8P_jA.js → video-preview-CSDK5j6H.js} +1 -1
  65. package/dist/web/index.html +1 -1
  66. package/dist/web/sw.js +1 -1
  67. package/docs/architecture/ai-chat-and-providers.md +9 -0
  68. package/package.json +1 -1
  69. package/packages/ext-git-graph/src/webview-html.test.ts +30 -5
  70. package/packages/ext-git-graph/src/webview-html.ts +99 -31
  71. package/src/services/edge-forwarder.ts +191 -191
  72. package/src/services/windows-process-tree.ts +351 -351
  73. package/src/shared/codex-daily-guard.ts +12 -5
  74. package/src/web/components/extensions/extension-tree-view.tsx +4 -11
  75. package/src/web/components/layout/command-palette.tsx +2 -18
  76. package/src/web/components/settings/accounts/account-card.tsx +2 -2
  77. package/src/web/components/settings/accounts/codex-accounts-section.tsx +4 -4
  78. package/src/web/components/settings/extension-manager-section.tsx +8 -1
  79. package/src/web/lib/extension-icons.ts +70 -0
  80. package/src/web/lib/tab-type-icons.ts +14 -0
  81. package/dist/web/assets/accounts-settings-section-BVr9-FZJ.js +0 -1
  82. package/dist/web/assets/chat-tab-DQJfjm8E.js +0 -15
  83. package/dist/web/assets/extension-manager-section-DG1guILi.js +0 -1
  84. package/dist/web/assets/index-DU68xk06.js +0 -52
  85. package/dist/web/assets/keybindings-store-DCRsnKg5.js +0 -1
  86. package/dist/web/assets/markdown-renderer-DGJp8HC3.js +0 -3
  87. package/dist/web/assets/notification-store-BXt54VIn.js +0 -1
  88. package/packages/vscode-compat/node_modules/.bin/tsc.bunx +0 -0
  89. package/packages/vscode-compat/node_modules/.bin/tsc.exe +0 -0
  90. package/packages/vscode-compat/node_modules/.bin/tsserver.bunx +0 -0
  91. package/packages/vscode-compat/node_modules/.bin/tsserver.exe +0 -0
  92. package/src/web/hooks/use-delayed-flag.ts +0 -35
@@ -1,7 +1,7 @@
1
- import{o as e}from"./rolldown-runtime-FhOqtrmT.js";import{C as t}from"./vendor-markdown-CuWCHIVb.js";import{n,s as r}from"./api-client-C1ZwRL4Y.js";import{i}from"./project-store-B87hLRSk.js";import{Et as a,Qt as o}from"./index-DU68xk06.js";`0`.repeat(40);function s(e){return/^0+$/.test(e)}function c(e,t=Date.now()){if(!e)return``;if(s(e.hash))return`You, uncommitted changes`;let n=e.author||`Unknown`,r=e.authorTime>0?l(e.authorTime*1e3,t):``,i=r?`${n}, ${r}`:n;return e.summary?`${i} • ${e.summary}`:i}function l(e,t=Date.now()){let n=Math.max(0,Math.round((t-e)/1e3));if(n<60)return`just now`;for(let[e,t,r]of[[3600,60,`minute`],[86400,3600,`hour`],[2592e3,86400,`day`],[31536e3,2592e3,`month`],[1/0,31536e3,`year`]])if(n<e){let e=Math.floor(n/t);return`${e} ${r}${e===1?``:`s`} ago`}return`just now`}function u(e){let t=new Date(e),n=[`January`,`February`,`March`,`April`,`May`,`June`,`July`,`August`,`September`,`October`,`November`,`December`],r=t.getDate(),i=t.getHours()%12||12,a=String(t.getMinutes()).padStart(2,`0`),o=t.getHours()<12?`AM`:`PM`;return`${n[t.getMonth()]} ${r}${d(r)}, ${t.getFullYear()} ${i}:${a} ${o}`}function d(e){return e%100>=11&&e%100<=13?`th`:[`th`,`st`,`nd`,`rd`][e%10]??`th`}var f=[`ppm.blame.copySha`,`ppm.blame.fileHistory`,`ppm.blame.blameFile`,`ppm.blame.showInGraph`],p=7;function m(e){return e.replace(/[\\`*_{}[\]()#+\-!<>]/g,e=>`\\${e}`)}function h(e){let t=e.trim().split(/\s+/).filter(Boolean);return t.length===0?`?`:(t[0][0]+(t.length>1?t[t.length-1][0]:``)).toUpperCase()}var g=[`4E79A7`,`F28E2B`,`E15759`,`76B7B2`,`59A14F`,`AF7AA1`,`9C755F`,`B07AA1`];function _(e){let t=0;for(let n=0;n<e.length;n++)t=t*31+e.charCodeAt(n)|0;return g[Math.abs(t)%g.length]}function v(e){let t=`<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><circle cx="8" cy="8" r="8" fill="#${_(e)}"/><text x="8" y="11.5" font-family="sans-serif" font-size="7" font-weight="700" fill="#ffffff" text-anchor="middle">${y(h(e))}</text></svg>`;return`data:image/svg+xml;charset=utf-8,${encodeURIComponent(t)}`}function y(e){return e.replace(/&/g,`&amp;`).replace(/</g,`&lt;`).replace(/>/g,`&gt;`).replace(/"/g,`&quot;`)}function b(e,t){return`command:${e}?${encodeURIComponent(JSON.stringify(t))}`}function x(e){let{commit:t,detail:n,filePath:r,projectPath:i,now:a=Date.now()}=e;if(s(t.hash))return null;let o=t.author||`Unknown`,c=t.hash.slice(0,p),d=[],h=t.authorTime>0?`${l(t.authorTime*1e3,a)} (${u(t.authorTime*1e3)})`:``;d.push(`![](${v(o)}) **${m(o)}**${h?` &nbsp;$(history) ${m(h)}`:``}`);let g=n?.message||t.summary;g&&(d.push(``),d.push(m(g).split(`
1
+ import{o as e}from"./rolldown-runtime-FhOqtrmT.js";import{C as t}from"./vendor-markdown-CuWCHIVb.js";import{n,s as r}from"./api-client-C1ZwRL4Y.js";import{i}from"./project-store-B87hLRSk.js";import{$t as a,Et as o}from"./index-CEZVxM4G.js";`0`.repeat(40);function s(e){return/^0+$/.test(e)}function c(e,t=Date.now()){if(!e)return``;if(s(e.hash))return`You, uncommitted changes`;let n=e.author||`Unknown`,r=e.authorTime>0?l(e.authorTime*1e3,t):``,i=r?`${n}, ${r}`:n;return e.summary?`${i} • ${e.summary}`:i}function l(e,t=Date.now()){let n=Math.max(0,Math.round((t-e)/1e3));if(n<60)return`just now`;for(let[e,t,r]of[[3600,60,`minute`],[86400,3600,`hour`],[2592e3,86400,`day`],[31536e3,2592e3,`month`],[1/0,31536e3,`year`]])if(n<e){let e=Math.floor(n/t);return`${e} ${r}${e===1?``:`s`} ago`}return`just now`}function u(e){let t=new Date(e),n=[`January`,`February`,`March`,`April`,`May`,`June`,`July`,`August`,`September`,`October`,`November`,`December`],r=t.getDate(),i=t.getHours()%12||12,a=String(t.getMinutes()).padStart(2,`0`),o=t.getHours()<12?`AM`:`PM`;return`${n[t.getMonth()]} ${r}${d(r)}, ${t.getFullYear()} ${i}:${a} ${o}`}function d(e){return e%100>=11&&e%100<=13?`th`:[`th`,`st`,`nd`,`rd`][e%10]??`th`}var f=[`ppm.blame.copySha`,`ppm.blame.fileHistory`,`ppm.blame.blameFile`,`ppm.blame.showInGraph`],p=7;function m(e){return e.replace(/[\\`*_{}[\]()#+\-!<>]/g,e=>`\\${e}`)}function h(e){let t=e.trim().split(/\s+/).filter(Boolean);return t.length===0?`?`:(t[0][0]+(t.length>1?t[t.length-1][0]:``)).toUpperCase()}var g=[`4E79A7`,`F28E2B`,`E15759`,`76B7B2`,`59A14F`,`AF7AA1`,`9C755F`,`B07AA1`];function _(e){let t=0;for(let n=0;n<e.length;n++)t=t*31+e.charCodeAt(n)|0;return g[Math.abs(t)%g.length]}function v(e){let t=`<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><circle cx="8" cy="8" r="8" fill="#${_(e)}"/><text x="8" y="11.5" font-family="sans-serif" font-size="7" font-weight="700" fill="#ffffff" text-anchor="middle">${y(h(e))}</text></svg>`;return`data:image/svg+xml;charset=utf-8,${encodeURIComponent(t)}`}function y(e){return e.replace(/&/g,`&amp;`).replace(/</g,`&lt;`).replace(/>/g,`&gt;`).replace(/"/g,`&quot;`)}function b(e,t){return`command:${e}?${encodeURIComponent(JSON.stringify(t))}`}function x(e){let{commit:t,detail:n,filePath:r,projectPath:i,now:a=Date.now()}=e;if(s(t.hash))return null;let o=t.author||`Unknown`,c=t.hash.slice(0,p),d=[],h=t.authorTime>0?`${l(t.authorTime*1e3,a)} (${u(t.authorTime*1e3)})`:``;d.push(`![](${v(o)}) **${m(o)}**${h?` &nbsp;$(history) ${m(h)}`:``}`);let g=n?.message||t.summary;g&&(d.push(``),d.push(m(g).split(`
2
2
  `).join(`
3
3
  `)));let _=[``,`---`,``],y=[`[$(git-commit) ${c}](${b(`ppm.blame.copySha`,[t.hash])} "Copy commit hash")`];i&&y.push(`[$(history) File History](${b(`ppm.blame.fileHistory`,[i,r])} "Open the file's history")`,`[$(users) Blame](${b(`ppm.blame.blameFile`,[i,r])} "Open the blame view")`,`[$(git-branch) Graph](${b(`ppm.blame.showInGraph`,[i])} "Open the commit graph")`),d.push(..._),d.push(y.join(` &nbsp; `));let x=[...(n?.removed??[]).map(e=>`-${e}`),...(n?.added??[]).map(e=>`+${e}`)];if(x.length>0){d.push(..._),d.push("```diff"),d.push(...x),d.push("```"),d.push(``);let e=(n?.removed.length??0)===0?`added in`:`in`;d.push(`Changes ${e} \`${c}\``)}return{value:d.join(`
4
- `),isTrusted:{enabledCommands:[...f]},supportThemeIcons:!0}}var S=!1;function C(e,t){window.dispatchEvent(new CustomEvent(`ext:command:execute`,{detail:{command:e,args:t}}))}function w(e){return typeof e==`string`&&/^[0-9a-f]{7,40}$/.test(e)?e:null}function T(e){return typeof e==`string`&&e.length>0?e:null}function E(e,t,n){let r=T(t),i=T(n);!r||!i||C(e,[r,i])}function D(e){S||(S=!0,e.editor.registerCommand(`ppm.blame.copySha`,(e,t)=>{let n=w(t);n&&o(n).then(e=>{r[e?`success`:`error`](e?`Copied ${n.slice(0,7)}`:`Could not copy`)})}),e.editor.registerCommand(`ppm.blame.fileHistory`,(e,t,n)=>{E(`git-graph.fileHistory`,t,n)}),e.editor.registerCommand(`ppm.blame.blameFile`,(e,t,n)=>{E(`git-graph.blame`,t,n)}),e.editor.registerCommand(`ppm.blame.showInGraph`,(e,t)=>{let n=T(t);n&&C(`git-graph.view`,[n])}))}var O=`diff`,k=!1;function A(e){if(!k){if(e.languages.getLanguages().some(e=>e.id===`diff`)){k=!0;return}e.languages.register({id:O,aliases:[`Diff`,`patch`],extensions:[`.diff`,`.patch`]}),e.languages.setMonarchTokensProvider(O,{tokenizer:{root:[[/^diff .*$/,`meta.diff.header`],[/^(index|similarity index|rename from|rename to|new file mode|deleted file mode|old mode|new mode) .*$/,`meta.diff.header`],[/^(\+\+\+|---) .*$/,`meta.diff.header`],[/^@@.*$/,`meta.diff.range`],[/^\+.*$/,`inserted`],[/^-.*$/,`deleted`],[/^\\ .*$/,`meta.diff.header`],[/^.*$/,``]]}}),k=!0}}var j=e(t(),1),M=`inline-blame-styles`,N=`
4
+ `),isTrusted:{enabledCommands:[...f]},supportThemeIcons:!0}}var S=!1;function C(e,t){window.dispatchEvent(new CustomEvent(`ext:command:execute`,{detail:{command:e,args:t}}))}function w(e){return typeof e==`string`&&/^[0-9a-f]{7,40}$/.test(e)?e:null}function T(e){return typeof e==`string`&&e.length>0?e:null}function E(e,t,n){let r=T(t),i=T(n);!r||!i||C(e,[r,i])}function D(e){S||(S=!0,e.editor.registerCommand(`ppm.blame.copySha`,(e,t)=>{let n=w(t);n&&a(n).then(e=>{r[e?`success`:`error`](e?`Copied ${n.slice(0,7)}`:`Could not copy`)})}),e.editor.registerCommand(`ppm.blame.fileHistory`,(e,t,n)=>{E(`git-graph.fileHistory`,t,n)}),e.editor.registerCommand(`ppm.blame.blameFile`,(e,t,n)=>{E(`git-graph.blame`,t,n)}),e.editor.registerCommand(`ppm.blame.showInGraph`,(e,t)=>{let n=T(t);n&&C(`git-graph.view`,[n])}))}var O=`diff`,k=!1;function A(e){if(!k){if(e.languages.getLanguages().some(e=>e.id===`diff`)){k=!0;return}e.languages.register({id:O,aliases:[`Diff`,`patch`],extensions:[`.diff`,`.patch`]}),e.languages.setMonarchTokensProvider(O,{tokenizer:{root:[[/^diff .*$/,`meta.diff.header`],[/^(index|similarity index|rename from|rename to|new file mode|deleted file mode|old mode|new mode) .*$/,`meta.diff.header`],[/^(\+\+\+|---) .*$/,`meta.diff.header`],[/^@@.*$/,`meta.diff.range`],[/^\+.*$/,`inserted`],[/^-.*$/,`deleted`],[/^\\ .*$/,`meta.diff.header`],[/^.*$/,``]]}}),k=!0}}var j=e(t(),1),M=`inline-blame-styles`,N=`
5
5
  .inline-blame-annotation {
6
6
  color: var(--color-muted-foreground);
7
7
  opacity: 0.6;
@@ -13,4 +13,4 @@ import{o as e}from"./rolldown-runtime-FhOqtrmT.js";import{C as t}from"./vendor-m
13
13
  .monaco-hover img {
14
14
  vertical-align: text-bottom;
15
15
  }
16
- `;function P(e){let t=e.getDomNode()?.ownerDocument??document;if(t.getElementById(M))return;let n=t.createElement(`style`);n.id=M,n.textContent=N,t.head?.appendChild(n)}function F({editor:e,monaco:t,projectName:r,filePath:o,rev:l,enabled:u,readOnly:d=!1}){let[f,p]=(0,j.useState)(null),[m,h]=(0,j.useState)(!1),[g,_]=(0,j.useState)(0),[v,y]=(0,j.useState)(0),[b,S]=(0,j.useState)(null),C=(0,j.useRef)(new Map),w=(0,j.useRef)(null),T=(0,j.useRef)(0),E=i(e=>e.projects.find(e=>e.name===r)?.path),O=a(r),k=O.repo?.path??E,M=o?O.repoPath(o):null,N=(0,j.useCallback)(()=>y(e=>e+1),[]);(0,j.useEffect)(()=>{!t||!u||(A(t),D(t))},[t,u]),(0,j.useEffect)(()=>{if(!u||!r||!o||M==null){p(null);return}let e=!1,t=new URLSearchParams({path:M});return l&&t.set(`rev`,l),n.get(O.gitUrl(`/blame?${t}`)).then(t=>{e||(p(t),h(!1))}).catch(()=>{e||p(null)}),()=>{e=!0}},[u,r,o,M,l,v,O]),(0,j.useEffect)(()=>{if(!e||!u)return;_(e.getPosition()?.lineNumber??0);let t=e.onDidChangeCursorPosition(e=>_(e.position.lineNumber));if(d)return()=>t.dispose();let n=e.onDidChangeModelContent(()=>h(!0));return()=>{t.dispose(),n.dispose()}},[e,u,d]),(0,j.useEffect)(()=>{if(!e||!u||!window.matchMedia?.(`(hover: none)`).matches)return;let t=e.onMouseDown(t=>{let n=t.target.position,r=e.getModel();!n||!r||n.lineNumber===T.current&&(n.column<r.getLineMaxColumn(n.lineNumber)||e.getAction(`editor.action.showHover`)?.run())});return()=>t.dispose()},[e,u]);let F=(()=>{if(!f||m||g<=0)return null;let e=f.lines[g-1],t=e?.finalLine===g?e:f.lines.find(e=>e.finalLine===g);if(!t)return null;let n=f.commits[t.hash];return n?{commit:n,origLine:t.origLine}:null})(),I=F?.commit??null,L=I&&!s(I.hash)?I.hash:null,R=I?.filename||M||void 0,z=F?.origLine??0,B=`${L} ${z} ${R}`;return(0,j.useEffect)(()=>{if(!u||!r||!L||!R||z<1){S(null);return}let e=B,t=C.current;if(t.has(e)){S({key:e,value:t.get(e)??null});return}let i=!1,a=new URLSearchParams({hash:L,path:R,line:String(z)});return n.get(O.gitUrl(`/commit-line?${a}`)).then(n=>{i||(t.size>=200&&t.delete(t.keys().next().value),t.set(e,n??null),S({key:e,value:n??null}))}).catch(()=>{i||S(null)}),()=>{i=!0}},[u,r,L,R,z,B,O]),(0,j.useEffect)(()=>{if(!e||!t)return;if(!u||!I||g<=0){T.current=0,w.current?.clear();return}P(e);let n=e.getModel();if(!n||g>n.getLineCount()){T.current=0,w.current?.clear();return}T.current=g;let r=n.getLineMaxColumn(g),i=c(I),a={range:new t.Range(g,r,g,r),options:{after:{content:` ${i}`,inlineClassName:`inline-blame-annotation`},showIfCollapsed:!0,hoverMessage:x({commit:I,detail:b?.key===B?b.value:null,filePath:M??``,projectPath:k})}};w.current?w.current.set([a]):w.current=e.createDecorationsCollection([a])},[e,t,u,I,g,b,B,M,k]),(0,j.useEffect)(()=>()=>{w.current?.clear(),w.current=null},[]),{stale:m,refresh:N}}export{F as t};
16
+ `;function P(e){let t=e.getDomNode()?.ownerDocument??document;if(t.getElementById(M))return;let n=t.createElement(`style`);n.id=M,n.textContent=N,t.head?.appendChild(n)}function F({editor:e,monaco:t,projectName:r,filePath:a,rev:l,enabled:u,readOnly:d=!1}){let[f,p]=(0,j.useState)(null),[m,h]=(0,j.useState)(!1),[g,_]=(0,j.useState)(0),[v,y]=(0,j.useState)(0),[b,S]=(0,j.useState)(null),C=(0,j.useRef)(new Map),w=(0,j.useRef)(null),T=(0,j.useRef)(0),E=i(e=>e.projects.find(e=>e.name===r)?.path),O=o(r),k=O.repo?.path??E,M=a?O.repoPath(a):null,N=(0,j.useCallback)(()=>y(e=>e+1),[]);(0,j.useEffect)(()=>{!t||!u||(A(t),D(t))},[t,u]),(0,j.useEffect)(()=>{if(!u||!r||!a||M==null){p(null);return}let e=!1,t=new URLSearchParams({path:M});return l&&t.set(`rev`,l),n.get(O.gitUrl(`/blame?${t}`)).then(t=>{e||(p(t),h(!1))}).catch(()=>{e||p(null)}),()=>{e=!0}},[u,r,a,M,l,v,O]),(0,j.useEffect)(()=>{if(!e||!u)return;_(e.getPosition()?.lineNumber??0);let t=e.onDidChangeCursorPosition(e=>_(e.position.lineNumber));if(d)return()=>t.dispose();let n=e.onDidChangeModelContent(()=>h(!0));return()=>{t.dispose(),n.dispose()}},[e,u,d]),(0,j.useEffect)(()=>{if(!e||!u||!window.matchMedia?.(`(hover: none)`).matches)return;let t=e.onMouseDown(t=>{let n=t.target.position,r=e.getModel();!n||!r||n.lineNumber===T.current&&(n.column<r.getLineMaxColumn(n.lineNumber)||e.getAction(`editor.action.showHover`)?.run())});return()=>t.dispose()},[e,u]);let F=(()=>{if(!f||m||g<=0)return null;let e=f.lines[g-1],t=e?.finalLine===g?e:f.lines.find(e=>e.finalLine===g);if(!t)return null;let n=f.commits[t.hash];return n?{commit:n,origLine:t.origLine}:null})(),I=F?.commit??null,L=I&&!s(I.hash)?I.hash:null,R=I?.filename||M||void 0,z=F?.origLine??0,B=`${L} ${z} ${R}`;return(0,j.useEffect)(()=>{if(!u||!r||!L||!R||z<1){S(null);return}let e=B,t=C.current;if(t.has(e)){S({key:e,value:t.get(e)??null});return}let i=!1,a=new URLSearchParams({hash:L,path:R,line:String(z)});return n.get(O.gitUrl(`/commit-line?${a}`)).then(n=>{i||(t.size>=200&&t.delete(t.keys().next().value),t.set(e,n??null),S({key:e,value:n??null}))}).catch(()=>{i||S(null)}),()=>{i=!0}},[u,r,L,R,z,B,O]),(0,j.useEffect)(()=>{if(!e||!t)return;if(!u||!I||g<=0){T.current=0,w.current?.clear();return}P(e);let n=e.getModel();if(!n||g>n.getLineCount()){T.current=0,w.current?.clear();return}T.current=g;let r=n.getLineMaxColumn(g),i=c(I),a={range:new t.Range(g,r,g,r),options:{after:{content:` ${i}`,inlineClassName:`inline-blame-annotation`},showIfCollapsed:!0,hoverMessage:x({commit:I,detail:b?.key===B?b.value:null,filePath:M??``,projectPath:k})}};w.current?w.current.set([a]):w.current=e.createDecorationsCollection([a])},[e,t,u,I,g,b,B,M,k]),(0,j.useEffect)(()=>()=>{w.current?.clear(),w.current=null},[]),{stale:m,refresh:N}}export{F as t};
@@ -1,4 +1,4 @@
1
- import{o as e}from"./rolldown-runtime-FhOqtrmT.js";import{C as t}from"./vendor-markdown-CuWCHIVb.js";import"./vendor-ui-DmZ-Mb-H.js";import{i as n,n as r}from"./api-client-C1ZwRL4Y.js";import"./ws-auth-CEYVQ8NH.js";import{S as i,a}from"./index-DU68xk06.js";var o=e(t(),1),s=15e3;function c(e){clearTimeout(e.timer),e.detach?.()}var l=class{ws;docs=new Map;pending=new Map;notificationListeners=new Set;statusListeners=new Set;nextId=1;constructor(e){this.projectName=e,this.ws=new a(`/ws/project/${encodeURIComponent(e)}/lsp`),this.ws.onMessage(e=>this.receive(e)),this.ws.connect()}open(e,t){this.docs.set(e,{source:t,status:{state:`opening`}}),this.setStatus(e,{state:`opening`}),this.sendOpen(e)}sendOpen(e){let t=this.docs.get(e);t&&this.send({t:`open`,path:e,version:t.source.getVersion(),text:t.source.getText(),clientUri:t.source.clientUri})}close(e){this.docs.delete(e)&&this.send({t:`close`,path:e})}change(e,t,n){this.docs.has(e)&&this.send({t:`change`,path:e,version:t,changes:n})}save(e,t){this.docs.has(e)&&this.send({t:`save`,path:e,text:t})}statusOf(e){return this.docs.get(e)?.status}request(e,t,n,r={}){let i=this.docs.get(e);if(!i||i.status.state!==`ready`)return Promise.reject(Error(`No language server is ready for ${e}`));let{timeoutMs:a=s,signal:o}=r;if(o?.aborted)return Promise.reject(Error(`${t} was cancelled`));let c=this.nextId++;return new Promise((r,i)=>{let s=setTimeout(()=>{this.pending.delete(c),this.send({t:`cancel`,id:c}),i(Error(`${t} timed out`))},a),l=()=>{this.pending.delete(c)&&(clearTimeout(s),this.send({t:`cancel`,id:c}),i(Error(`${t} was cancelled`)))};o?.addEventListener(`abort`,l,{once:!0}),this.pending.set(c,{resolve:r,reject:i,timer:s,detach:o?()=>o.removeEventListener(`abort`,l):void 0}),this.send({t:`request`,id:c,path:e,method:t,params:n})})}onNotification(e){return this.notificationListeners.add(e),()=>this.notificationListeners.delete(e)}onStatus(e){return this.statusListeners.add(e),()=>this.statusListeners.delete(e)}send(e){this.ws.send(JSON.stringify(e))}receive(e){let t;try{t=JSON.parse(typeof e.data==`string`?e.data:``)}catch{return}switch(t.t){case`hello`:for(let e of this.docs.keys())this.sendOpen(e);break;case`ready`:this.setStatus(String(t.path),{state:`ready`,languageId:String(t.languageId),server:t.server,projectPath:String(t.projectPath??``),capabilities:t.capabilities??{}});break;case`unavailable`:this.setStatus(String(t.path),{state:`unavailable`,reason:String(t.reason),server:t.server??null,message:String(t.message)});break;case`resync`:{let e=String(t.path),n=this.docs.get(e);n&&this.send({t:`change`,path:e,version:n.source.getVersion(),text:n.source.getText()});break}case`response`:{let e=this.pending.get(Number(t.id));if(!e)return;c(e),this.pending.delete(Number(t.id)),e.resolve(t.result);break}case`error`:{let e=this.pending.get(Number(t.id));if(!e)return;c(e),this.pending.delete(Number(t.id)),e.reject(Error(String(t.message)));break}case`notification`:for(let e of this.notificationListeners)e(String(t.method),t.params);break}}setStatus(e,t){let n=this.docs.get(e);n&&(n.status=t);for(let n of this.statusListeners)n(e,t)}dispose(){for(let e of this.pending.values())c(e),e.reject(Error(`The language server connection was closed`));this.pending.clear(),this.docs.clear(),this.notificationListeners.clear(),this.statusListeners.clear(),this.ws.disconnect()}},u=new Map;function d(e){let t=u.get(e);if(t)return t.holders++,t.connection;let n=new l(e);return u.set(e,{connection:n,holders:1}),n}function f(e){let t=u.get(e);return!t||(t.holders--,t.holders>0)?!1:(u.delete(e),t.connection.dispose(),!0)}var p=new Map;function ee(e,t){p.set(e.uri.toString(),t)}function m(e){p.delete(e.uri.toString())}function h(e){return p.get(e.uri.toString())}function g(e){if(!e.startsWith(`file:`))return null;let t=e.slice(5),n=``;if(t.startsWith(`//`)){t=t.slice(2);let e=t.indexOf(`/`);n=e<0?t:t.slice(0,e),t=e<0?``:t.slice(e)}let r=t.split(`/`).map(_).join(`/`);return/^\/[A-Za-z]:/.test(r)?r.slice(1):n?`//${_(n)}${r}`:r}function _(e){try{return decodeURIComponent(e)}catch{return e}}var te=40,v=500,y=3,ne=6,b=new Map,x=new Map;function re(e){return(x.get(e)??0)>=y}function S(e){w(e,(x.get(e)??0)+1)}function C(e){w(e,y)}function w(e,t){for(x.delete(e),x.set(e,t);x.size>v;){let e=x.keys().next().value;if(e===void 0)return;x.delete(e)}}function T(e){x.delete(e)}async function ie(e,t,n){let r=0,i=Array.from({length:Math.min(t,e.length)},async()=>{for(;;){let t=r++;if(t>=e.length)return;await n(e[t])}});await Promise.all(i)}function ae(e,t){let n=e.replace(/\\/g,`/`).replace(/\/+$/,``),r=t.replace(/\\/g,`/`),i=n+`/`,a=/^[A-Za-z]:\//.test(i),o=r.slice(0,i.length);return(a?o.toLowerCase()!==i.toLowerCase():o!==i)?null:r.slice(i.length)}async function oe(e,t,i,a){if(!i)return;let o=new Set,s=[...new Set(a)].filter(t=>{if(re(t))return!1;let n=b.get(t);return n&&(b.delete(t),!n.isDisposed())?(b.set(t,n),o.add(t),!1):t.startsWith(`file:`)&&!e.editor.getModel(e.Uri.parse(t))});s.length!==0&&(await ie(s,ne,async a=>{try{let s=g(a),c=s?ae(i,s):null;if(!c){C(a);return}let l=(await r.get(`${n(t)}/files/read?path=${encodeURIComponent(c)}`))?.content;if(typeof l!=`string`){S(a);return}T(a);let u=e.Uri.parse(a);if(e.editor.getModel(u)){o.add(a);return}b.set(a,e.editor.createModel(l,void 0,u)),o.add(a)}catch{S(a)}}),se(o))}function se(e){for(let t of[...b.keys()]){if(b.size<=te)return;if(e.has(t))continue;let n=b.get(t);b.delete(t);try{n?.dispose()}catch{}}}function ce(){for(let e of b.values())try{e.dispose()}catch{}b.clear(),x.clear()}function E(e){if(!e)return;let t=new AbortController;return e.isCancellationRequested?t.abort():e.onCancellationRequested(()=>t.abort()),t.signal}function D(e){return{line:e.lineNumber-1,character:e.column-1}}function le(e){return{lineNumber:e.line+1,column:e.character+1}}function O(e){return{start:{line:e.startLineNumber-1,character:e.startColumn-1},end:{line:e.endLineNumber-1,character:e.endColumn-1}}}function k(e){return{startLineNumber:e.start.line+1,startColumn:e.start.character+1,endLineNumber:e.end.line+1,endColumn:e.end.character+1}}var ue={1:`Text`,2:`Method`,3:`Function`,4:`Constructor`,5:`Field`,6:`Variable`,7:`Class`,8:`Interface`,9:`Module`,10:`Property`,11:`Unit`,12:`Value`,13:`Enum`,14:`Keyword`,15:`Snippet`,16:`Color`,17:`File`,18:`Reference`,19:`Folder`,20:`EnumMember`,21:`Constant`,22:`Struct`,23:`Event`,24:`Operator`,25:`TypeParameter`},A={1:`File`,2:`Module`,3:`Namespace`,4:`Package`,5:`Class`,6:`Method`,7:`Property`,8:`Field`,9:`Constructor`,10:`Enum`,11:`Interface`,12:`Function`,13:`Variable`,14:`Constant`,15:`String`,16:`Number`,17:`Boolean`,18:`Array`,19:`Object`,20:`Key`,21:`Null`,22:`EnumMember`,23:`Struct`,24:`Event`,25:`Operator`,26:`TypeParameter`},j={1:`Error`,2:`Warning`,3:`Info`,4:`Hint`},M={1:`Text`,2:`Read`,3:`Write`};function N(e,t){let n=ue[t??0];return e.languages.CompletionItemKind[n??`Text`]}function P(e,t){let n=A[t??0];return e.languages.SymbolKind[n??`Variable`]}function F(e,t){let n=j[t??0];return e.MarkerSeverity[n??`Warning`]}function I(e,t){let n=M[t??0];return e.languages.DocumentHighlightKind[n??`Text`]}function L(e){if(e!=null){if(Array.isArray(e)){let t=e.map(L).filter(e=>!!e?.value);return t.length===0?void 0:{value:t.map(e=>e.value).join(`
1
+ import{o as e}from"./rolldown-runtime-FhOqtrmT.js";import{C as t}from"./vendor-markdown-CuWCHIVb.js";import"./vendor-ui-DmZ-Mb-H.js";import{i as n,n as r}from"./api-client-C1ZwRL4Y.js";import"./ws-auth-CEYVQ8NH.js";import{S as i,a}from"./index-CEZVxM4G.js";var o=e(t(),1),s=15e3;function c(e){clearTimeout(e.timer),e.detach?.()}var l=class{ws;docs=new Map;pending=new Map;notificationListeners=new Set;statusListeners=new Set;nextId=1;constructor(e){this.projectName=e,this.ws=new a(`/ws/project/${encodeURIComponent(e)}/lsp`),this.ws.onMessage(e=>this.receive(e)),this.ws.connect()}open(e,t){this.docs.set(e,{source:t,status:{state:`opening`}}),this.setStatus(e,{state:`opening`}),this.sendOpen(e)}sendOpen(e){let t=this.docs.get(e);t&&this.send({t:`open`,path:e,version:t.source.getVersion(),text:t.source.getText(),clientUri:t.source.clientUri})}close(e){this.docs.delete(e)&&this.send({t:`close`,path:e})}change(e,t,n){this.docs.has(e)&&this.send({t:`change`,path:e,version:t,changes:n})}save(e,t){this.docs.has(e)&&this.send({t:`save`,path:e,text:t})}statusOf(e){return this.docs.get(e)?.status}request(e,t,n,r={}){let i=this.docs.get(e);if(!i||i.status.state!==`ready`)return Promise.reject(Error(`No language server is ready for ${e}`));let{timeoutMs:a=s,signal:o}=r;if(o?.aborted)return Promise.reject(Error(`${t} was cancelled`));let c=this.nextId++;return new Promise((r,i)=>{let s=setTimeout(()=>{this.pending.delete(c),this.send({t:`cancel`,id:c}),i(Error(`${t} timed out`))},a),l=()=>{this.pending.delete(c)&&(clearTimeout(s),this.send({t:`cancel`,id:c}),i(Error(`${t} was cancelled`)))};o?.addEventListener(`abort`,l,{once:!0}),this.pending.set(c,{resolve:r,reject:i,timer:s,detach:o?()=>o.removeEventListener(`abort`,l):void 0}),this.send({t:`request`,id:c,path:e,method:t,params:n})})}onNotification(e){return this.notificationListeners.add(e),()=>this.notificationListeners.delete(e)}onStatus(e){return this.statusListeners.add(e),()=>this.statusListeners.delete(e)}send(e){this.ws.send(JSON.stringify(e))}receive(e){let t;try{t=JSON.parse(typeof e.data==`string`?e.data:``)}catch{return}switch(t.t){case`hello`:for(let e of this.docs.keys())this.sendOpen(e);break;case`ready`:this.setStatus(String(t.path),{state:`ready`,languageId:String(t.languageId),server:t.server,projectPath:String(t.projectPath??``),capabilities:t.capabilities??{}});break;case`unavailable`:this.setStatus(String(t.path),{state:`unavailable`,reason:String(t.reason),server:t.server??null,message:String(t.message)});break;case`resync`:{let e=String(t.path),n=this.docs.get(e);n&&this.send({t:`change`,path:e,version:n.source.getVersion(),text:n.source.getText()});break}case`response`:{let e=this.pending.get(Number(t.id));if(!e)return;c(e),this.pending.delete(Number(t.id)),e.resolve(t.result);break}case`error`:{let e=this.pending.get(Number(t.id));if(!e)return;c(e),this.pending.delete(Number(t.id)),e.reject(Error(String(t.message)));break}case`notification`:for(let e of this.notificationListeners)e(String(t.method),t.params);break}}setStatus(e,t){let n=this.docs.get(e);n&&(n.status=t);for(let n of this.statusListeners)n(e,t)}dispose(){for(let e of this.pending.values())c(e),e.reject(Error(`The language server connection was closed`));this.pending.clear(),this.docs.clear(),this.notificationListeners.clear(),this.statusListeners.clear(),this.ws.disconnect()}},u=new Map;function d(e){let t=u.get(e);if(t)return t.holders++,t.connection;let n=new l(e);return u.set(e,{connection:n,holders:1}),n}function f(e){let t=u.get(e);return!t||(t.holders--,t.holders>0)?!1:(u.delete(e),t.connection.dispose(),!0)}var p=new Map;function ee(e,t){p.set(e.uri.toString(),t)}function m(e){p.delete(e.uri.toString())}function h(e){return p.get(e.uri.toString())}function g(e){if(!e.startsWith(`file:`))return null;let t=e.slice(5),n=``;if(t.startsWith(`//`)){t=t.slice(2);let e=t.indexOf(`/`);n=e<0?t:t.slice(0,e),t=e<0?``:t.slice(e)}let r=t.split(`/`).map(_).join(`/`);return/^\/[A-Za-z]:/.test(r)?r.slice(1):n?`//${_(n)}${r}`:r}function _(e){try{return decodeURIComponent(e)}catch{return e}}var te=40,v=500,y=3,ne=6,b=new Map,x=new Map;function re(e){return(x.get(e)??0)>=y}function S(e){w(e,(x.get(e)??0)+1)}function C(e){w(e,y)}function w(e,t){for(x.delete(e),x.set(e,t);x.size>v;){let e=x.keys().next().value;if(e===void 0)return;x.delete(e)}}function T(e){x.delete(e)}async function ie(e,t,n){let r=0,i=Array.from({length:Math.min(t,e.length)},async()=>{for(;;){let t=r++;if(t>=e.length)return;await n(e[t])}});await Promise.all(i)}function ae(e,t){let n=e.replace(/\\/g,`/`).replace(/\/+$/,``),r=t.replace(/\\/g,`/`),i=n+`/`,a=/^[A-Za-z]:\//.test(i),o=r.slice(0,i.length);return(a?o.toLowerCase()!==i.toLowerCase():o!==i)?null:r.slice(i.length)}async function oe(e,t,i,a){if(!i)return;let o=new Set,s=[...new Set(a)].filter(t=>{if(re(t))return!1;let n=b.get(t);return n&&(b.delete(t),!n.isDisposed())?(b.set(t,n),o.add(t),!1):t.startsWith(`file:`)&&!e.editor.getModel(e.Uri.parse(t))});s.length!==0&&(await ie(s,ne,async a=>{try{let s=g(a),c=s?ae(i,s):null;if(!c){C(a);return}let l=(await r.get(`${n(t)}/files/read?path=${encodeURIComponent(c)}`))?.content;if(typeof l!=`string`){S(a);return}T(a);let u=e.Uri.parse(a);if(e.editor.getModel(u)){o.add(a);return}b.set(a,e.editor.createModel(l,void 0,u)),o.add(a)}catch{S(a)}}),se(o))}function se(e){for(let t of[...b.keys()]){if(b.size<=te)return;if(e.has(t))continue;let n=b.get(t);b.delete(t);try{n?.dispose()}catch{}}}function ce(){for(let e of b.values())try{e.dispose()}catch{}b.clear(),x.clear()}function E(e){if(!e)return;let t=new AbortController;return e.isCancellationRequested?t.abort():e.onCancellationRequested(()=>t.abort()),t.signal}function D(e){return{line:e.lineNumber-1,character:e.column-1}}function le(e){return{lineNumber:e.line+1,column:e.character+1}}function O(e){return{start:{line:e.startLineNumber-1,character:e.startColumn-1},end:{line:e.endLineNumber-1,character:e.endColumn-1}}}function k(e){return{startLineNumber:e.start.line+1,startColumn:e.start.character+1,endLineNumber:e.end.line+1,endColumn:e.end.character+1}}var ue={1:`Text`,2:`Method`,3:`Function`,4:`Constructor`,5:`Field`,6:`Variable`,7:`Class`,8:`Interface`,9:`Module`,10:`Property`,11:`Unit`,12:`Value`,13:`Enum`,14:`Keyword`,15:`Snippet`,16:`Color`,17:`File`,18:`Reference`,19:`Folder`,20:`EnumMember`,21:`Constant`,22:`Struct`,23:`Event`,24:`Operator`,25:`TypeParameter`},A={1:`File`,2:`Module`,3:`Namespace`,4:`Package`,5:`Class`,6:`Method`,7:`Property`,8:`Field`,9:`Constructor`,10:`Enum`,11:`Interface`,12:`Function`,13:`Variable`,14:`Constant`,15:`String`,16:`Number`,17:`Boolean`,18:`Array`,19:`Object`,20:`Key`,21:`Null`,22:`EnumMember`,23:`Struct`,24:`Event`,25:`Operator`,26:`TypeParameter`},j={1:`Error`,2:`Warning`,3:`Info`,4:`Hint`},M={1:`Text`,2:`Read`,3:`Write`};function N(e,t){let n=ue[t??0];return e.languages.CompletionItemKind[n??`Text`]}function P(e,t){let n=A[t??0];return e.languages.SymbolKind[n??`Variable`]}function F(e,t){let n=j[t??0];return e.MarkerSeverity[n??`Warning`]}function I(e,t){let n=M[t??0];return e.languages.DocumentHighlightKind[n??`Text`]}function L(e){if(e!=null){if(Array.isArray(e)){let t=e.map(L).filter(e=>!!e?.value);return t.length===0?void 0:{value:t.map(e=>e.value).join(`
2
2
 
3
3
  ---
4
4
 
@@ -1 +1 @@
1
- import{o as e}from"./rolldown-runtime-FhOqtrmT.js";import{C as t}from"./vendor-markdown-CuWCHIVb.js";import{t as n}from"./settings-store-krC6bc79.js";import{r,t as i}from"./apply-theme-CbR31K6I.js";import{t as a}from"./resolve-theme-B_ukrg_8.js";import{s as o}from"./index-DU68xk06.js";var s=e(t(),1);function c(){let e=n(e=>e.themeStyle),t=n(e=>e.themeMode),c=n(e=>e.customThemeId),l=n(e=>e.customThemes),u=()=>o(r()??a(e,t,l,c)),[d,f]=(0,s.useState)(u);return(0,s.useEffect)(()=>{f(u());let e=()=>f(u());return window.addEventListener(i,e),()=>window.removeEventListener(i,e)},[e,t,c,l]),d}export{c as t};
1
+ import{o as e}from"./rolldown-runtime-FhOqtrmT.js";import{C as t}from"./vendor-markdown-CuWCHIVb.js";import{t as n}from"./settings-store-krC6bc79.js";import{r,t as i}from"./apply-theme-CbR31K6I.js";import{t as a}from"./resolve-theme-B_ukrg_8.js";import{s as o}from"./index-CEZVxM4G.js";var s=e(t(),1);function c(){let e=n(e=>e.themeStyle),t=n(e=>e.themeMode),c=n(e=>e.customThemeId),l=n(e=>e.customThemes),u=()=>o(r()??a(e,t,l,c)),[d,f]=(0,s.useState)(u);return(0,s.useEffect)(()=>{f(u());let e=()=>f(u());return window.addEventListener(i,e),()=>window.removeEventListener(i,e)},[e,t,c,l]),d}export{c as t};
@@ -1 +1 @@
1
- import{o as e}from"./rolldown-runtime-FhOqtrmT.js";import{C as t}from"./vendor-markdown-CuWCHIVb.js";import{a as n}from"./index-DU68xk06.js";var r=e(t(),1);function i({url:e,onMessage:t,autoConnect:i=!0,idleTimeoutMs:a,onConnectionChange:o}){let s=(0,r.useRef)(null),c=(0,r.useRef)(t),l=(0,r.useRef)(o);return c.current=t,l.current=o,(0,r.useEffect)(()=>{let t=!0,r=new n(e,{idleTimeoutMs:a,onConnectionChange:e=>{t&&l.current?.(e)}});return s.current=r,r.onMessage(e=>c.current?.(e)),i&&r.connect(),()=>{t=!1,r.disconnect(),s.current=null}},[e,i,a]),{send:(0,r.useCallback)(e=>{s.current?.send(e)},[]),connect:(0,r.useCallback)(()=>{s.current?.connect()},[]),disconnect:(0,r.useCallback)(()=>{s.current?.disconnect()},[])}}export{i as t};
1
+ import{o as e}from"./rolldown-runtime-FhOqtrmT.js";import{C as t}from"./vendor-markdown-CuWCHIVb.js";import{a as n}from"./index-CEZVxM4G.js";var r=e(t(),1);function i({url:e,onMessage:t,autoConnect:i=!0,idleTimeoutMs:a,onConnectionChange:o}){let s=(0,r.useRef)(null),c=(0,r.useRef)(t),l=(0,r.useRef)(o);return c.current=t,l.current=o,(0,r.useEffect)(()=>{let t=!0,r=new n(e,{idleTimeoutMs:a,onConnectionChange:e=>{t&&l.current?.(e)}});return s.current=r,r.onMessage(e=>c.current?.(e)),i&&r.connect(),()=>{t=!1,r.disconnect(),s.current=null}},[e,i,a]),{send:(0,r.useCallback)(e=>{s.current?.send(e)},[]),connect:(0,r.useCallback)(()=>{s.current?.connect()},[]),disconnect:(0,r.useCallback)(()=>{s.current?.disconnect()},[])}}export{i as t};
@@ -1 +1 @@
1
- import{o as e}from"./rolldown-runtime-FhOqtrmT.js";import{C as t,S as n}from"./vendor-markdown-CuWCHIVb.js";import"./vendor-ui-DmZ-Mb-H.js";import{$n as r,Ct as i,Dr as a,Fr as o,Gn as s,Ir as c,Pr as l,Tt as u,er as d,ln as f,mn as p,or as m,st as h,xn as g,yt as _,zn as v}from"./icons-DQjqk0lJ.js";import"./api-client-C1ZwRL4Y.js";import"./portal-container-context-BarKmT4S.js";import{t as y}from"./button-B9CTrsEf.js";import{Gt as b,Ht as x,Kt as S,Ut as C,Vt as w,Wt as T,Xt as E,zt as D}from"./index-DU68xk06.js";import{o as O}from"./can-open-in-ppm-cv5--yHX.js";import{a as k,i as A,n as j,r as M,t as ee}from"./media-url-yfqHpPz0.js";var N=e(t(),1),P={rotation:0,flipH:!1,flipV:!1};function F(e){return{...e,rotation:(e.rotation+90)%360}}function te(e){return{...e,rotation:(e.rotation+270)%360}}function I(e){return e.rotation===0&&!e.flipH&&!e.flipV}function ne(e){let t=[];return e.rotation&&t.push(`rotate(${e.rotation}deg)`),e.flipH&&t.push(`scaleX(-1)`),e.flipV&&t.push(`scaleY(-1)`),t.length?t.join(` `):`none`}function re(e,t){return e.rotation===90||e.rotation===270?{maxWidth:t.height,maxHeight:t.width}:{maxWidth:t.width,maxHeight:t.height}}var L=[[`Space / K`,`Play / pause`],[`← / →`,`Seek 5s`],[`J / L or Shift+← / →`,`Seek 10s`],[`↑ / ↓`,`Volume`],[`M`,`Mute`],[`F`,`Fullscreen`],[`< / >`,`Speed`],[`R / Shift+R`,`Rotate`]];function R(e){return(0,N.useCallback)(t=>{let n=t.target;if(n.tagName===`INPUT`||n.tagName===`TEXTAREA`||n.isContentEditable||t.ctrlKey||t.metaKey||t.altKey)return;let r=!0;switch(t.key){case` `:case`k`:case`K`:e.togglePlay();break;case`ArrowLeft`:e.seekBy(t.shiftKey?-10:-5);break;case`ArrowRight`:e.seekBy(t.shiftKey?10:5);break;case`j`:case`J`:e.seekBy(-10);break;case`l`:case`L`:e.seekBy(10);break;case`ArrowUp`:e.volumeBy(.1);break;case`ArrowDown`:e.volumeBy(-.1);break;case`m`:case`M`:e.toggleMute();break;case`f`:case`F`:e.toggleFullscreen();break;case`<`:case`,`:e.speedStep(-1);break;case`>`:case`.`:e.speedStep(1);break;case`r`:e.rotate(1);break;case`R`:e.rotate(-1);break;default:r=!1}r&&t.preventDefault()},[e])}var z=n(),B=[.25,.5,.75,1,1.25,1.5,2,3];function V({speed:e,onSpeed:t,transform:n,onRotate:o,onFlipH:s,onFlipV:c,onResetTransform:l}){return(0,z.jsxs)(D,{children:[(0,z.jsx)(E,{asChild:!0,children:(0,z.jsxs)(y,{variant:`ghost`,size:`icon`,className:`size-11 shrink-0 relative`,"aria-label":`Playback settings`,children:[(0,z.jsx)(m,{className:`size-5`}),e!==1&&(0,z.jsxs)(`span`,{className:`absolute -top-0.5 -right-0.5 text-[10px] leading-none px-1 rounded bg-primary text-primary-foreground tabular-nums`,children:[e,`x`]})]})}),(0,z.jsxs)(w,{align:`end`,className:`w-60 max-h-[70vh] overflow-y-auto`,children:[(0,z.jsx)(C,{children:`Speed`}),(0,z.jsx)(T,{value:String(e),onValueChange:e=>t(Number(e)),children:(0,z.jsx)(`div`,{className:`grid grid-cols-4 gap-1 px-1 pb-1`,children:B.map(e=>(0,z.jsxs)(b,{value:String(e),className:`justify-center pl-2 min-h-11 text-xs tabular-nums data-[state=checked]:bg-accent [&>span:first-child]:hidden`,children:[e,`x`]},e))})}),(0,z.jsx)(S,{}),(0,z.jsx)(C,{children:`Orientation`}),(0,z.jsxs)(x,{className:`min-h-11`,onSelect:e=>{e.preventDefault(),o(1)},children:[(0,z.jsx)(d,{className:`size-4`}),` Rotate right `,(0,z.jsx)(`span`,{className:`ml-auto text-xs text-text-subtle`,children:`R`})]}),(0,z.jsxs)(x,{className:`min-h-11`,onSelect:e=>{e.preventDefault(),o(-1)},children:[(0,z.jsx)(r,{className:`size-4`}),` Rotate left `,(0,z.jsx)(`span`,{className:`ml-auto text-xs text-text-subtle`,children:`⇧R`})]}),(0,z.jsxs)(x,{className:`min-h-11`,onSelect:e=>{e.preventDefault(),s()},children:[(0,z.jsx)(i,{className:`size-4`}),` Flip horizontal `,n.flipH&&(0,z.jsx)(`span`,{className:`ml-auto text-xs`,children:`✓`})]}),(0,z.jsxs)(x,{className:`min-h-11`,onSelect:e=>{e.preventDefault(),c()},children:[(0,z.jsx)(u,{className:`size-4`}),` Flip vertical `,n.flipV&&(0,z.jsx)(`span`,{className:`ml-auto text-xs`,children:`✓`})]}),!I(n)&&(0,z.jsxs)(x,{className:`min-h-11`,onSelect:l,children:[(0,z.jsx)(a,{className:`size-4`}),` Reset orientation`]}),(0,z.jsx)(S,{}),(0,z.jsx)(C,{children:`Keyboard`}),(0,z.jsx)(`div`,{className:`px-2 pb-2 grid grid-cols-[auto_1fr] gap-x-3 gap-y-1 text-xs text-text-secondary`,children:L.map(([e,t])=>(0,z.jsxs)(`div`,{className:`contents`,children:[(0,z.jsx)(`kbd`,{className:`font-mono text-text-subtle whitespace-nowrap`,children:e}),(0,z.jsx)(`span`,{children:t})]},e))})]})]})}function ie(e){let t=e.muted||e.volume===0?c:e.volume<.5?l:o,n=t=>e.onSeek(Number(t.target.value));return(0,z.jsxs)(`div`,{className:`flex items-center gap-1 px-2 py-1 bg-surface border-t border-border`,children:[(0,z.jsx)(y,{variant:`ghost`,size:`icon`,className:`size-11 shrink-0`,onClick:e.onTogglePlay,"aria-label":e.playing?`Pause`:`Play`,children:e.playing?(0,z.jsx)(v,{className:`size-5`}):(0,z.jsx)(s,{className:`size-5`})}),(0,z.jsxs)(`span`,{className:`text-xs tabular-nums text-text-secondary shrink-0 min-w-[4.5rem] text-center`,children:[H(e.position),e.duration?` / ${H(e.duration)}`:``]}),e.duration?(0,z.jsx)(`input`,{type:`range`,min:0,max:e.duration,step:.1,value:Math.min(e.position,e.duration),"aria-label":`Seek`,className:`flex-1 h-11 accent-primary cursor-pointer min-w-0`,onChange:t=>e.onScrub(Number(t.target.value)),onPointerUp:n,onKeyUp:n,onTouchEnd:n}):(0,z.jsx)(`div`,{className:`flex-1`}),(0,z.jsxs)(`div`,{className:`flex items-center shrink-0`,children:[(0,z.jsx)(y,{variant:`ghost`,size:`icon`,className:`size-11`,onClick:e.onToggleMute,"aria-label":e.muted?`Unmute`:`Mute`,children:(0,z.jsx)(t,{className:`size-5`})}),(0,z.jsx)(`input`,{type:`range`,min:0,max:1,step:.05,value:e.muted?0:e.volume,"aria-label":`Volume`,className:`hidden sm:block w-20 h-11 accent-primary cursor-pointer`,onChange:t=>e.onVolume(Number(t.target.value))})]}),(0,z.jsx)(V,{speed:e.speed,onSpeed:e.onSpeed,transform:e.transform,onRotate:e.onRotate,onFlipH:e.onFlipH,onFlipV:e.onFlipV,onResetTransform:e.onResetTransform}),(0,z.jsx)(y,{variant:`ghost`,size:`icon`,className:`size-11 shrink-0`,onClick:e.onToggleFullscreen,"aria-label":e.fullscreen?`Exit fullscreen`:`Fullscreen`,children:e.fullscreen?(0,z.jsx)(g,{className:`size-5`}):(0,z.jsx)(p,{className:`size-5`})})]})}function H(e){let t=Math.max(0,Math.floor(Number.isFinite(e)?e:0)),n=Math.floor(t/3600),r=Math.floor(t%3600/60),i=t%60,a=n?String(r).padStart(2,`0`):String(r);return`${n?`${n}:`:``}${a}:${String(i).padStart(2,`0`)}`}function U({filePath:e,projectName:t,mode:n,probeDuration:r=null,onNativeError:i}){let a=(0,N.useRef)(null),o=(0,N.useRef)(null),s=(0,N.useRef)(null),c=(0,N.useRef)(!0),[l]=(0,N.useState)(ee),[u,d]=(0,N.useState)(0),[p,m]=(0,N.useState)(0),[h,g]=(0,N.useState)(null),[_,v]=(0,N.useState)(!1),[b,x]=(0,N.useState)(!0),[S,C]=(0,N.useState)(null),[w,T]=(0,N.useState)(1),[E,D]=(0,N.useState)(!1),[O,j]=(0,N.useState)(1),[I,L]=(0,N.useState)(P),[V,H]=(0,N.useState)(!1),[U,W]=(0,N.useState)({width:0,height:0}),[G,K]=(0,N.useState)(null),q=n===`transcode`,J=q?k(e,t,u,l):M(e,t),Y=q?r:h,X=S??(q?u+p:p);(0,N.useEffect)(()=>{m(0),x(!0),K(null)},[J]),(0,N.useEffect)(()=>{d(0),g(null),L(P)},[e,n]),(0,N.useEffect)(()=>{let e=s.current;e&&(e.volume=w,e.muted=E)},[w,E]),(0,N.useEffect)(()=>{let e=s.current;e&&(e.playbackRate=O)},[O,J]),(0,N.useEffect)(()=>{let n=s.current,r=()=>{q&&A(e,t,l)};return window.addEventListener(`pagehide`,r),()=>{window.removeEventListener(`pagehide`,r),n&&!n.isConnected&&(n.pause(),n.removeAttribute(`src`),n.load(),r())}},[e,t,q,l]),(0,N.useEffect)(()=>{let e=()=>H(document.fullscreenElement===a.current);return document.addEventListener(`fullscreenchange`,e),()=>document.removeEventListener(`fullscreenchange`,e)},[]),(0,N.useEffect)(()=>{let e=o.current;if(!e)return;let t=new ResizeObserver(()=>W({width:e.clientWidth,height:e.clientHeight}));return t.observe(e),()=>t.disconnect()},[]);let Z=(0,N.useCallback)(e=>{let t=s.current,n=Math.max(0,Y?Math.min(e,Y-.5):e);if(C(null),!q){t&&(t.currentTime=n);return}Math.abs(n-(u+(t?.currentTime??0)))<.5||d(n)},[Y,q,u]),Q=(0,N.useMemo)(()=>({togglePlay:()=>{let e=s.current;e&&(c.current=e.paused,e.paused?e.play().catch(()=>{}):e.pause())},seekBy:e=>Z((q?u:0)+(s.current?.currentTime??0)+e),toggleFullscreen:()=>{document.fullscreenElement?document.exitFullscreen():a.current?.requestFullscreen?.()},toggleMute:()=>D(e=>!e),volumeBy:e=>{D(!1),T(t=>Math.min(1,Math.max(0,Math.round((t+e)*100)/100)))},speedStep:e=>j(t=>{let n=B.indexOf(t);return B[Math.min(B.length-1,Math.max(0,(n===-1?3:n)+e))]??1}),rotate:e=>L(t=>e===1?F(t):te(t))}),[Z,q,u]),ae=R(Q),$=re(I,U),oe=()=>{K(null),d(e=>e+.001)};return(0,z.jsxs)(`div`,{ref:a,"data-testid":`video-player`,tabIndex:0,onKeyDown:ae,className:`flex flex-col h-full bg-black outline-none focus-visible:ring-1 focus-visible:ring-primary/60`,children:[(0,z.jsxs)(`div`,{ref:o,className:`relative flex-1 min-h-0 flex items-center justify-center overflow-hidden`,onClick:e=>{a.current?.focus(),e.detail===1&&Q.togglePlay()},onDoubleClick:Q.toggleFullscreen,children:[(0,z.jsx)(`video`,{ref:s,src:J,autoPlay:!0,playsInline:!0,preload:q?`auto`:`metadata`,style:{transform:ne(I),maxWidth:$.maxWidth||void 0,maxHeight:$.maxHeight||void 0},onLoadedMetadata:e=>{let t=e.currentTarget;t.playbackRate=O,t.volume=w,t.muted=E,!q&&Number.isFinite(t.duration)&&g(t.duration),q&&!c.current&&t.pause()},onPlay:()=>v(!0),onPause:()=>v(!1),onWaiting:()=>x(!0),onPlaying:()=>x(!1),onCanPlay:()=>x(!1),onTimeUpdate:e=>m(e.currentTarget.currentTime),onEnded:()=>{v(!1),c.current=!1},onError:()=>{q?K(`Transcoding failed. ffmpeg may have stopped or the file is corrupt.`):i?.()}}),b&&!G&&(0,z.jsx)(f,{className:`absolute size-8 animate-spin text-white/80 pointer-events-none`}),G&&(0,z.jsxs)(`div`,{className:`absolute inset-0 flex flex-col items-center justify-center gap-3 bg-black/85 text-text-secondary p-4 text-center`,onClick:e=>e.stopPropagation(),onDoubleClick:e=>e.stopPropagation(),children:[(0,z.jsx)(`p`,{className:`text-sm`,children:G}),(0,z.jsx)(y,{variant:`outline`,size:`sm`,className:`h-11 px-4`,onClick:oe,children:`Retry`})]})]}),(0,z.jsx)(ie,{playing:_,position:X,duration:Y,volume:w,muted:E,speed:O,transform:I,fullscreen:V,onTogglePlay:Q.togglePlay,onScrub:C,onSeek:Z,onVolume:e=>{T(e),D(e===0)},onToggleMute:Q.toggleMute,onSpeed:j,onRotate:Q.rotate,onFlipH:()=>L(e=>({...e,flipH:!e.flipH})),onFlipV:()=>L(e=>({...e,flipV:!e.flipV})),onResetTransform:()=>L(P),onToggleFullscreen:Q.toggleFullscreen})]})}var W=new Set([`mp4`,`m4v`,`webm`,`ogg`,`ogv`,`mov`]);function G({filePath:e,projectName:t}){let n=O(e),[r,i]=(0,N.useState)(()=>W.has(n)?{kind:`native`}:{kind:`probing`});return(0,N.useEffect)(()=>{i(W.has(O(e))?{kind:`native`}:{kind:`probing`})},[e]),(0,N.useEffect)(()=>{if(r.kind!==`probing`)return;let n=!1;return j(e,t).then(e=>{n||i(e.transcodable?{kind:`transcode`,probe:e}:{kind:`unsupported`,probe:e})}).catch(()=>{n||i({kind:`unsupported`,probe:null})}),()=>{n=!0}},[r.kind,e,t]),r.kind===`probing`?(0,z.jsx)(`div`,{className:`flex items-center justify-center h-full`,children:(0,z.jsx)(f,{className:`size-5 animate-spin text-text-subtle`})}):r.kind===`transcode`?(0,z.jsx)(U,{filePath:e,projectName:t,mode:`transcode`,probeDuration:r.probe.duration}):r.kind===`unsupported`?(0,z.jsx)(K,{filePath:e,projectName:t,probe:r.probe}):(0,z.jsx)(U,{filePath:e,projectName:t,mode:`native`,onNativeError:()=>i({kind:`probing`})})}function K({filePath:e,projectName:t,probe:n}){let r=[n?.video?.codec,n?.audio?.codec].filter(Boolean).join(` + `);return(0,z.jsxs)(`div`,{className:`flex flex-col items-center justify-center h-full gap-3 text-text-secondary p-6 text-center`,children:[(0,z.jsx)(_,{className:`size-10 text-text-subtle`}),(0,z.jsxs)(`p`,{className:`text-sm`,children:[`This video cannot be played in the browser`,r?` (${r})`:``,`.`]}),(0,z.jsxs)(`p`,{className:`text-xs text-text-subtle max-w-sm`,children:[`Install `,(0,z.jsx)(`code`,{children:`ffmpeg`}),` on the PPM server (e.g. `,(0,z.jsx)(`code`,{children:`winget install ffmpeg`}),`, `,(0,z.jsx)(`code`,{children:`brew install ffmpeg`}),`,`,` `,(0,z.jsx)(`code`,{children:`apt install ffmpeg`}),`) and restart PPM to transcode it on the fly.`]}),(0,z.jsx)(y,{asChild:!0,variant:`outline`,size:`sm`,className:`h-11 px-4`,children:(0,z.jsxs)(`a`,{href:`${M(e,t)}&download=true`,download:!0,children:[(0,z.jsx)(h,{className:`size-4 mr-2`}),` Download file`]})})]})}export{G as VideoPreview};
1
+ import{o as e}from"./rolldown-runtime-FhOqtrmT.js";import{C as t,S as n}from"./vendor-markdown-CuWCHIVb.js";import"./vendor-ui-DmZ-Mb-H.js";import{$n as r,Ct as i,Dr as a,Fr as o,Gn as s,Ir as c,Pr as l,Tt as u,er as d,ln as f,mn as p,or as m,st as h,xn as g,yt as _,zn as v}from"./icons-DQjqk0lJ.js";import"./api-client-C1ZwRL4Y.js";import"./portal-container-context-BarKmT4S.js";import{t as y}from"./button-B9CTrsEf.js";import{Gt as b,Ht as x,Kt as S,Ut as C,Vt as w,Wt as T,Xt as E,zt as D}from"./index-CEZVxM4G.js";import{o as O}from"./can-open-in-ppm-cv5--yHX.js";import{a as k,i as A,n as j,r as M,t as ee}from"./media-url-yfqHpPz0.js";var N=e(t(),1),P={rotation:0,flipH:!1,flipV:!1};function F(e){return{...e,rotation:(e.rotation+90)%360}}function te(e){return{...e,rotation:(e.rotation+270)%360}}function I(e){return e.rotation===0&&!e.flipH&&!e.flipV}function ne(e){let t=[];return e.rotation&&t.push(`rotate(${e.rotation}deg)`),e.flipH&&t.push(`scaleX(-1)`),e.flipV&&t.push(`scaleY(-1)`),t.length?t.join(` `):`none`}function re(e,t){return e.rotation===90||e.rotation===270?{maxWidth:t.height,maxHeight:t.width}:{maxWidth:t.width,maxHeight:t.height}}var L=[[`Space / K`,`Play / pause`],[`← / →`,`Seek 5s`],[`J / L or Shift+← / →`,`Seek 10s`],[`↑ / ↓`,`Volume`],[`M`,`Mute`],[`F`,`Fullscreen`],[`< / >`,`Speed`],[`R / Shift+R`,`Rotate`]];function R(e){return(0,N.useCallback)(t=>{let n=t.target;if(n.tagName===`INPUT`||n.tagName===`TEXTAREA`||n.isContentEditable||t.ctrlKey||t.metaKey||t.altKey)return;let r=!0;switch(t.key){case` `:case`k`:case`K`:e.togglePlay();break;case`ArrowLeft`:e.seekBy(t.shiftKey?-10:-5);break;case`ArrowRight`:e.seekBy(t.shiftKey?10:5);break;case`j`:case`J`:e.seekBy(-10);break;case`l`:case`L`:e.seekBy(10);break;case`ArrowUp`:e.volumeBy(.1);break;case`ArrowDown`:e.volumeBy(-.1);break;case`m`:case`M`:e.toggleMute();break;case`f`:case`F`:e.toggleFullscreen();break;case`<`:case`,`:e.speedStep(-1);break;case`>`:case`.`:e.speedStep(1);break;case`r`:e.rotate(1);break;case`R`:e.rotate(-1);break;default:r=!1}r&&t.preventDefault()},[e])}var z=n(),B=[.25,.5,.75,1,1.25,1.5,2,3];function V({speed:e,onSpeed:t,transform:n,onRotate:o,onFlipH:s,onFlipV:c,onResetTransform:l}){return(0,z.jsxs)(D,{children:[(0,z.jsx)(E,{asChild:!0,children:(0,z.jsxs)(y,{variant:`ghost`,size:`icon`,className:`size-11 shrink-0 relative`,"aria-label":`Playback settings`,children:[(0,z.jsx)(m,{className:`size-5`}),e!==1&&(0,z.jsxs)(`span`,{className:`absolute -top-0.5 -right-0.5 text-[10px] leading-none px-1 rounded bg-primary text-primary-foreground tabular-nums`,children:[e,`x`]})]})}),(0,z.jsxs)(w,{align:`end`,className:`w-60 max-h-[70vh] overflow-y-auto`,children:[(0,z.jsx)(C,{children:`Speed`}),(0,z.jsx)(T,{value:String(e),onValueChange:e=>t(Number(e)),children:(0,z.jsx)(`div`,{className:`grid grid-cols-4 gap-1 px-1 pb-1`,children:B.map(e=>(0,z.jsxs)(b,{value:String(e),className:`justify-center pl-2 min-h-11 text-xs tabular-nums data-[state=checked]:bg-accent [&>span:first-child]:hidden`,children:[e,`x`]},e))})}),(0,z.jsx)(S,{}),(0,z.jsx)(C,{children:`Orientation`}),(0,z.jsxs)(x,{className:`min-h-11`,onSelect:e=>{e.preventDefault(),o(1)},children:[(0,z.jsx)(d,{className:`size-4`}),` Rotate right `,(0,z.jsx)(`span`,{className:`ml-auto text-xs text-text-subtle`,children:`R`})]}),(0,z.jsxs)(x,{className:`min-h-11`,onSelect:e=>{e.preventDefault(),o(-1)},children:[(0,z.jsx)(r,{className:`size-4`}),` Rotate left `,(0,z.jsx)(`span`,{className:`ml-auto text-xs text-text-subtle`,children:`⇧R`})]}),(0,z.jsxs)(x,{className:`min-h-11`,onSelect:e=>{e.preventDefault(),s()},children:[(0,z.jsx)(i,{className:`size-4`}),` Flip horizontal `,n.flipH&&(0,z.jsx)(`span`,{className:`ml-auto text-xs`,children:`✓`})]}),(0,z.jsxs)(x,{className:`min-h-11`,onSelect:e=>{e.preventDefault(),c()},children:[(0,z.jsx)(u,{className:`size-4`}),` Flip vertical `,n.flipV&&(0,z.jsx)(`span`,{className:`ml-auto text-xs`,children:`✓`})]}),!I(n)&&(0,z.jsxs)(x,{className:`min-h-11`,onSelect:l,children:[(0,z.jsx)(a,{className:`size-4`}),` Reset orientation`]}),(0,z.jsx)(S,{}),(0,z.jsx)(C,{children:`Keyboard`}),(0,z.jsx)(`div`,{className:`px-2 pb-2 grid grid-cols-[auto_1fr] gap-x-3 gap-y-1 text-xs text-text-secondary`,children:L.map(([e,t])=>(0,z.jsxs)(`div`,{className:`contents`,children:[(0,z.jsx)(`kbd`,{className:`font-mono text-text-subtle whitespace-nowrap`,children:e}),(0,z.jsx)(`span`,{children:t})]},e))})]})]})}function ie(e){let t=e.muted||e.volume===0?c:e.volume<.5?l:o,n=t=>e.onSeek(Number(t.target.value));return(0,z.jsxs)(`div`,{className:`flex items-center gap-1 px-2 py-1 bg-surface border-t border-border`,children:[(0,z.jsx)(y,{variant:`ghost`,size:`icon`,className:`size-11 shrink-0`,onClick:e.onTogglePlay,"aria-label":e.playing?`Pause`:`Play`,children:e.playing?(0,z.jsx)(v,{className:`size-5`}):(0,z.jsx)(s,{className:`size-5`})}),(0,z.jsxs)(`span`,{className:`text-xs tabular-nums text-text-secondary shrink-0 min-w-[4.5rem] text-center`,children:[H(e.position),e.duration?` / ${H(e.duration)}`:``]}),e.duration?(0,z.jsx)(`input`,{type:`range`,min:0,max:e.duration,step:.1,value:Math.min(e.position,e.duration),"aria-label":`Seek`,className:`flex-1 h-11 accent-primary cursor-pointer min-w-0`,onChange:t=>e.onScrub(Number(t.target.value)),onPointerUp:n,onKeyUp:n,onTouchEnd:n}):(0,z.jsx)(`div`,{className:`flex-1`}),(0,z.jsxs)(`div`,{className:`flex items-center shrink-0`,children:[(0,z.jsx)(y,{variant:`ghost`,size:`icon`,className:`size-11`,onClick:e.onToggleMute,"aria-label":e.muted?`Unmute`:`Mute`,children:(0,z.jsx)(t,{className:`size-5`})}),(0,z.jsx)(`input`,{type:`range`,min:0,max:1,step:.05,value:e.muted?0:e.volume,"aria-label":`Volume`,className:`hidden sm:block w-20 h-11 accent-primary cursor-pointer`,onChange:t=>e.onVolume(Number(t.target.value))})]}),(0,z.jsx)(V,{speed:e.speed,onSpeed:e.onSpeed,transform:e.transform,onRotate:e.onRotate,onFlipH:e.onFlipH,onFlipV:e.onFlipV,onResetTransform:e.onResetTransform}),(0,z.jsx)(y,{variant:`ghost`,size:`icon`,className:`size-11 shrink-0`,onClick:e.onToggleFullscreen,"aria-label":e.fullscreen?`Exit fullscreen`:`Fullscreen`,children:e.fullscreen?(0,z.jsx)(g,{className:`size-5`}):(0,z.jsx)(p,{className:`size-5`})})]})}function H(e){let t=Math.max(0,Math.floor(Number.isFinite(e)?e:0)),n=Math.floor(t/3600),r=Math.floor(t%3600/60),i=t%60,a=n?String(r).padStart(2,`0`):String(r);return`${n?`${n}:`:``}${a}:${String(i).padStart(2,`0`)}`}function U({filePath:e,projectName:t,mode:n,probeDuration:r=null,onNativeError:i}){let a=(0,N.useRef)(null),o=(0,N.useRef)(null),s=(0,N.useRef)(null),c=(0,N.useRef)(!0),[l]=(0,N.useState)(ee),[u,d]=(0,N.useState)(0),[p,m]=(0,N.useState)(0),[h,g]=(0,N.useState)(null),[_,v]=(0,N.useState)(!1),[b,x]=(0,N.useState)(!0),[S,C]=(0,N.useState)(null),[w,T]=(0,N.useState)(1),[E,D]=(0,N.useState)(!1),[O,j]=(0,N.useState)(1),[I,L]=(0,N.useState)(P),[V,H]=(0,N.useState)(!1),[U,W]=(0,N.useState)({width:0,height:0}),[G,K]=(0,N.useState)(null),q=n===`transcode`,J=q?k(e,t,u,l):M(e,t),Y=q?r:h,X=S??(q?u+p:p);(0,N.useEffect)(()=>{m(0),x(!0),K(null)},[J]),(0,N.useEffect)(()=>{d(0),g(null),L(P)},[e,n]),(0,N.useEffect)(()=>{let e=s.current;e&&(e.volume=w,e.muted=E)},[w,E]),(0,N.useEffect)(()=>{let e=s.current;e&&(e.playbackRate=O)},[O,J]),(0,N.useEffect)(()=>{let n=s.current,r=()=>{q&&A(e,t,l)};return window.addEventListener(`pagehide`,r),()=>{window.removeEventListener(`pagehide`,r),n&&!n.isConnected&&(n.pause(),n.removeAttribute(`src`),n.load(),r())}},[e,t,q,l]),(0,N.useEffect)(()=>{let e=()=>H(document.fullscreenElement===a.current);return document.addEventListener(`fullscreenchange`,e),()=>document.removeEventListener(`fullscreenchange`,e)},[]),(0,N.useEffect)(()=>{let e=o.current;if(!e)return;let t=new ResizeObserver(()=>W({width:e.clientWidth,height:e.clientHeight}));return t.observe(e),()=>t.disconnect()},[]);let Z=(0,N.useCallback)(e=>{let t=s.current,n=Math.max(0,Y?Math.min(e,Y-.5):e);if(C(null),!q){t&&(t.currentTime=n);return}Math.abs(n-(u+(t?.currentTime??0)))<.5||d(n)},[Y,q,u]),Q=(0,N.useMemo)(()=>({togglePlay:()=>{let e=s.current;e&&(c.current=e.paused,e.paused?e.play().catch(()=>{}):e.pause())},seekBy:e=>Z((q?u:0)+(s.current?.currentTime??0)+e),toggleFullscreen:()=>{document.fullscreenElement?document.exitFullscreen():a.current?.requestFullscreen?.()},toggleMute:()=>D(e=>!e),volumeBy:e=>{D(!1),T(t=>Math.min(1,Math.max(0,Math.round((t+e)*100)/100)))},speedStep:e=>j(t=>{let n=B.indexOf(t);return B[Math.min(B.length-1,Math.max(0,(n===-1?3:n)+e))]??1}),rotate:e=>L(t=>e===1?F(t):te(t))}),[Z,q,u]),ae=R(Q),$=re(I,U),oe=()=>{K(null),d(e=>e+.001)};return(0,z.jsxs)(`div`,{ref:a,"data-testid":`video-player`,tabIndex:0,onKeyDown:ae,className:`flex flex-col h-full bg-black outline-none focus-visible:ring-1 focus-visible:ring-primary/60`,children:[(0,z.jsxs)(`div`,{ref:o,className:`relative flex-1 min-h-0 flex items-center justify-center overflow-hidden`,onClick:e=>{a.current?.focus(),e.detail===1&&Q.togglePlay()},onDoubleClick:Q.toggleFullscreen,children:[(0,z.jsx)(`video`,{ref:s,src:J,autoPlay:!0,playsInline:!0,preload:q?`auto`:`metadata`,style:{transform:ne(I),maxWidth:$.maxWidth||void 0,maxHeight:$.maxHeight||void 0},onLoadedMetadata:e=>{let t=e.currentTarget;t.playbackRate=O,t.volume=w,t.muted=E,!q&&Number.isFinite(t.duration)&&g(t.duration),q&&!c.current&&t.pause()},onPlay:()=>v(!0),onPause:()=>v(!1),onWaiting:()=>x(!0),onPlaying:()=>x(!1),onCanPlay:()=>x(!1),onTimeUpdate:e=>m(e.currentTarget.currentTime),onEnded:()=>{v(!1),c.current=!1},onError:()=>{q?K(`Transcoding failed. ffmpeg may have stopped or the file is corrupt.`):i?.()}}),b&&!G&&(0,z.jsx)(f,{className:`absolute size-8 animate-spin text-white/80 pointer-events-none`}),G&&(0,z.jsxs)(`div`,{className:`absolute inset-0 flex flex-col items-center justify-center gap-3 bg-black/85 text-text-secondary p-4 text-center`,onClick:e=>e.stopPropagation(),onDoubleClick:e=>e.stopPropagation(),children:[(0,z.jsx)(`p`,{className:`text-sm`,children:G}),(0,z.jsx)(y,{variant:`outline`,size:`sm`,className:`h-11 px-4`,onClick:oe,children:`Retry`})]})]}),(0,z.jsx)(ie,{playing:_,position:X,duration:Y,volume:w,muted:E,speed:O,transform:I,fullscreen:V,onTogglePlay:Q.togglePlay,onScrub:C,onSeek:Z,onVolume:e=>{T(e),D(e===0)},onToggleMute:Q.toggleMute,onSpeed:j,onRotate:Q.rotate,onFlipH:()=>L(e=>({...e,flipH:!e.flipH})),onFlipV:()=>L(e=>({...e,flipV:!e.flipV})),onResetTransform:()=>L(P),onToggleFullscreen:Q.toggleFullscreen})]})}var W=new Set([`mp4`,`m4v`,`webm`,`ogg`,`ogv`,`mov`]);function G({filePath:e,projectName:t}){let n=O(e),[r,i]=(0,N.useState)(()=>W.has(n)?{kind:`native`}:{kind:`probing`});return(0,N.useEffect)(()=>{i(W.has(O(e))?{kind:`native`}:{kind:`probing`})},[e]),(0,N.useEffect)(()=>{if(r.kind!==`probing`)return;let n=!1;return j(e,t).then(e=>{n||i(e.transcodable?{kind:`transcode`,probe:e}:{kind:`unsupported`,probe:e})}).catch(()=>{n||i({kind:`unsupported`,probe:null})}),()=>{n=!0}},[r.kind,e,t]),r.kind===`probing`?(0,z.jsx)(`div`,{className:`flex items-center justify-center h-full`,children:(0,z.jsx)(f,{className:`size-5 animate-spin text-text-subtle`})}):r.kind===`transcode`?(0,z.jsx)(U,{filePath:e,projectName:t,mode:`transcode`,probeDuration:r.probe.duration}):r.kind===`unsupported`?(0,z.jsx)(K,{filePath:e,projectName:t,probe:r.probe}):(0,z.jsx)(U,{filePath:e,projectName:t,mode:`native`,onNativeError:()=>i({kind:`probing`})})}function K({filePath:e,projectName:t,probe:n}){let r=[n?.video?.codec,n?.audio?.codec].filter(Boolean).join(` + `);return(0,z.jsxs)(`div`,{className:`flex flex-col items-center justify-center h-full gap-3 text-text-secondary p-6 text-center`,children:[(0,z.jsx)(_,{className:`size-10 text-text-subtle`}),(0,z.jsxs)(`p`,{className:`text-sm`,children:[`This video cannot be played in the browser`,r?` (${r})`:``,`.`]}),(0,z.jsxs)(`p`,{className:`text-xs text-text-subtle max-w-sm`,children:[`Install `,(0,z.jsx)(`code`,{children:`ffmpeg`}),` on the PPM server (e.g. `,(0,z.jsx)(`code`,{children:`winget install ffmpeg`}),`, `,(0,z.jsx)(`code`,{children:`brew install ffmpeg`}),`,`,` `,(0,z.jsx)(`code`,{children:`apt install ffmpeg`}),`) and restart PPM to transcode it on the fly.`]}),(0,z.jsx)(y,{asChild:!0,variant:`outline`,size:`sm`,className:`h-11 px-4`,children:(0,z.jsxs)(`a`,{href:`${M(e,t)}&download=true`,download:!0,children:[(0,z.jsx)(h,{className:`size-4 mr-2`}),` Download file`]})})]})}export{G as VideoPreview};
@@ -9,7 +9,7 @@
9
9
  <link rel="preconnect" href="https://fonts.googleapis.com" />
10
10
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
11
11
  <link href="https://fonts.googleapis.com/css2?family=Geist+Mono:wght@400;500;600;700&family=Geist:wght@400;500;600;700&display=swap" rel="stylesheet" />
12
- <script type="module" crossorigin src="/assets/index-DU68xk06.js"></script>
12
+ <script type="module" crossorigin src="/assets/index-CEZVxM4G.js"></script>
13
13
  <link rel="modulepreload" crossorigin href="/assets/rolldown-runtime-FhOqtrmT.js">
14
14
  <link rel="modulepreload" crossorigin href="/assets/vendor-mermaid-BitiXJlL.js">
15
15
  <link rel="modulepreload" crossorigin href="/assets/vendor-markdown-CuWCHIVb.js">
package/dist/web/sw.js CHANGED
@@ -1 +1 @@
1
- try{self[`workbox:core:7.3.0`]&&_()}catch{}var e=(e,...t)=>{let n=e;return t.length>0&&(n+=` :: ${JSON.stringify(t)}`),n},t=class extends Error{constructor(t,n){let r=e(t,n);super(r),this.name=t,this.details=n}},n={googleAnalytics:`googleAnalytics`,precache:`precache-v2`,prefix:`workbox`,runtime:`runtime`,suffix:typeof registration<`u`?registration.scope:``},r=e=>[n.prefix,e,n.suffix].filter(e=>e&&e.length>0).join(`-`),i=e=>{for(let t of Object.keys(n))e(t)},a={updateDetails:e=>{i(t=>{typeof e[t]==`string`&&(n[t]=e[t])})},getGoogleAnalyticsName:e=>e||r(n.googleAnalytics),getPrecacheName:e=>e||r(n.precache),getPrefix:()=>n.prefix,getRuntimeName:e=>e||r(n.runtime),getSuffix:()=>n.suffix};function o(e,t){let n=t();return e.waitUntil(n),n}try{self[`workbox:precaching:7.3.0`]&&_()}catch{}var s=`__WB_REVISION__`;function c(e){if(!e)throw new t(`add-to-cache-list-unexpected-type`,{entry:e});if(typeof e==`string`){let t=new URL(e,location.href);return{cacheKey:t.href,url:t.href}}let{revision:n,url:r}=e;if(!r)throw new t(`add-to-cache-list-unexpected-type`,{entry:e});if(!n){let e=new URL(r,location.href);return{cacheKey:e.href,url:e.href}}let i=new URL(r,location.href),a=new URL(r,location.href);return i.searchParams.set(s,n),{cacheKey:i.href,url:a.href}}var l=class{constructor(){this.updatedURLs=[],this.notUpdatedURLs=[],this.handlerWillStart=async({request:e,state:t})=>{t&&(t.originalRequest=e)},this.cachedResponseWillBeUsed=async({event:e,state:t,cachedResponse:n})=>{if(e.type===`install`&&t&&t.originalRequest&&t.originalRequest instanceof Request){let e=t.originalRequest.url;n?this.notUpdatedURLs.push(e):this.updatedURLs.push(e)}return n}}},u=class{constructor({precacheController:e}){this.cacheKeyWillBeUsed=async({request:e,params:t})=>{let n=t?.cacheKey||this._precacheController.getCacheKeyForURL(e.url);return n?new Request(n,{headers:e.headers}):e},this._precacheController=e}},d;function f(){if(d===void 0){let e=new Response(``);if(`body`in e)try{new Response(e.body),d=!0}catch{d=!1}d=!1}return d}async function p(e,n){let r=null;if(e.url&&(r=new URL(e.url).origin),r!==self.location.origin)throw new t(`cross-origin-copy-response`,{origin:r});let i=e.clone(),a={headers:new Headers(i.headers),status:i.status,statusText:i.statusText},o=n?n(a):a,s=f()?i.body:await i.blob();return new Response(s,o)}var m=e=>new URL(String(e),location.href).href.replace(RegExp(`^${location.origin}`),``);function h(e,t){let n=new URL(e);for(let e of t)n.searchParams.delete(e);return n.href}async function g(e,t,n,r){let i=h(t.url,n);if(t.url===i)return e.match(t,r);let a=Object.assign(Object.assign({},r),{ignoreSearch:!0}),o=await e.keys(t,a);for(let t of o)if(i===h(t.url,n))return e.match(t,r)}var v=class{constructor(){this.promise=new Promise((e,t)=>{this.resolve=e,this.reject=t})}},y=new Set;async function b(){for(let e of y)await e()}function x(e){return new Promise(t=>setTimeout(t,e))}try{self[`workbox:strategies:7.3.0`]&&_()}catch{}function S(e){return typeof e==`string`?new Request(e):e}var C=class{constructor(e,t){this._cacheKeys={},Object.assign(this,t),this.event=t.event,this._strategy=e,this._handlerDeferred=new v,this._extendLifetimePromises=[],this._plugins=[...e.plugins],this._pluginStateMap=new Map;for(let e of this._plugins)this._pluginStateMap.set(e,{});this.event.waitUntil(this._handlerDeferred.promise)}async fetch(e){let{event:n}=this,r=S(e);if(r.mode===`navigate`&&n instanceof FetchEvent&&n.preloadResponse){let e=await n.preloadResponse;if(e)return e}let i=this.hasCallback(`fetchDidFail`)?r.clone():null;try{for(let e of this.iterateCallbacks(`requestWillFetch`))r=await e({request:r.clone(),event:n})}catch(e){if(e instanceof Error)throw new t(`plugin-error-request-will-fetch`,{thrownErrorMessage:e.message})}let a=r.clone();try{let e;e=await fetch(r,r.mode===`navigate`?void 0:this._strategy.fetchOptions);for(let t of this.iterateCallbacks(`fetchDidSucceed`))e=await t({event:n,request:a,response:e});return e}catch(e){throw i&&await this.runCallbacks(`fetchDidFail`,{error:e,event:n,originalRequest:i.clone(),request:a.clone()}),e}}async fetchAndCachePut(e){let t=await this.fetch(e),n=t.clone();return this.waitUntil(this.cachePut(e,n)),t}async cacheMatch(e){let t=S(e),n,{cacheName:r,matchOptions:i}=this._strategy,a=await this.getCacheKey(t,`read`),o=Object.assign(Object.assign({},i),{cacheName:r});n=await caches.match(a,o);for(let e of this.iterateCallbacks(`cachedResponseWillBeUsed`))n=await e({cacheName:r,matchOptions:i,cachedResponse:n,request:a,event:this.event})||void 0;return n}async cachePut(e,n){let r=S(e);await x(0);let i=await this.getCacheKey(r,`write`);if(!n)throw new t(`cache-put-with-no-response`,{url:m(i.url)});let a=await this._ensureResponseSafeToCache(n);if(!a)return!1;let{cacheName:o,matchOptions:s}=this._strategy,c=await self.caches.open(o),l=this.hasCallback(`cacheDidUpdate`),u=l?await g(c,i.clone(),[`__WB_REVISION__`],s):null;try{await c.put(i,l?a.clone():a)}catch(e){if(e instanceof Error)throw e.name===`QuotaExceededError`&&await b(),e}for(let e of this.iterateCallbacks(`cacheDidUpdate`))await e({cacheName:o,oldResponse:u,newResponse:a.clone(),request:i,event:this.event});return!0}async getCacheKey(e,t){let n=`${e.url} | ${t}`;if(!this._cacheKeys[n]){let r=e;for(let e of this.iterateCallbacks(`cacheKeyWillBeUsed`))r=S(await e({mode:t,request:r,event:this.event,params:this.params}));this._cacheKeys[n]=r}return this._cacheKeys[n]}hasCallback(e){for(let t of this._strategy.plugins)if(e in t)return!0;return!1}async runCallbacks(e,t){for(let n of this.iterateCallbacks(e))await n(t)}*iterateCallbacks(e){for(let t of this._strategy.plugins)if(typeof t[e]==`function`){let n=this._pluginStateMap.get(t);yield r=>{let i=Object.assign(Object.assign({},r),{state:n});return t[e](i)}}}waitUntil(e){return this._extendLifetimePromises.push(e),e}async doneWaiting(){for(;this._extendLifetimePromises.length;){let e=this._extendLifetimePromises.splice(0),t=(await Promise.allSettled(e)).find(e=>e.status===`rejected`);if(t)throw t.reason}}destroy(){this._handlerDeferred.resolve(null)}async _ensureResponseSafeToCache(e){let t=e,n=!1;for(let e of this.iterateCallbacks(`cacheWillUpdate`))if(t=await e({request:this.request,response:t,event:this.event})||void 0,n=!0,!t)break;return n||t&&t.status!==200&&(t=void 0),t}},w=class{constructor(e={}){this.cacheName=a.getRuntimeName(e.cacheName),this.plugins=e.plugins||[],this.fetchOptions=e.fetchOptions,this.matchOptions=e.matchOptions}handle(e){let[t]=this.handleAll(e);return t}handleAll(e){e instanceof FetchEvent&&(e={event:e,request:e.request});let t=e.event,n=typeof e.request==`string`?new Request(e.request):e.request,r=`params`in e?e.params:void 0,i=new C(this,{event:t,request:n,params:r}),a=this._getResponse(i,n,t);return[a,this._awaitComplete(a,i,n,t)]}async _getResponse(e,n,r){await e.runCallbacks(`handlerWillStart`,{event:r,request:n});let i;try{if(i=await this._handle(n,e),!i||i.type===`error`)throw new t(`no-response`,{url:n.url})}catch(t){if(t instanceof Error){for(let a of e.iterateCallbacks(`handlerDidError`))if(i=await a({error:t,event:r,request:n}),i)break}if(!i)throw t}for(let t of e.iterateCallbacks(`handlerWillRespond`))i=await t({event:r,request:n,response:i});return i}async _awaitComplete(e,t,n,r){let i,a;try{i=await e}catch{}try{await t.runCallbacks(`handlerDidRespond`,{event:r,request:n,response:i}),await t.doneWaiting()}catch(e){e instanceof Error&&(a=e)}if(await t.runCallbacks(`handlerDidComplete`,{event:r,request:n,response:i,error:a}),t.destroy(),a)throw a}},T=class e extends w{constructor(t={}){t.cacheName=a.getPrecacheName(t.cacheName),super(t),this._fallbackToNetwork=t.fallbackToNetwork!==!1,this.plugins.push(e.copyRedirectedCacheableResponsesPlugin)}async _handle(e,t){return await t.cacheMatch(e)||(t.event&&t.event.type===`install`?await this._handleInstall(e,t):await this._handleFetch(e,t))}async _handleFetch(e,n){let r,i=n.params||{};if(this._fallbackToNetwork){let t=i.integrity,a=e.integrity,o=!a||a===t;r=await n.fetch(new Request(e,{integrity:e.mode===`no-cors`?void 0:a||t})),t&&o&&e.mode!==`no-cors`&&(this._useDefaultCacheabilityPluginIfNeeded(),await n.cachePut(e,r.clone()))}else throw new t(`missing-precache-entry`,{cacheName:this.cacheName,url:e.url});return r}async _handleInstall(e,n){this._useDefaultCacheabilityPluginIfNeeded();let r=await n.fetch(e);if(!await n.cachePut(e,r.clone()))throw new t(`bad-precaching-response`,{url:e.url,status:r.status});return r}_useDefaultCacheabilityPluginIfNeeded(){let t=null,n=0;for(let[r,i]of this.plugins.entries())i!==e.copyRedirectedCacheableResponsesPlugin&&(i===e.defaultPrecacheCacheabilityPlugin&&(t=r),i.cacheWillUpdate&&n++);n===0?this.plugins.push(e.defaultPrecacheCacheabilityPlugin):n>1&&t!==null&&this.plugins.splice(t,1)}};T.defaultPrecacheCacheabilityPlugin={async cacheWillUpdate({response:e}){return!e||e.status>=400?null:e}},T.copyRedirectedCacheableResponsesPlugin={async cacheWillUpdate({response:e}){return e.redirected?await p(e):e}};var E=class{constructor({cacheName:e,plugins:t=[],fallbackToNetwork:n=!0}={}){this._urlsToCacheKeys=new Map,this._urlsToCacheModes=new Map,this._cacheKeysToIntegrities=new Map,this._strategy=new T({cacheName:a.getPrecacheName(e),plugins:[...t,new u({precacheController:this})],fallbackToNetwork:n}),this.install=this.install.bind(this),this.activate=this.activate.bind(this)}get strategy(){return this._strategy}precache(e){this.addToCacheList(e),this._installAndActiveListenersAdded||=(self.addEventListener(`install`,this.install),self.addEventListener(`activate`,this.activate),!0)}addToCacheList(e){let n=[];for(let r of e){typeof r==`string`?n.push(r):r&&r.revision===void 0&&n.push(r.url);let{cacheKey:e,url:i}=c(r),a=typeof r!=`string`&&r.revision?`reload`:`default`;if(this._urlsToCacheKeys.has(i)&&this._urlsToCacheKeys.get(i)!==e)throw new t(`add-to-cache-list-conflicting-entries`,{firstEntry:this._urlsToCacheKeys.get(i),secondEntry:e});if(typeof r!=`string`&&r.integrity){if(this._cacheKeysToIntegrities.has(e)&&this._cacheKeysToIntegrities.get(e)!==r.integrity)throw new t(`add-to-cache-list-conflicting-integrities`,{url:i});this._cacheKeysToIntegrities.set(e,r.integrity)}if(this._urlsToCacheKeys.set(i,e),this._urlsToCacheModes.set(i,a),n.length>0){let e=`Workbox is precaching URLs without revision info: ${n.join(`, `)}\nThis is generally NOT safe. Learn more at https://bit.ly/wb-precache`;console.warn(e)}}}install(e){return o(e,async()=>{let t=new l;this.strategy.plugins.push(t);for(let[t,n]of this._urlsToCacheKeys){let r=this._cacheKeysToIntegrities.get(n),i=this._urlsToCacheModes.get(t),a=new Request(t,{integrity:r,cache:i,credentials:`same-origin`});await Promise.all(this.strategy.handleAll({params:{cacheKey:n},request:a,event:e}))}let{updatedURLs:n,notUpdatedURLs:r}=t;return{updatedURLs:n,notUpdatedURLs:r}})}activate(e){return o(e,async()=>{let e=await self.caches.open(this.strategy.cacheName),t=await e.keys(),n=new Set(this._urlsToCacheKeys.values()),r=[];for(let i of t)n.has(i.url)||(await e.delete(i),r.push(i.url));return{deletedURLs:r}})}getURLsToCacheKeys(){return this._urlsToCacheKeys}getCachedURLs(){return[...this._urlsToCacheKeys.keys()]}getCacheKeyForURL(e){let t=new URL(e,location.href);return this._urlsToCacheKeys.get(t.href)}getIntegrityForCacheKey(e){return this._cacheKeysToIntegrities.get(e)}async matchPrecache(e){let t=e instanceof Request?e.url:e,n=this.getCacheKeyForURL(t);if(n)return(await self.caches.open(this.strategy.cacheName)).match(n)}createHandlerBoundToURL(e){let n=this.getCacheKeyForURL(e);if(!n)throw new t(`non-precached-url`,{url:e});return t=>(t.request=new Request(e),t.params=Object.assign({cacheKey:n},t.params),this.strategy.handle(t))}},D,O=()=>(D||=new E,D);try{self[`workbox:routing:7.3.0`]&&_()}catch{}var k=e=>e&&typeof e==`object`?e:{handle:e},A=class{constructor(e,t,n=`GET`){this.handler=k(t),this.match=e,this.method=n}setCatchHandler(e){this.catchHandler=k(e)}},j=class extends A{constructor(e,t,n){super(({url:t})=>{let n=e.exec(t.href);if(n&&!(t.origin!==location.origin&&n.index!==0))return n.slice(1)},t,n)}},M=class{constructor(){this._routes=new Map,this._defaultHandlerMap=new Map}get routes(){return this._routes}addFetchListener(){self.addEventListener(`fetch`,(e=>{let{request:t}=e,n=this.handleRequest({request:t,event:e});n&&e.respondWith(n)}))}addCacheListener(){self.addEventListener(`message`,(e=>{if(e.data&&e.data.type===`CACHE_URLS`){let{payload:t}=e.data,n=Promise.all(t.urlsToCache.map(t=>{typeof t==`string`&&(t=[t]);let n=new Request(...t);return this.handleRequest({request:n,event:e})}));e.waitUntil(n),e.ports&&e.ports[0]&&n.then(()=>e.ports[0].postMessage(!0))}}))}handleRequest({request:e,event:t}){let n=new URL(e.url,location.href);if(!n.protocol.startsWith(`http`))return;let r=n.origin===location.origin,{params:i,route:a}=this.findMatchingRoute({event:t,request:e,sameOrigin:r,url:n}),o=a&&a.handler,s=e.method;if(!o&&this._defaultHandlerMap.has(s)&&(o=this._defaultHandlerMap.get(s)),!o)return;let c;try{c=o.handle({url:n,request:e,event:t,params:i})}catch(e){c=Promise.reject(e)}let l=a&&a.catchHandler;return c instanceof Promise&&(this._catchHandler||l)&&(c=c.catch(async r=>{if(l)try{return await l.handle({url:n,request:e,event:t,params:i})}catch(e){e instanceof Error&&(r=e)}if(this._catchHandler)return this._catchHandler.handle({url:n,request:e,event:t});throw r})),c}findMatchingRoute({url:e,sameOrigin:t,request:n,event:r}){let i=this._routes.get(n.method)||[];for(let a of i){let i,o=a.match({url:e,sameOrigin:t,request:n,event:r});if(o)return i=o,(Array.isArray(i)&&i.length===0||o.constructor===Object&&Object.keys(o).length===0||typeof o==`boolean`)&&(i=void 0),{route:a,params:i}}return{}}setDefaultHandler(e,t=`GET`){this._defaultHandlerMap.set(t,k(e))}setCatchHandler(e){this._catchHandler=k(e)}registerRoute(e){this._routes.has(e.method)||this._routes.set(e.method,[]),this._routes.get(e.method).push(e)}unregisterRoute(e){if(!this._routes.has(e.method))throw new t(`unregister-route-but-not-found-with-method`,{method:e.method});let n=this._routes.get(e.method).indexOf(e);if(n>-1)this._routes.get(e.method).splice(n,1);else throw new t(`unregister-route-route-not-registered`)}},N,P=()=>(N||(N=new M,N.addFetchListener(),N.addCacheListener()),N);function F(e,n,r){let i;if(typeof e==`string`){let t=new URL(e,location.href);i=new A(({url:e})=>e.href===t.href,n,r)}else if(e instanceof RegExp)i=new j(e,n,r);else if(typeof e==`function`)i=new A(e,n,r);else if(e instanceof A)i=e;else throw new t(`unsupported-route-type`,{moduleName:`workbox-routing`,funcName:`registerRoute`,paramName:`capture`});return P().registerRoute(i),i}function I(e,t=[]){for(let n of[...e.searchParams.keys()])t.some(e=>e.test(n))&&e.searchParams.delete(n);return e}function*L(e,{ignoreURLParametersMatching:t=[/^utm_/,/^fbclid$/],directoryIndex:n=`index.html`,cleanURLs:r=!0,urlManipulation:i}={}){let a=new URL(e,location.href);a.hash=``,yield a.href;let o=I(a,t);if(yield o.href,n&&o.pathname.endsWith(`/`)){let e=new URL(o.href);e.pathname+=n,yield e.href}if(r){let e=new URL(o.href);e.pathname+=`.html`,yield e.href}if(i){let e=i({url:a});for(let t of e)yield t.href}}var R=class extends A{constructor(e,t){super(({request:n})=>{let r=e.getURLsToCacheKeys();for(let i of L(n.url,t)){let t=r.get(i);if(t)return{cacheKey:t,integrity:e.getIntegrityForCacheKey(t)}}},e.strategy)}};function z(e){F(new R(O(),e))}var B=`-precache-`,V=async(e,t=B)=>{let n=(await self.caches.keys()).filter(n=>n.includes(t)&&n.includes(self.registration.scope)&&n!==e);return await Promise.all(n.map(e=>self.caches.delete(e))),n};function H(){self.addEventListener(`activate`,(e=>{let t=a.getPrecacheName();e.waitUntil(V(t).then(e=>{}))}))}function U(e){O().precache(e)}function W(e,t){U(e),z(t)}var G=class extends w{async _handle(e,n){let r=await n.cacheMatch(e),i;if(!r)try{r=await n.fetchAndCachePut(e)}catch(e){e instanceof Error&&(i=e)}if(!r)throw new t(`no-response`,{url:e.url,error:i});return r}};W([{"revision":"166e49a6feb053ee22b5265ea5ab7a0d","url":"index.html"},{"revision":"26dccd02a2ef7522892015154f5e3680","url":"manifest.webmanifest"},{"revision":"a0fb34fc84eb148d51812cd62669f20d","url":"icon-512.svg"},{"revision":"a0fb34fc84eb148d51812cd62669f20d","url":"icon-192.svg"},{"revision":null,"url":"assets/index-DU68xk06.js"},{"revision":null,"url":"assets/index-BH99TIE0.css"},{"revision":"a0fb34fc84eb148d51812cd62669f20d","url":"icon-192.svg"},{"revision":"a0fb34fc84eb148d51812cd62669f20d","url":"icon-512.svg"},{"revision":"26dccd02a2ef7522892015154f5e3680","url":"manifest.webmanifest"}]),H();var K=e=>(e.headers.get(`content-type`)??``).startsWith(`text/html`);F(({url:e})=>e.pathname.startsWith(`/assets/`),new G({cacheName:`ppm-assets`,plugins:[{cacheWillUpdate:async({response:e})=>K(e)?null:e,cachedResponseWillBeUsed:async({cachedResponse:e})=>e&&K(e)?null:e}]})),self.skipWaiting(),self.addEventListener(`activate`,()=>{self.clients.claim()});
1
+ try{self[`workbox:core:7.3.0`]&&_()}catch{}var e=(e,...t)=>{let n=e;return t.length>0&&(n+=` :: ${JSON.stringify(t)}`),n},t=class extends Error{constructor(t,n){let r=e(t,n);super(r),this.name=t,this.details=n}},n={googleAnalytics:`googleAnalytics`,precache:`precache-v2`,prefix:`workbox`,runtime:`runtime`,suffix:typeof registration<`u`?registration.scope:``},r=e=>[n.prefix,e,n.suffix].filter(e=>e&&e.length>0).join(`-`),i=e=>{for(let t of Object.keys(n))e(t)},a={updateDetails:e=>{i(t=>{typeof e[t]==`string`&&(n[t]=e[t])})},getGoogleAnalyticsName:e=>e||r(n.googleAnalytics),getPrecacheName:e=>e||r(n.precache),getPrefix:()=>n.prefix,getRuntimeName:e=>e||r(n.runtime),getSuffix:()=>n.suffix};function o(e,t){let n=t();return e.waitUntil(n),n}try{self[`workbox:precaching:7.3.0`]&&_()}catch{}var s=`__WB_REVISION__`;function c(e){if(!e)throw new t(`add-to-cache-list-unexpected-type`,{entry:e});if(typeof e==`string`){let t=new URL(e,location.href);return{cacheKey:t.href,url:t.href}}let{revision:n,url:r}=e;if(!r)throw new t(`add-to-cache-list-unexpected-type`,{entry:e});if(!n){let e=new URL(r,location.href);return{cacheKey:e.href,url:e.href}}let i=new URL(r,location.href),a=new URL(r,location.href);return i.searchParams.set(s,n),{cacheKey:i.href,url:a.href}}var l=class{constructor(){this.updatedURLs=[],this.notUpdatedURLs=[],this.handlerWillStart=async({request:e,state:t})=>{t&&(t.originalRequest=e)},this.cachedResponseWillBeUsed=async({event:e,state:t,cachedResponse:n})=>{if(e.type===`install`&&t&&t.originalRequest&&t.originalRequest instanceof Request){let e=t.originalRequest.url;n?this.notUpdatedURLs.push(e):this.updatedURLs.push(e)}return n}}},u=class{constructor({precacheController:e}){this.cacheKeyWillBeUsed=async({request:e,params:t})=>{let n=t?.cacheKey||this._precacheController.getCacheKeyForURL(e.url);return n?new Request(n,{headers:e.headers}):e},this._precacheController=e}},d;function f(){if(d===void 0){let e=new Response(``);if(`body`in e)try{new Response(e.body),d=!0}catch{d=!1}d=!1}return d}async function p(e,n){let r=null;if(e.url&&(r=new URL(e.url).origin),r!==self.location.origin)throw new t(`cross-origin-copy-response`,{origin:r});let i=e.clone(),a={headers:new Headers(i.headers),status:i.status,statusText:i.statusText},o=n?n(a):a,s=f()?i.body:await i.blob();return new Response(s,o)}var m=e=>new URL(String(e),location.href).href.replace(RegExp(`^${location.origin}`),``);function h(e,t){let n=new URL(e);for(let e of t)n.searchParams.delete(e);return n.href}async function g(e,t,n,r){let i=h(t.url,n);if(t.url===i)return e.match(t,r);let a=Object.assign(Object.assign({},r),{ignoreSearch:!0}),o=await e.keys(t,a);for(let t of o)if(i===h(t.url,n))return e.match(t,r)}var v=class{constructor(){this.promise=new Promise((e,t)=>{this.resolve=e,this.reject=t})}},y=new Set;async function b(){for(let e of y)await e()}function x(e){return new Promise(t=>setTimeout(t,e))}try{self[`workbox:strategies:7.3.0`]&&_()}catch{}function S(e){return typeof e==`string`?new Request(e):e}var C=class{constructor(e,t){this._cacheKeys={},Object.assign(this,t),this.event=t.event,this._strategy=e,this._handlerDeferred=new v,this._extendLifetimePromises=[],this._plugins=[...e.plugins],this._pluginStateMap=new Map;for(let e of this._plugins)this._pluginStateMap.set(e,{});this.event.waitUntil(this._handlerDeferred.promise)}async fetch(e){let{event:n}=this,r=S(e);if(r.mode===`navigate`&&n instanceof FetchEvent&&n.preloadResponse){let e=await n.preloadResponse;if(e)return e}let i=this.hasCallback(`fetchDidFail`)?r.clone():null;try{for(let e of this.iterateCallbacks(`requestWillFetch`))r=await e({request:r.clone(),event:n})}catch(e){if(e instanceof Error)throw new t(`plugin-error-request-will-fetch`,{thrownErrorMessage:e.message})}let a=r.clone();try{let e;e=await fetch(r,r.mode===`navigate`?void 0:this._strategy.fetchOptions);for(let t of this.iterateCallbacks(`fetchDidSucceed`))e=await t({event:n,request:a,response:e});return e}catch(e){throw i&&await this.runCallbacks(`fetchDidFail`,{error:e,event:n,originalRequest:i.clone(),request:a.clone()}),e}}async fetchAndCachePut(e){let t=await this.fetch(e),n=t.clone();return this.waitUntil(this.cachePut(e,n)),t}async cacheMatch(e){let t=S(e),n,{cacheName:r,matchOptions:i}=this._strategy,a=await this.getCacheKey(t,`read`),o=Object.assign(Object.assign({},i),{cacheName:r});n=await caches.match(a,o);for(let e of this.iterateCallbacks(`cachedResponseWillBeUsed`))n=await e({cacheName:r,matchOptions:i,cachedResponse:n,request:a,event:this.event})||void 0;return n}async cachePut(e,n){let r=S(e);await x(0);let i=await this.getCacheKey(r,`write`);if(!n)throw new t(`cache-put-with-no-response`,{url:m(i.url)});let a=await this._ensureResponseSafeToCache(n);if(!a)return!1;let{cacheName:o,matchOptions:s}=this._strategy,c=await self.caches.open(o),l=this.hasCallback(`cacheDidUpdate`),u=l?await g(c,i.clone(),[`__WB_REVISION__`],s):null;try{await c.put(i,l?a.clone():a)}catch(e){if(e instanceof Error)throw e.name===`QuotaExceededError`&&await b(),e}for(let e of this.iterateCallbacks(`cacheDidUpdate`))await e({cacheName:o,oldResponse:u,newResponse:a.clone(),request:i,event:this.event});return!0}async getCacheKey(e,t){let n=`${e.url} | ${t}`;if(!this._cacheKeys[n]){let r=e;for(let e of this.iterateCallbacks(`cacheKeyWillBeUsed`))r=S(await e({mode:t,request:r,event:this.event,params:this.params}));this._cacheKeys[n]=r}return this._cacheKeys[n]}hasCallback(e){for(let t of this._strategy.plugins)if(e in t)return!0;return!1}async runCallbacks(e,t){for(let n of this.iterateCallbacks(e))await n(t)}*iterateCallbacks(e){for(let t of this._strategy.plugins)if(typeof t[e]==`function`){let n=this._pluginStateMap.get(t);yield r=>{let i=Object.assign(Object.assign({},r),{state:n});return t[e](i)}}}waitUntil(e){return this._extendLifetimePromises.push(e),e}async doneWaiting(){for(;this._extendLifetimePromises.length;){let e=this._extendLifetimePromises.splice(0),t=(await Promise.allSettled(e)).find(e=>e.status===`rejected`);if(t)throw t.reason}}destroy(){this._handlerDeferred.resolve(null)}async _ensureResponseSafeToCache(e){let t=e,n=!1;for(let e of this.iterateCallbacks(`cacheWillUpdate`))if(t=await e({request:this.request,response:t,event:this.event})||void 0,n=!0,!t)break;return n||t&&t.status!==200&&(t=void 0),t}},w=class{constructor(e={}){this.cacheName=a.getRuntimeName(e.cacheName),this.plugins=e.plugins||[],this.fetchOptions=e.fetchOptions,this.matchOptions=e.matchOptions}handle(e){let[t]=this.handleAll(e);return t}handleAll(e){e instanceof FetchEvent&&(e={event:e,request:e.request});let t=e.event,n=typeof e.request==`string`?new Request(e.request):e.request,r=`params`in e?e.params:void 0,i=new C(this,{event:t,request:n,params:r}),a=this._getResponse(i,n,t);return[a,this._awaitComplete(a,i,n,t)]}async _getResponse(e,n,r){await e.runCallbacks(`handlerWillStart`,{event:r,request:n});let i;try{if(i=await this._handle(n,e),!i||i.type===`error`)throw new t(`no-response`,{url:n.url})}catch(t){if(t instanceof Error){for(let a of e.iterateCallbacks(`handlerDidError`))if(i=await a({error:t,event:r,request:n}),i)break}if(!i)throw t}for(let t of e.iterateCallbacks(`handlerWillRespond`))i=await t({event:r,request:n,response:i});return i}async _awaitComplete(e,t,n,r){let i,a;try{i=await e}catch{}try{await t.runCallbacks(`handlerDidRespond`,{event:r,request:n,response:i}),await t.doneWaiting()}catch(e){e instanceof Error&&(a=e)}if(await t.runCallbacks(`handlerDidComplete`,{event:r,request:n,response:i,error:a}),t.destroy(),a)throw a}},T=class e extends w{constructor(t={}){t.cacheName=a.getPrecacheName(t.cacheName),super(t),this._fallbackToNetwork=t.fallbackToNetwork!==!1,this.plugins.push(e.copyRedirectedCacheableResponsesPlugin)}async _handle(e,t){return await t.cacheMatch(e)||(t.event&&t.event.type===`install`?await this._handleInstall(e,t):await this._handleFetch(e,t))}async _handleFetch(e,n){let r,i=n.params||{};if(this._fallbackToNetwork){let t=i.integrity,a=e.integrity,o=!a||a===t;r=await n.fetch(new Request(e,{integrity:e.mode===`no-cors`?void 0:a||t})),t&&o&&e.mode!==`no-cors`&&(this._useDefaultCacheabilityPluginIfNeeded(),await n.cachePut(e,r.clone()))}else throw new t(`missing-precache-entry`,{cacheName:this.cacheName,url:e.url});return r}async _handleInstall(e,n){this._useDefaultCacheabilityPluginIfNeeded();let r=await n.fetch(e);if(!await n.cachePut(e,r.clone()))throw new t(`bad-precaching-response`,{url:e.url,status:r.status});return r}_useDefaultCacheabilityPluginIfNeeded(){let t=null,n=0;for(let[r,i]of this.plugins.entries())i!==e.copyRedirectedCacheableResponsesPlugin&&(i===e.defaultPrecacheCacheabilityPlugin&&(t=r),i.cacheWillUpdate&&n++);n===0?this.plugins.push(e.defaultPrecacheCacheabilityPlugin):n>1&&t!==null&&this.plugins.splice(t,1)}};T.defaultPrecacheCacheabilityPlugin={async cacheWillUpdate({response:e}){return!e||e.status>=400?null:e}},T.copyRedirectedCacheableResponsesPlugin={async cacheWillUpdate({response:e}){return e.redirected?await p(e):e}};var E=class{constructor({cacheName:e,plugins:t=[],fallbackToNetwork:n=!0}={}){this._urlsToCacheKeys=new Map,this._urlsToCacheModes=new Map,this._cacheKeysToIntegrities=new Map,this._strategy=new T({cacheName:a.getPrecacheName(e),plugins:[...t,new u({precacheController:this})],fallbackToNetwork:n}),this.install=this.install.bind(this),this.activate=this.activate.bind(this)}get strategy(){return this._strategy}precache(e){this.addToCacheList(e),this._installAndActiveListenersAdded||=(self.addEventListener(`install`,this.install),self.addEventListener(`activate`,this.activate),!0)}addToCacheList(e){let n=[];for(let r of e){typeof r==`string`?n.push(r):r&&r.revision===void 0&&n.push(r.url);let{cacheKey:e,url:i}=c(r),a=typeof r!=`string`&&r.revision?`reload`:`default`;if(this._urlsToCacheKeys.has(i)&&this._urlsToCacheKeys.get(i)!==e)throw new t(`add-to-cache-list-conflicting-entries`,{firstEntry:this._urlsToCacheKeys.get(i),secondEntry:e});if(typeof r!=`string`&&r.integrity){if(this._cacheKeysToIntegrities.has(e)&&this._cacheKeysToIntegrities.get(e)!==r.integrity)throw new t(`add-to-cache-list-conflicting-integrities`,{url:i});this._cacheKeysToIntegrities.set(e,r.integrity)}if(this._urlsToCacheKeys.set(i,e),this._urlsToCacheModes.set(i,a),n.length>0){let e=`Workbox is precaching URLs without revision info: ${n.join(`, `)}\nThis is generally NOT safe. Learn more at https://bit.ly/wb-precache`;console.warn(e)}}}install(e){return o(e,async()=>{let t=new l;this.strategy.plugins.push(t);for(let[t,n]of this._urlsToCacheKeys){let r=this._cacheKeysToIntegrities.get(n),i=this._urlsToCacheModes.get(t),a=new Request(t,{integrity:r,cache:i,credentials:`same-origin`});await Promise.all(this.strategy.handleAll({params:{cacheKey:n},request:a,event:e}))}let{updatedURLs:n,notUpdatedURLs:r}=t;return{updatedURLs:n,notUpdatedURLs:r}})}activate(e){return o(e,async()=>{let e=await self.caches.open(this.strategy.cacheName),t=await e.keys(),n=new Set(this._urlsToCacheKeys.values()),r=[];for(let i of t)n.has(i.url)||(await e.delete(i),r.push(i.url));return{deletedURLs:r}})}getURLsToCacheKeys(){return this._urlsToCacheKeys}getCachedURLs(){return[...this._urlsToCacheKeys.keys()]}getCacheKeyForURL(e){let t=new URL(e,location.href);return this._urlsToCacheKeys.get(t.href)}getIntegrityForCacheKey(e){return this._cacheKeysToIntegrities.get(e)}async matchPrecache(e){let t=e instanceof Request?e.url:e,n=this.getCacheKeyForURL(t);if(n)return(await self.caches.open(this.strategy.cacheName)).match(n)}createHandlerBoundToURL(e){let n=this.getCacheKeyForURL(e);if(!n)throw new t(`non-precached-url`,{url:e});return t=>(t.request=new Request(e),t.params=Object.assign({cacheKey:n},t.params),this.strategy.handle(t))}},D,O=()=>(D||=new E,D);try{self[`workbox:routing:7.3.0`]&&_()}catch{}var k=e=>e&&typeof e==`object`?e:{handle:e},A=class{constructor(e,t,n=`GET`){this.handler=k(t),this.match=e,this.method=n}setCatchHandler(e){this.catchHandler=k(e)}},j=class extends A{constructor(e,t,n){super(({url:t})=>{let n=e.exec(t.href);if(n&&!(t.origin!==location.origin&&n.index!==0))return n.slice(1)},t,n)}},M=class{constructor(){this._routes=new Map,this._defaultHandlerMap=new Map}get routes(){return this._routes}addFetchListener(){self.addEventListener(`fetch`,(e=>{let{request:t}=e,n=this.handleRequest({request:t,event:e});n&&e.respondWith(n)}))}addCacheListener(){self.addEventListener(`message`,(e=>{if(e.data&&e.data.type===`CACHE_URLS`){let{payload:t}=e.data,n=Promise.all(t.urlsToCache.map(t=>{typeof t==`string`&&(t=[t]);let n=new Request(...t);return this.handleRequest({request:n,event:e})}));e.waitUntil(n),e.ports&&e.ports[0]&&n.then(()=>e.ports[0].postMessage(!0))}}))}handleRequest({request:e,event:t}){let n=new URL(e.url,location.href);if(!n.protocol.startsWith(`http`))return;let r=n.origin===location.origin,{params:i,route:a}=this.findMatchingRoute({event:t,request:e,sameOrigin:r,url:n}),o=a&&a.handler,s=e.method;if(!o&&this._defaultHandlerMap.has(s)&&(o=this._defaultHandlerMap.get(s)),!o)return;let c;try{c=o.handle({url:n,request:e,event:t,params:i})}catch(e){c=Promise.reject(e)}let l=a&&a.catchHandler;return c instanceof Promise&&(this._catchHandler||l)&&(c=c.catch(async r=>{if(l)try{return await l.handle({url:n,request:e,event:t,params:i})}catch(e){e instanceof Error&&(r=e)}if(this._catchHandler)return this._catchHandler.handle({url:n,request:e,event:t});throw r})),c}findMatchingRoute({url:e,sameOrigin:t,request:n,event:r}){let i=this._routes.get(n.method)||[];for(let a of i){let i,o=a.match({url:e,sameOrigin:t,request:n,event:r});if(o)return i=o,(Array.isArray(i)&&i.length===0||o.constructor===Object&&Object.keys(o).length===0||typeof o==`boolean`)&&(i=void 0),{route:a,params:i}}return{}}setDefaultHandler(e,t=`GET`){this._defaultHandlerMap.set(t,k(e))}setCatchHandler(e){this._catchHandler=k(e)}registerRoute(e){this._routes.has(e.method)||this._routes.set(e.method,[]),this._routes.get(e.method).push(e)}unregisterRoute(e){if(!this._routes.has(e.method))throw new t(`unregister-route-but-not-found-with-method`,{method:e.method});let n=this._routes.get(e.method).indexOf(e);if(n>-1)this._routes.get(e.method).splice(n,1);else throw new t(`unregister-route-route-not-registered`)}},N,P=()=>(N||(N=new M,N.addFetchListener(),N.addCacheListener()),N);function F(e,n,r){let i;if(typeof e==`string`){let t=new URL(e,location.href);i=new A(({url:e})=>e.href===t.href,n,r)}else if(e instanceof RegExp)i=new j(e,n,r);else if(typeof e==`function`)i=new A(e,n,r);else if(e instanceof A)i=e;else throw new t(`unsupported-route-type`,{moduleName:`workbox-routing`,funcName:`registerRoute`,paramName:`capture`});return P().registerRoute(i),i}function I(e,t=[]){for(let n of[...e.searchParams.keys()])t.some(e=>e.test(n))&&e.searchParams.delete(n);return e}function*L(e,{ignoreURLParametersMatching:t=[/^utm_/,/^fbclid$/],directoryIndex:n=`index.html`,cleanURLs:r=!0,urlManipulation:i}={}){let a=new URL(e,location.href);a.hash=``,yield a.href;let o=I(a,t);if(yield o.href,n&&o.pathname.endsWith(`/`)){let e=new URL(o.href);e.pathname+=n,yield e.href}if(r){let e=new URL(o.href);e.pathname+=`.html`,yield e.href}if(i){let e=i({url:a});for(let t of e)yield t.href}}var R=class extends A{constructor(e,t){super(({request:n})=>{let r=e.getURLsToCacheKeys();for(let i of L(n.url,t)){let t=r.get(i);if(t)return{cacheKey:t,integrity:e.getIntegrityForCacheKey(t)}}},e.strategy)}};function z(e){F(new R(O(),e))}var B=`-precache-`,V=async(e,t=B)=>{let n=(await self.caches.keys()).filter(n=>n.includes(t)&&n.includes(self.registration.scope)&&n!==e);return await Promise.all(n.map(e=>self.caches.delete(e))),n};function H(){self.addEventListener(`activate`,(e=>{let t=a.getPrecacheName();e.waitUntil(V(t).then(e=>{}))}))}function U(e){O().precache(e)}function W(e,t){U(e),z(t)}var G=class extends w{async _handle(e,n){let r=await n.cacheMatch(e),i;if(!r)try{r=await n.fetchAndCachePut(e)}catch(e){e instanceof Error&&(i=e)}if(!r)throw new t(`no-response`,{url:e.url,error:i});return r}};W([{"revision":"e7df0dd1bfe9b16560e99adb2afd00f8","url":"index.html"},{"revision":"26dccd02a2ef7522892015154f5e3680","url":"manifest.webmanifest"},{"revision":"a0fb34fc84eb148d51812cd62669f20d","url":"icon-512.svg"},{"revision":"a0fb34fc84eb148d51812cd62669f20d","url":"icon-192.svg"},{"revision":null,"url":"assets/index-CEZVxM4G.js"},{"revision":null,"url":"assets/index-BH99TIE0.css"},{"revision":"a0fb34fc84eb148d51812cd62669f20d","url":"icon-192.svg"},{"revision":"a0fb34fc84eb148d51812cd62669f20d","url":"icon-512.svg"},{"revision":"26dccd02a2ef7522892015154f5e3680","url":"manifest.webmanifest"}]),H();var K=e=>(e.headers.get(`content-type`)??``).startsWith(`text/html`);F(({url:e})=>e.pathname.startsWith(`/assets/`),new G({cacheName:`ppm-assets`,plugins:[{cacheWillUpdate:async({response:e})=>K(e)?null:e,cachedResponseWillBeUsed:async({cachedResponse:e})=>e&&K(e)?null:e}]})),self.skipWaiting(),self.addEventListener(`activate`,()=>{self.clients.claim()});
@@ -2,6 +2,15 @@
2
2
 
3
3
  > Part of the [PPM system architecture](../system-architecture.md).
4
4
 
5
+ ## Codex daily guard for weekly-only accounts
6
+
7
+ Daily guard spreads a seven-day quota window across five weekdays: each weekday
8
+ unlocks another 20% of the weekly quota. Unused allowance carries forward.
9
+ Saturday/Sunday slots keep the previous cap; a window starting on a weekend
10
+ opens its first allowance on Monday. Slots are 24 hours from the weekly reset
11
+ time and use UTC weekdays, consistently in the server and browser. This does not
12
+ change Codex's reset schedule. Users can disable the guard per account.
13
+
5
14
  ## Codex context settings
6
15
 
7
16
  **AI Settings → Codex** exposes **Context window (tokens)** and **Auto-compact
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hienlh/ppm",
3
- "version": "0.22.0",
3
+ "version": "0.22.1",
4
4
  "description": "Personal Project Manager — mobile-first web IDE with AI assistance",
5
5
  "author": "hienlh",
6
6
  "license": "SEE LICENSE IN LICENSE",
@@ -589,14 +589,39 @@ describe("webview-html: a panel narrower than the table", () => {
589
589
  expect(html).toContain('<div id="graph-clip"><div id="graph-svg-container"></div></div>');
590
590
  });
591
591
 
592
- it("puts the graph's scrollbar in the header, not on the graph", () => {
593
- // The overlay is as tall as the whole history, so a scrollbar along its
594
- // bottom edge would sit thousands of pixels below the viewport.
595
- const header = html.slice(html.indexOf('id="graph-header"'), html.indexOf('id="commit-list-wrapper"'));
596
- expect(header).toContain('id="graph-hscroll"');
592
+ it("pans the graph by dragging it, with no scrollbar taking a row", () => {
593
+ // A real scrollbar has nowhere to go: not on the overlay, which is as tall
594
+ // as the whole history, and not in the 24px header row, where the thumb
595
+ // comes down across the word "Graph". So the graph is dragged directly, and
596
+ // the only furniture is a hint that takes no space in the table.
597
+ expect(html).not.toContain("graph-hscroll");
598
+ expect(html).toMatch(/#graph-pan-bar \{[^}]*position: absolute/);
599
+ expect(html).toMatch(/#graph-pan-bar \{[^}]*pointer-events: none/);
597
600
  expect(html).toContain("transform: translateX(calc(-1 * var(--graph-pan-x, 0px)))");
598
601
  });
599
602
 
603
+ it("leaves the vertical scroll to the browser and the sideways drag to itself", () => {
604
+ // Without pan-y the finger that scrolls the list would be taken for a pan
605
+ // attempt on every row whose graph cell it happened to land on.
606
+ expect(html).toContain(".commit-row:not(.header-row) .col-graph { align-self: stretch; touch-action: pan-y; }");
607
+ expect(html).toContain("Math.abs(dx) <= Math.abs(e.clientY - startY)");
608
+ });
609
+
610
+ it("gives a row's graph cell a height to be dragged by, and spares the header's", () => {
611
+ // The cell is an empty spacer in a row that centres its cells, so it is 0px
612
+ // tall and every pointer lands on the row behind it. The header's cell has
613
+ // a label, and stretching that one lifts it off the other headings' line.
614
+ expect(html).toMatch(/\.commit-row:not\(\.header-row\) \.col-graph \{[^}]*align-self: stretch/);
615
+ expect(html).not.toMatch(/^\.commit-row \.col-graph \{/m);
616
+ });
617
+
618
+ it("does not select the commit a drag happened to end on", () => {
619
+ // The row's own click handler opens a commit, and a pan ends over a row.
620
+ const click = html.slice(html.indexOf("list.addEventListener('click'"));
621
+ expect(click.slice(0, 200)).toContain("e.stopPropagation()");
622
+ expect(click.slice(0, 200)).toContain("}, true)");
623
+ });
624
+
600
625
  it("agrees between the message column's floor and the cap that respects it", () => {
601
626
  // Two numbers for one thing: a CSS floor wider than the JS cap allows for
602
627
  // is a row that overflows its own box instead of one that fits.
@@ -99,7 +99,7 @@ ${getStyles()}
99
99
  <div id="graph-container">
100
100
  <div id="graph-header" class="commit-row header-row">
101
101
  <div class="col-refs">Branch / Tag</div>
102
- <div class="col-graph">Graph<div class="graph-hscroll hidden" id="graph-hscroll"><div id="graph-hscroll-inner"></div></div><div class="graph-resize-handle" id="graph-resize-handle"></div></div>
102
+ <div class="col-graph">Graph<div class="graph-resize-handle" id="graph-resize-handle"></div></div>
103
103
  <div class="col-message">Message</div>
104
104
  <div class="col-changes">Changes</div>
105
105
  <div class="col-author">Author</div>
@@ -112,6 +112,7 @@ ${getStyles()}
112
112
  </div>
113
113
  <div id="loading" class="loading hidden">Loading...</div>
114
114
  </div>
115
+ <div id="graph-pan-bar" class="hidden" aria-hidden="true"><div id="graph-pan-thumb"></div></div>
115
116
  <div id="scroll-markers" aria-hidden="true"></div>
116
117
  </div>
117
118
  <div id="detail-panel" class="detail-panel hidden"></div>
@@ -374,16 +375,24 @@ button:active { background: var(--surface); }
374
375
  .col-graph { width: var(--graph-col-w, 120px); min-width: var(--graph-col-w, 80px); overflow: hidden; flex-shrink: 0; position: relative; }
375
376
  .graph-resize-handle { position: absolute; right: 0; top: 0; bottom: 0; width: 6px; cursor: col-resize; z-index: 3; background: transparent; }
376
377
  .graph-resize-handle:hover, .graph-resize-handle.dragging { background: var(--blue); opacity: 0.5; }
377
- /* The graph's own horizontal scrollbar, in the sticky header. It cannot sit on
378
- the graph itself: that is one overlay as tall as the whole history, so a
379
- scrollbar along its bottom edge would be thousands of pixels below the
380
- viewport. This strip scrolls nothing its scrollLeft is read and applied to
381
- the overlay as a translation. */
382
- .graph-hscroll { position: absolute; left: 0; right: 6px; bottom: 0; height: 7px; overflow-x: auto; overflow-y: hidden; }
383
- .graph-hscroll-inner { height: 1px; }
384
- .graph-hscroll::-webkit-scrollbar { height: 6px; }
385
- .graph-hscroll::-webkit-scrollbar-thumb { background: var(--border2); border-radius: 3px; }
386
- .graph-hscroll::-webkit-scrollbar-thumb:hover { background: var(--subtext); }
378
+ /* Panning the graph is a drag on the graph itself, so there is no scrollbar in
379
+ the table taking a row of its own a real one cannot go on the overlay,
380
+ which is as tall as the whole history, and in a 24px header row the thumb
381
+ lands across the word "Graph". What is left is a hint: where in the lanes the
382
+ column currently is, shown while a drag or a wheel is moving it and faded out
383
+ after. It is positioned over the graph area rather than inside the scroller,
384
+ so it neither scrolls away nor displaces a row. */
385
+ /* A row's graph cell is an empty spacer, and the row centres its cells — so
386
+ without this it is 0px tall and the pointer that looks like it is on the
387
+ graph is really on the row behind it, which is what decides whether a drag
388
+ pans or selects a commit. Not the header's cell: that one has a label in it,
389
+ and stretching it takes the label off the line the other headings sit on. */
390
+ .commit-row:not(.header-row) .col-graph { align-self: stretch; touch-action: pan-y; }
391
+ :root.graph-can-pan .commit-row:not(.header-row) .col-graph { cursor: grab; }
392
+ :root.graph-panning .commit-row:not(.header-row) .col-graph { cursor: grabbing; }
393
+ #graph-pan-bar { position: absolute; z-index: 4; bottom: 6px; left: calc(var(--refs-col-w, 170px) + 6px); width: var(--graph-col-w, 120px); height: 4px; border-radius: 2px; background: color-mix(in srgb, var(--text) 10%, transparent); opacity: 0; transition: opacity 0.4s ease; pointer-events: none; }
394
+ #graph-pan-bar.visible { opacity: 1; transition-duration: 0.1s; }
395
+ #graph-pan-thumb { position: absolute; top: 0; bottom: 0; border-radius: 2px; background: var(--subtext); }
387
396
  /* The message never shrinks past a readable measure. Every other column is
388
397
  either fixed or hidden by the width tiers, so without a floor here this one
389
398
  absorbs the whole shortfall and disappears. */
@@ -454,7 +463,7 @@ button:active { background: var(--surface); }
454
463
  changes and author columns — it is positioned and they are not, so it wins
455
464
  the paint order — and capping the column without clipping only trades a
456
465
  missing message for one with branch lines drawn through it. What the clip
457
- hides is reached by panning: --graph-pan-x, driven by the header's strip. */
466
+ hides is reached by panning: --graph-pan-x, driven by a drag on the graph. */
458
467
  #commit-list-wrapper { position: relative; }
459
468
  #graph-clip { position: absolute; top: 0; left: calc(var(--refs-col-w, 170px) + 6px); width: var(--graph-col-w, 120px); height: 100%; overflow: hidden; z-index: 1; pointer-events: none; }
460
469
  /* The clip box starts where the graph cell starts — 6px being the row's own
@@ -702,10 +711,6 @@ button:active { background: var(--surface); }
702
711
  #graph-container { overflow-x: auto; overflow-y: auto; }
703
712
  #find-bar { order: 0; }
704
713
  #status-bar { order: 9; }
705
- /* A 6px scrollbar is a mouse's target. This is the only way to pan the graph
706
- without a wheel, so it gets a thumb a finger can land on. */
707
- .graph-hscroll { height: 14px; }
708
- .graph-hscroll::-webkit-scrollbar { height: 12px; }
709
714
  .commit-row.header-row { min-height: 20px; }
710
715
  .detail-panel { order: 8; max-height: 35vh; }
711
716
  }
@@ -1643,12 +1648,56 @@ document.getElementById('stash-save').addEventListener('click', () => {
1643
1648
 
1644
1649
  // --- Panning the graph inside its column ---
1645
1650
  {
1646
- const strip = document.getElementById('graph-hscroll');
1647
- strip.addEventListener('scroll', () => {
1648
- if (Math.abs(strip.scrollLeft - state.graphPanX) <= 1) return;
1649
- state.graphPanX = strip.scrollLeft;
1651
+ const list = document.getElementById('commit-list');
1652
+ let tracking = false, panned = false, startX = 0, startY = 0, startPan = 0, pointerId = null;
1653
+
1654
+ list.addEventListener('pointerdown', (e) => {
1655
+ if (e.button !== 0 || !e.target.closest || !e.target.closest('.col-graph')) return;
1656
+ if (graphPanMax() <= 0) return;
1657
+ tracking = true;
1658
+ panned = false;
1659
+ startX = e.clientX;
1660
+ startY = e.clientY;
1661
+ startPan = state.graphPanX;
1662
+ pointerId = e.pointerId;
1663
+ });
1664
+
1665
+ list.addEventListener('pointermove', (e) => {
1666
+ if (!tracking) return;
1667
+ const dx = e.clientX - startX;
1668
+ if (!panned) {
1669
+ // Sideways and past the slop before this is a pan: anything else is the
1670
+ // press that selects a commit, or the finger that scrolls the list —
1671
+ // .col-graph is touch-action: pan-y so the browser keeps that one.
1672
+ if (Math.abs(dx) < 4 || Math.abs(dx) <= Math.abs(e.clientY - startY)) return;
1673
+ panned = true;
1674
+ list.setPointerCapture(pointerId);
1675
+ document.documentElement.classList.add('graph-panning');
1676
+ showPanHint(true);
1677
+ }
1678
+ state.graphPanX = startPan - dx;
1650
1679
  applyGraphPan();
1651
1680
  });
1681
+
1682
+ const endPan = () => {
1683
+ if (!tracking) return;
1684
+ tracking = false;
1685
+ if (!panned) return;
1686
+ try { list.releasePointerCapture(pointerId); } catch (err) { /* already released */ }
1687
+ document.documentElement.classList.remove('graph-panning');
1688
+ showPanHint(false);
1689
+ };
1690
+ list.addEventListener('pointerup', endPan);
1691
+ list.addEventListener('pointercancel', endPan);
1692
+ // A drag is not a click. Captured on the way down, because the row's own
1693
+ // handler would otherwise open the commit the pan happened to end on.
1694
+ list.addEventListener('click', (e) => {
1695
+ if (!panned) return;
1696
+ panned = false;
1697
+ e.stopPropagation();
1698
+ e.preventDefault();
1699
+ }, true);
1700
+
1652
1701
  // A trackpad's sideways gesture and shift+wheel, over the list itself. The
1653
1702
  // overlay cannot take these: it is pointer-events: none so that a click lands
1654
1703
  // on the row underneath it.
@@ -2071,30 +2120,49 @@ function applyGraphColWidth() {
2071
2120
  applyGraphPan();
2072
2121
  }
2073
2122
 
2123
+ /** How far the graph can be moved: what is drawn, less what the column shows. */
2124
+ function graphPanMax() {
2125
+ const cell = document.querySelector('#graph-header .col-graph');
2126
+ return Math.max(0, state.graphWidth - (cell ? cell.offsetWidth : 0));
2127
+ }
2128
+
2074
2129
  /**
2075
- * Move the overlay inside its clip box, and keep the header's scroll strip
2076
- * saying the same thing. The strip scrolls nothing itself it exists because
2077
- * a scrollbar on the overlay would sit below the last commit in the history.
2130
+ * Move the overlay inside its clip box, and put the hint where the column now
2131
+ * is. The hint is not a scrollbar: it takes no room in the table and is only
2132
+ * legible while something is moving the graph.
2078
2133
  */
2079
2134
  function applyGraphPan() {
2080
2135
  const cell = document.querySelector('#graph-header .col-graph');
2081
2136
  const shown = cell ? cell.offsetWidth : 0;
2082
- const max = Math.max(0, state.graphWidth - shown);
2137
+ const max = graphPanMax();
2083
2138
  state.graphPanX = Math.min(Math.max(0, state.graphPanX), max);
2084
2139
  document.documentElement.style.setProperty('--graph-pan-x', state.graphPanX + 'px');
2140
+ document.documentElement.classList.toggle('graph-can-pan', max > 0);
2141
+
2142
+ const bar = document.getElementById('graph-pan-bar');
2143
+ const thumb = document.getElementById('graph-pan-thumb');
2144
+ if (!bar || !thumb) return;
2145
+ bar.classList.toggle('hidden', max <= 0 || !state.graphWidth);
2146
+ if (max <= 0 || !state.graphWidth) return;
2147
+ const ratio = shown / state.graphWidth;
2148
+ thumb.style.width = (ratio * 100) + '%';
2149
+ thumb.style.left = ((state.graphPanX / state.graphWidth) * 100) + '%';
2150
+ }
2085
2151
 
2086
- const strip = document.getElementById('graph-hscroll');
2087
- const inner = document.getElementById('graph-hscroll-inner');
2088
- if (!strip || !inner) return;
2089
- inner.style.width = state.graphWidth + 'px';
2090
- strip.classList.toggle('hidden', max <= 0);
2091
- // Guarded, or writing scrollLeft here re-enters through the scroll handler.
2092
- if (Math.abs(strip.scrollLeft - state.graphPanX) > 1) strip.scrollLeft = state.graphPanX;
2152
+ /** Show the hint while something is moving the graph, then let it fade. */
2153
+ let panHintTimer = null;
2154
+ function showPanHint(sticky) {
2155
+ const bar = document.getElementById('graph-pan-bar');
2156
+ if (!bar || bar.classList.contains('hidden')) return;
2157
+ bar.classList.add('visible');
2158
+ if (panHintTimer) clearTimeout(panHintTimer);
2159
+ panHintTimer = sticky ? null : setTimeout(() => bar.classList.remove('visible'), 700);
2093
2160
  }
2094
2161
 
2095
2162
  function panGraphBy(dx) {
2096
2163
  state.graphPanX += dx;
2097
2164
  applyGraphPan();
2165
+ showPanHint(false);
2098
2166
  }
2099
2167
 
2100
2168
  function graphVertexOver(e) {