@hienlh/ppm 0.22.0 → 0.22.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +20 -0
- package/CLAUDE.md +1 -1
- package/assets/skills/ppm/SKILL.md +1 -1
- package/assets/skills/ppm/references/cli-reference.md +4 -4
- package/assets/skills/ppm/references/http-api.md +1 -1
- package/dist/web/assets/accounts-settings-section-CLEAA_Jc.js +1 -0
- package/dist/web/assets/{ai-resource-editor-CdDpOwjh.js → ai-resource-editor-C4ecid2g.js} +1 -1
- package/dist/web/assets/ai-settings-section-BOwGdiyH.js +1 -0
- package/dist/web/assets/ai-settings-section-Cqz13gRt.js +1 -0
- package/dist/web/assets/{api-client-C1ZwRL4Y.js → api-client-Jn3njtNw.js} +1 -1
- package/dist/web/assets/api-client-rSFnnCj4.js +1 -0
- package/dist/web/assets/{api-settings-_7Q-ULxp.js → api-settings-BxijvPBR.js} +1 -1
- package/dist/web/assets/{api-themes-DRAERo4Q.js → api-themes-CSUarkzD.js} +1 -1
- package/dist/web/assets/{appearance-settings-section-DLoPK0LD.js → appearance-settings-section-DbA8L-Vz.js} +1 -1
- package/dist/web/assets/{audio-preview-DsYvgKqj.js → audio-preview-CxJd8wRV.js} +1 -1
- package/dist/web/assets/{branch-review-tab-G84Ojzae.js → branch-review-tab-CMTa2uSR.js} +1 -1
- package/dist/web/assets/chat-tab-BpdgqjSL.js +15 -0
- package/dist/web/assets/{code-editor-D04iUPsZ.js → code-editor-B7y7-5KE.js} +4 -4
- package/dist/web/assets/{codex-daily-guard-BSccLRGT.js → codex-daily-guard-ChDPiXDx.js} +1 -1
- package/dist/web/assets/{conflict-editor-C4ay676e.js → conflict-editor-Axs9Ad7A.js} +3 -3
- package/dist/web/assets/{csv-preview-DbwEmG7o.js → csv-preview-DTUAW2HW.js} +1 -1
- package/dist/web/assets/{database-viewer-S6LsALjX.js → database-viewer-qXDiWeXj.js} +1 -1
- package/dist/web/assets/{diff-viewer-3oBA7vgQ.js → diff-viewer-BtLiSpqe.js} +1 -1
- package/dist/web/assets/{docx-preview-CXuk-emm.js → docx-preview-Dxvy6h13.js} +1 -1
- package/dist/web/assets/{editor-language-service-DJmaKVY0.js → editor-language-service-D75GuLXP.js} +1 -1
- package/dist/web/assets/{explorer-body-BQ0jyAGv.js → explorer-body-xg1-MhlW.js} +2 -2
- package/dist/web/assets/{explorer-window-content-jdkWt34J.js → explorer-window-content-BeQocW3i.js} +1 -1
- package/dist/web/assets/extension-manager-section-Bm2v3P-n.js +1 -0
- package/dist/web/assets/{extension-webview-BGSDUbdK.js → extension-webview-CzxrAHyL.js} +1 -1
- package/dist/web/assets/{file-icons-BXdvggK2.js → file-icons-wS-OmEVu.js} +1 -1
- package/dist/web/assets/{file-store-ojgMXgAw.js → file-store-Ds3qJ4hC.js} +1 -1
- package/dist/web/assets/{files-settings-section-Gnyd7han.js → files-settings-section-Bd-_GeZU.js} +1 -1
- package/dist/web/assets/{format-file-meta-C77h04cZ.js → format-file-meta-PPi3ptkm.js} +1 -1
- package/dist/web/assets/{general-settings-section-V6Khh15V.js → general-settings-section-CfNPHQUk.js} +1 -1
- package/dist/web/assets/{git-log-panel-Bi513qjT.js → git-log-panel-CtGxPzH6.js} +1 -1
- package/dist/web/assets/{git-repo-store-88Z8v-pF.js → git-repo-store-BCEPfUGT.js} +1 -1
- package/dist/web/assets/{glide-data-grid-DnQwYSmQ.js → glide-data-grid-iSo2vP0q.js} +1 -1
- package/dist/web/assets/{group-chat-tab-DpczdwyV.js → group-chat-tab-D1lx0zz-.js} +1 -1
- package/dist/web/assets/{image-preview-CzCc4_Do.js → image-preview-DeGD0HJu.js} +1 -1
- package/dist/web/assets/index-CN0G8uYY.js +52 -0
- package/dist/web/assets/{jira-watcher-section-f2HUbGDY.js → jira-watcher-section-kyifZPTv.js} +1 -1
- package/dist/web/assets/keybindings-store-L5vV8DEJ.js +1 -0
- package/dist/web/assets/{keyboard-shortcuts-section-BpvVEw_Y.js → keyboard-shortcuts-section-D2uJq4x9.js} +1 -1
- package/dist/web/assets/markdown-renderer-BX1Q00sC.js +3 -0
- package/dist/web/assets/markdown-renderer-CLUux0vA.js +1 -0
- package/dist/web/assets/{media-url-yfqHpPz0.js → media-url-DKK0YHxL.js} +1 -1
- package/dist/web/assets/{mobile-explorer-sheet-Bol3XAO1.js → mobile-explorer-sheet-BHQDzpwK.js} +1 -1
- package/dist/web/assets/notification-store-BHgSy-ci.js +1 -0
- package/dist/web/assets/panel-store-D20Zuf3i.js +1 -0
- package/dist/web/assets/{pdf-preview-CmBI6E7d.js → pdf-preview-DAcfhfGm.js} +1 -1
- package/dist/web/assets/{postgres-viewer-8ZAqEALv.js → postgres-viewer-DPRsmgP5.js} +1 -1
- package/dist/web/assets/{ppmbot-settings-section-DKJUA3Kq.js → ppmbot-settings-section-B5N1jHgm.js} +1 -1
- package/dist/web/assets/{problems-panel-CFcoUx8h.js → problems-panel-D_wZ4_Qg.js} +1 -1
- package/dist/web/assets/{process-table-EKr2dqG6.js → process-table-DahflyQn.js} +1 -1
- package/dist/web/assets/{project-framework-store-B70Q3dNM.js → project-framework-store-ViZgce6y.js} +1 -1
- package/dist/web/assets/{project-store-B87hLRSk.js → project-store-hNvwfqX3.js} +1 -1
- package/dist/web/assets/{proxy-settings-section-B7qRVl8w.js → proxy-settings-section-CLg_nlxn.js} +1 -1
- package/dist/web/assets/{query-audit-section-By6qyqdB.js → query-audit-section-BrfSo0s_.js} +1 -1
- package/dist/web/assets/{remote-desktop-clipboard-notice-0WDYsyCA.js → remote-desktop-clipboard-notice-Fi6cieGM.js} +1 -1
- package/dist/web/assets/{remote-desktop-mobile-sheet-COYDg16H.js → remote-desktop-mobile-sheet-lLZ-oK73.js} +2 -2
- package/dist/web/assets/{remote-desktop-mobile-view-2DqSuS2U.js → remote-desktop-mobile-view-j3v-4rYa.js} +1 -1
- package/dist/web/assets/{remote-desktop-readiness-gate-Dm_qMJMH.js → remote-desktop-readiness-gate-CeLvcX_w.js} +1 -1
- package/dist/web/assets/{remote-desktop-window-content-UodhsF7W.js → remote-desktop-window-content-lwbkLsTC.js} +1 -1
- package/dist/web/assets/{run-in-terminal-CdefEe_R.js → run-in-terminal-D7W4IKb9.js} +1 -1
- package/dist/web/assets/{schedules-settings-section-bG2lYfGv.js → schedules-settings-section-C8OS0o80.js} +1 -1
- package/dist/web/assets/{send-to-chat-F207yH3u.js → send-to-chat-DNKhmHbi.js} +1 -1
- package/dist/web/assets/{settings-body-C06bFarv.js → settings-body-DgN22Z0W.js} +2 -2
- package/dist/web/assets/{settings-store-krC6bc79.js → settings-store-CsVSVgLp.js} +2 -2
- package/dist/web/assets/{settings-tab-34RSaASd.js → settings-tab-ChOs94iB.js} +1 -1
- package/dist/web/assets/{settings-window-content-Dr_2lmHH.js → settings-window-content-BnKMmg2a.js} +1 -1
- package/dist/web/assets/{sql-query-editor-BgRH0cHD.js → sql-query-editor-BJZIIQsm.js} +1 -1
- package/dist/web/assets/{sqlite-viewer-DUxGslpa.js → sqlite-viewer--cMeCZum.js} +1 -1
- package/dist/web/assets/{system-monitor-body-IZuLn7Qh.js → system-monitor-body-CXiIrn0N.js} +2 -2
- package/dist/web/assets/system-monitor-tab-BJKrTSl0.js +1 -0
- package/dist/web/assets/{system-monitor-window-content-CEaFISgj.js → system-monitor-window-content-Dy9fZJE3.js} +1 -1
- package/dist/web/assets/{tab-host-window-content-D0TN8Wrq.js → tab-host-window-content-BezqrAwC.js} +1 -1
- package/dist/web/assets/{tab-store-OJa1GPCq.js → tab-store-krAuHQ6_.js} +1 -1
- package/dist/web/assets/{team-member-sheet-DDPNcCjd.js → team-member-sheet-CVM2QC3H.js} +2 -2
- package/dist/web/assets/{team-member-window-content-DCiW_1-E.js → team-member-window-content-D4RYKplm.js} +1 -1
- package/dist/web/assets/{terminal-tab-4ypP0NDY.js → terminal-tab-jikhQLct.js} +3 -3
- package/dist/web/assets/{tool-cards-Dd6E7Q3k.js → tool-cards-D5jCQvqn.js} +2 -2
- package/dist/web/assets/{use-blob-url-CPtCcY3i.js → use-blob-url-DMGlPCQD.js} +1 -1
- package/dist/web/assets/{use-inline-blame-vrfFHuaR.js → use-inline-blame-BF8Y1KfV.js} +3 -3
- package/dist/web/assets/{use-lsp-CsuZu49X.js → use-lsp-Bx4oVtlk.js} +1 -1
- package/dist/web/assets/{use-monaco-theme-BIVYJBIn.js → use-monaco-theme-DHczXLMb.js} +1 -1
- package/dist/web/assets/{use-websocket-BMbufhX7.js → use-websocket-BWZkbleJ.js} +1 -1
- package/dist/web/assets/{video-preview-Byj8P_jA.js → video-preview-D191TvX9.js} +1 -1
- package/dist/web/assets/{window-pip-registry-yD6esSju.js → window-pip-registry-D1oXq-Dq.js} +1 -1
- package/dist/web/assets/ws-auth-BG-cdrQ8.js +1 -0
- package/dist/web/index.html +13 -13
- package/dist/web/sw.js +1 -1
- package/docs/architecture/ai-chat-and-providers.md +9 -0
- package/docs/architecture/workspace-and-ui.md +13 -0
- package/package.json +1 -1
- package/packages/ext-git-graph/src/webview-html.test.ts +30 -5
- package/packages/ext-git-graph/src/webview-html.ts +99 -31
- package/src/cli/commands/init.ts +1 -0
- package/src/providers/codex-app-server/codex-history.ts +26 -7
- package/src/providers/codex-app-server/codex-provider.ts +6 -4
- package/src/server/routes/chat.ts +1 -1
- package/src/server/routes/settings.ts +11 -5
- package/src/services/config.service.ts +2 -0
- package/src/services/edge-forwarder.ts +191 -191
- package/src/services/windows-process-tree.ts +351 -351
- package/src/shared/codex-daily-guard.ts +12 -5
- package/src/types/chat.ts +1 -1
- package/src/types/config.ts +12 -1
- package/src/web/components/chat/chat-tab.tsx +162 -38
- package/src/web/components/chat/message-input.tsx +24 -0
- package/src/web/components/chat/model-thinking-selector.tsx +25 -5
- package/src/web/components/chat/new-chat-provider-gate.tsx +68 -0
- package/src/web/components/extensions/extension-tree-view.tsx +4 -11
- package/src/web/components/layout/command-palette.tsx +2 -18
- package/src/web/components/layout/editor-panel.tsx +1 -1
- package/src/web/components/layout/reparenting-tab.tsx +4 -2
- package/src/web/components/layout/tab-bar.tsx +1 -1
- package/src/web/components/settings/accounts/account-card.tsx +2 -2
- package/src/web/components/settings/accounts/codex-accounts-section.tsx +4 -4
- package/src/web/components/settings/ai-settings-section.tsx +36 -0
- package/src/web/components/settings/extension-manager-section.tsx +8 -1
- package/src/web/hooks/use-draft.ts +25 -4
- package/src/web/hooks/use-usage.ts +6 -4
- package/src/web/lib/api-client.ts +7 -1
- package/src/web/lib/api-settings.ts +1 -0
- package/src/web/lib/extension-icons.ts +70 -0
- package/src/web/lib/new-chat-provider.ts +8 -0
- package/src/web/lib/tab-type-icons.ts +14 -0
- package/src/web/stores/panel-store.ts +46 -3
- package/dist/web/assets/accounts-settings-section-BVr9-FZJ.js +0 -1
- package/dist/web/assets/ai-settings-section-B1hQyjAd.js +0 -1
- package/dist/web/assets/ai-settings-section-X2UOfSaS.js +0 -1
- package/dist/web/assets/api-client-pQL53cDQ.js +0 -1
- package/dist/web/assets/chat-tab-DQJfjm8E.js +0 -15
- package/dist/web/assets/extension-manager-section-DG1guILi.js +0 -1
- package/dist/web/assets/index-DU68xk06.js +0 -52
- package/dist/web/assets/keybindings-store-DCRsnKg5.js +0 -1
- package/dist/web/assets/markdown-renderer-Bcaf9_bA.js +0 -1
- package/dist/web/assets/markdown-renderer-DGJp8HC3.js +0 -3
- package/dist/web/assets/notification-store-BXt54VIn.js +0 -1
- package/dist/web/assets/panel-store-CboGJAwh.js +0 -1
- package/dist/web/assets/system-monitor-tab-DiSA490Z.js +0 -1
- package/dist/web/assets/ws-auth-CEYVQ8NH.js +0 -1
- package/packages/vscode-compat/node_modules/.bin/tsc.bunx +0 -0
- package/packages/vscode-compat/node_modules/.bin/tsc.exe +0 -0
- package/packages/vscode-compat/node_modules/.bin/tsserver.bunx +0 -0
- package/packages/vscode-compat/node_modules/.bin/tsserver.exe +0 -0
- package/src/web/hooks/use-delayed-flag.ts +0 -35
|
@@ -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-Jn3njtNw.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-CN0G8uYY.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-DKK0YHxL.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 +1 @@
|
|
|
1
|
-
import{o as e}from"./rolldown-runtime-FhOqtrmT.js";import{C as t}from"./vendor-markdown-CuWCHIVb.js";import{f as n}from"./panel-store-
|
|
1
|
+
import{o as e}from"./rolldown-runtime-FhOqtrmT.js";import{C as t}from"./vendor-markdown-CuWCHIVb.js";import{f as n}from"./panel-store-D20Zuf3i.js";var r=e(t(),1),i=new Map,a=new Map,o=new Set;function s(e,t){t?i.set(e,t):i.delete(e);for(let e of o)e()}function c(e,t=2e3){let n=p(e);return n?Promise.resolve(n):new Promise(n=>{let r=e=>{o.delete(i),clearTimeout(a),n(e)},i=()=>{let t=p(e);t&&r(t)},a=setTimeout(()=>r(null),t);o.add(i)})}var l=new Set;function u(e){l.add(e)}function d(e){return l.has(e)}function f(e){l.delete(e)}function p(e){return i.get(e)??null}function m(e,t){if((a.get(e)??null)!==t){t?a.set(e,t):a.delete(e);for(let e of o)e()}}function h(e){return e?a.get(e)??null:null}function g(e){return o.add(e),()=>{o.delete(e)}}function _(e){return(0,r.useSyncExternalStore)(g,(0,r.useCallback)(()=>h(e),[e]))}function v(e){return _(n(e))?.pipWindow.document.body}export{m as a,c,s as i,h as l,d as n,v as o,u as r,_ as s,f as t,p as u};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{r as e}from"./api-client-Jn3njtNw.js";function t(t){let n=e();return!n||/[?&]token=/.test(t)?t:`${t}${t.includes(`?`)?`&`:`?`}token=${encodeURIComponent(n)}`}export{t};
|
package/dist/web/index.html
CHANGED
|
@@ -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-
|
|
12
|
+
<script type="module" crossorigin src="/assets/index-CN0G8uYY.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">
|
|
@@ -17,14 +17,14 @@
|
|
|
17
17
|
<link rel="modulepreload" crossorigin href="/assets/utils-Bmf_8h7Y.js">
|
|
18
18
|
<link rel="modulepreload" crossorigin href="/assets/button-B9CTrsEf.js">
|
|
19
19
|
<link rel="modulepreload" crossorigin href="/assets/createLucideIcon-DoiEKeJ_.js">
|
|
20
|
-
<link rel="modulepreload" crossorigin href="/assets/api-client-
|
|
20
|
+
<link rel="modulepreload" crossorigin href="/assets/api-client-Jn3njtNw.js">
|
|
21
21
|
<link rel="modulepreload" crossorigin href="/assets/react-Bghu0NUO.js">
|
|
22
|
-
<link rel="modulepreload" crossorigin href="/assets/settings-store-
|
|
23
|
-
<link rel="modulepreload" crossorigin href="/assets/file-store-
|
|
22
|
+
<link rel="modulepreload" crossorigin href="/assets/settings-store-CsVSVgLp.js">
|
|
23
|
+
<link rel="modulepreload" crossorigin href="/assets/file-store-Ds3qJ4hC.js">
|
|
24
24
|
<link rel="modulepreload" crossorigin href="/assets/window-store-UC1jJeLM.js">
|
|
25
|
-
<link rel="modulepreload" crossorigin href="/assets/panel-store-
|
|
26
|
-
<link rel="modulepreload" crossorigin href="/assets/window-pip-registry-
|
|
27
|
-
<link rel="modulepreload" crossorigin href="/assets/format-file-meta-
|
|
25
|
+
<link rel="modulepreload" crossorigin href="/assets/panel-store-D20Zuf3i.js">
|
|
26
|
+
<link rel="modulepreload" crossorigin href="/assets/window-pip-registry-D1oXq-Dq.js">
|
|
27
|
+
<link rel="modulepreload" crossorigin href="/assets/format-file-meta-PPi3ptkm.js">
|
|
28
28
|
<link rel="modulepreload" crossorigin href="/assets/portal-container-context-BarKmT4S.js">
|
|
29
29
|
<link rel="modulepreload" crossorigin href="/assets/icons-DQjqk0lJ.js">
|
|
30
30
|
<link rel="modulepreload" crossorigin href="/assets/context-menu-C6pIsf83.js">
|
|
@@ -34,13 +34,13 @@
|
|
|
34
34
|
<link rel="modulepreload" crossorigin href="/assets/mobile-bottom-sheet-C3TniEP-.js">
|
|
35
35
|
<link rel="modulepreload" crossorigin href="/assets/scroll-area-BzeiOd-B.js">
|
|
36
36
|
<link rel="modulepreload" crossorigin href="/assets/use-is-mobile-TkcwP1Gx.js">
|
|
37
|
-
<link rel="modulepreload" crossorigin href="/assets/project-framework-store-
|
|
38
|
-
<link rel="modulepreload" crossorigin href="/assets/file-icons-
|
|
39
|
-
<link rel="modulepreload" crossorigin href="/assets/git-repo-store-
|
|
40
|
-
<link rel="modulepreload" crossorigin href="/assets/project-store-
|
|
41
|
-
<link rel="modulepreload" crossorigin href="/assets/ws-auth-
|
|
37
|
+
<link rel="modulepreload" crossorigin href="/assets/project-framework-store-ViZgce6y.js">
|
|
38
|
+
<link rel="modulepreload" crossorigin href="/assets/file-icons-wS-OmEVu.js">
|
|
39
|
+
<link rel="modulepreload" crossorigin href="/assets/git-repo-store-BCEPfUGT.js">
|
|
40
|
+
<link rel="modulepreload" crossorigin href="/assets/project-store-hNvwfqX3.js">
|
|
41
|
+
<link rel="modulepreload" crossorigin href="/assets/ws-auth-BG-cdrQ8.js">
|
|
42
42
|
<link rel="modulepreload" crossorigin href="/assets/streaming-store-BYukdB56.js">
|
|
43
|
-
<link rel="modulepreload" crossorigin href="/assets/tab-store-
|
|
43
|
+
<link rel="modulepreload" crossorigin href="/assets/tab-store-krAuHQ6_.js">
|
|
44
44
|
<link rel="modulepreload" crossorigin href="/assets/apply-theme-CbR31K6I.js">
|
|
45
45
|
<link rel="modulepreload" crossorigin href="/assets/resolve-theme-B_ukrg_8.js">
|
|
46
46
|
<link rel="stylesheet" crossorigin href="/assets/index-BH99TIE0.css">
|
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":"206312c0035b4551edbf7f8f5cf4d80f","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-CN0G8uYY.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
|
|
@@ -2,6 +2,19 @@
|
|
|
2
2
|
|
|
3
3
|
> Part of the [PPM system architecture](../system-architecture.md).
|
|
4
4
|
|
|
5
|
+
## New Chat Provider
|
|
6
|
+
|
|
7
|
+
Settings → AI offers `Always use default provider` and `Follow last focused chat`.
|
|
8
|
+
`ai.default_provider` is the fixed choice or the fallback when the current project has
|
|
9
|
+
no focused chat. Fresh installations use follow-focus; existing configurations without
|
|
10
|
+
`ai.new_chat_provider_mode` retain default mode.
|
|
11
|
+
|
|
12
|
+
Focus memory is per project and browser session, across panels. Editors, terminals and
|
|
13
|
+
panel chrome do not replace it. New tabs snapshot the source at creation and resolve
|
|
14
|
+
settings before mounting chat or claiming an account. An unavailable provider prompts
|
|
15
|
+
for an available choice. Existing tabs, resumed sessions and explicit fork/clear
|
|
16
|
+
providers are preserved; changing the setting only affects new tabs.
|
|
17
|
+
|
|
5
18
|
## File Service & Filtering (Lazy-Load Tree, Palette Index)
|
|
6
19
|
|
|
7
20
|
**Component:** FileFilterService + API endpoints `/files/list`, `/files/index`, settings endpoints
|
package/package.json
CHANGED
|
@@ -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("
|
|
593
|
-
//
|
|
594
|
-
//
|
|
595
|
-
|
|
596
|
-
|
|
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-
|
|
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
|
-
/*
|
|
378
|
-
the
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
.
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
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
|
|
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
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
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
|
|
2076
|
-
*
|
|
2077
|
-
*
|
|
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 =
|
|
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
|
-
|
|
2087
|
-
|
|
2088
|
-
|
|
2089
|
-
|
|
2090
|
-
|
|
2091
|
-
|
|
2092
|
-
if (
|
|
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) {
|
package/src/cli/commands/init.ts
CHANGED
|
@@ -155,6 +155,7 @@ export async function initProject(options: InitOptions = {}) {
|
|
|
155
155
|
configService.set("auth", { enabled: authEnabled, token: authToken });
|
|
156
156
|
configService.set("ai", {
|
|
157
157
|
default_provider: "claude",
|
|
158
|
+
new_chat_provider_mode: configService.get("ai").new_chat_provider_mode,
|
|
158
159
|
providers: {
|
|
159
160
|
claude: {
|
|
160
161
|
type: "agent-sdk",
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import type { ChatMessage, ChatEvent, SessionInfo } from "../provider.interface.ts";
|
|
2
2
|
import { stripSharedContext } from "../../shared/provider-context.ts";
|
|
3
|
-
import { readdirSync, readFileSync, statSync } from "node:fs";
|
|
3
|
+
import { readdirSync, readFileSync, statSync, realpathSync } from "node:fs";
|
|
4
4
|
import { join, resolve } from "node:path";
|
|
5
5
|
import { homedir } from "node:os";
|
|
6
|
+
import { getPpmDir } from "../../services/ppm-dir.ts";
|
|
6
7
|
import { redactTruncate } from "./codex-redact.ts";
|
|
7
8
|
import { parseApplyPatch, changeToToolUse } from "./codex-patch.ts";
|
|
8
9
|
import { mapRolloutItem } from "./codex-rollout-items.ts";
|
|
@@ -449,14 +450,27 @@ export function getRolloutMessages(sessionsDir: string, threadId: string, reques
|
|
|
449
450
|
|
|
450
451
|
/** True when a path points at a codex rollout in the ambient or a PPM account home. */
|
|
451
452
|
export function isCodexRolloutPath(p: string): boolean {
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
453
|
+
return withinCodexSessions(p, false);
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
function withinCodexSessions(p: string, canonical: boolean): boolean {
|
|
457
|
+
const normalize = (value: string) => process.platform === "win32" ? normPath(value).replace(/\\/g, "/") : normPath(value);
|
|
458
|
+
const n = normalize(p);
|
|
459
|
+
if (!n.endsWith(".jsonl")) return false;
|
|
460
|
+
const rootPath = (value: string) => {
|
|
461
|
+
if (canonical) { try { return normalize(realpathSync(value)); } catch { return null; } }
|
|
462
|
+
return normalize(value);
|
|
463
|
+
};
|
|
464
|
+
const ambientRoots = [join(homedir(), ".codex", "sessions")];
|
|
465
|
+
if (process.env.CODEX_HOME) ambientRoots.push(join(process.env.CODEX_HOME, "sessions"));
|
|
466
|
+
if (ambientRoots.some((value) => { const root = rootPath(value); return root && n.startsWith(root + "/"); })) return true;
|
|
467
|
+
const managed = rootPath(join(getPpmDir(), "codex-accounts"));
|
|
468
|
+
return !!managed && n.startsWith(managed + "/") && /^[^/]+\/sessions\/.+/.test(n.slice(managed.length + 1));
|
|
456
469
|
}
|
|
457
470
|
|
|
458
471
|
/**
|
|
459
|
-
* One pre-compact segment for the "load more" feature. Jails to
|
|
472
|
+
* One pre-compact segment for the "load more" feature. Jails to ambient,
|
|
473
|
+
* CODEX_HOME, or PPM managed-account session directories via real paths;
|
|
460
474
|
* fail-closed on cwd.
|
|
461
475
|
*
|
|
462
476
|
* One segment per request rather than everything before the first boundary, which is
|
|
@@ -468,7 +482,12 @@ export function isCodexRolloutPath(p: string): boolean {
|
|
|
468
482
|
*/
|
|
469
483
|
export function getCodexPreCompactMessages(file: string, requestedCwd?: string, beforeId?: string): ChatMessage[] {
|
|
470
484
|
if (!isCodexRolloutPath(file)) throw new Error("Access denied: not a codex rollout");
|
|
471
|
-
|
|
485
|
+
let resolved: string;
|
|
486
|
+
try { resolved = realpathSync(resolve(file)); } catch { throw new Error("File not found"); }
|
|
487
|
+
if (!withinCodexSessions(resolved, true)) throw new Error("Access denied: transcript outside Codex sessions");
|
|
488
|
+
const info = statSync(resolved);
|
|
489
|
+
if (!info.isFile()) throw new Error("Not a regular file");
|
|
490
|
+
if (info.size > 256 * 1024 * 1024) throw new Error("Transcript too large");
|
|
472
491
|
let text: string;
|
|
473
492
|
try { text = readFileSync(resolved, "utf-8"); } catch { throw new Error("File not found"); }
|
|
474
493
|
// Read once and reused below. `readSessionMeta` opens and reads the whole rollout again, and
|
|
@@ -1147,12 +1147,14 @@ export class CodexAppServerProvider implements AIProvider {
|
|
|
1147
1147
|
}
|
|
1148
1148
|
|
|
1149
1149
|
/** Read the session's account without advancing the account-selection strategy. */
|
|
1150
|
-
async getUsage(sessionId?: string): Promise<UsageInfo> {
|
|
1150
|
+
async getUsage(sessionId?: string, pickedAccountId?: string): Promise<UsageInfo> {
|
|
1151
1151
|
// Idempotent, and needed because a caller can reach the provider before the
|
|
1152
1152
|
// server has started background polling — an unregistered source would make
|
|
1153
1153
|
// the shared layer answer {} instead of reading codex.
|
|
1154
1154
|
registerUsageSource(codexUsageSource);
|
|
1155
|
-
|
|
1155
|
+
// An unopened chat has a claimed account but no session binding yet.
|
|
1156
|
+
// Read that exact account without advancing the selection strategy.
|
|
1157
|
+
const accountId = sessionId ? getSessionCodexAccount(sessionId) : pickedAccountId ?? null;
|
|
1156
1158
|
const bound = accountId ? getCodexAccount(accountId) : null;
|
|
1157
1159
|
if (bound) {
|
|
1158
1160
|
// Through the shared layer, so this answers from the cache or the stored
|
|
@@ -1166,12 +1168,12 @@ export class CodexAppServerProvider implements AIProvider {
|
|
|
1166
1168
|
};
|
|
1167
1169
|
}
|
|
1168
1170
|
|
|
1169
|
-
//
|
|
1171
|
+
// No binding or explicit tab claim — a session binds on its first send. Name the account
|
|
1170
1172
|
// that will serve it, but do NOT read its quota: that spawns an app-server
|
|
1171
1173
|
// against a login which is not yet this session's, and which a round-robin
|
|
1172
1174
|
// or lowest-usage pick may never hand it. So the toolbar can say WHO will
|
|
1173
1175
|
// answer without PPM touching that account on a session's behalf before
|
|
1174
|
-
// the session owns it.
|
|
1176
|
+
// the session owns it. Quota is read once a tab claims it or a session binds it.
|
|
1175
1177
|
//
|
|
1176
1178
|
// Skipped when the session names an account that no longer exists: naming
|
|
1177
1179
|
// a different one there would be a lie about a binding that already failed.
|
|
@@ -135,7 +135,7 @@ chatRoutes.get("/usage", async (c) => {
|
|
|
135
135
|
const { invalidateUsage } = await import("../../services/provider-usage/usage-registry.ts");
|
|
136
136
|
invalidateUsage(providerId);
|
|
137
137
|
}
|
|
138
|
-
try { return c.json(ok(await provider.getUsage(c.req.query("session")))); } catch { return c.json(ok({})); }
|
|
138
|
+
try { return c.json(ok(await provider.getUsage(c.req.query("session"), c.req.query("accountId")))); } catch { return c.json(ok({})); }
|
|
139
139
|
}
|
|
140
140
|
return c.json(ok({}));
|
|
141
141
|
}
|