@hienlh/ppm 0.13.76 → 0.13.78
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/.opencode/.env.example +98 -0
- package/.opencode/skills/ads-management/scripts/.env.example +13 -0
- package/.opencode/skills/ai-multimodal/.env.example +230 -0
- package/.opencode/skills/cip-design/.env.example +6 -0
- package/.opencode/skills/devops/.env.example +76 -0
- package/.opencode/skills/docs-seeker/.env.example +15 -0
- package/.opencode/skills/elevenlabs/.env.example +3 -0
- package/.opencode/skills/marketing-dashboard/.env.example +15 -0
- package/.opencode/skills/marketing-dashboard/app/.env.example +2 -0
- package/.opencode/skills/marketing-dashboard/server/.env.example +2 -0
- package/.opencode/skills/mcp-management/scripts/dist/analyze-tools.js +70 -0
- package/.opencode/skills/mcp-management/scripts/dist/cli.js +160 -0
- package/.opencode/skills/mcp-management/scripts/dist/mcp-client.js +183 -0
- package/.opencode/skills/payment-integration/scripts/.env.example +20 -0
- package/.opencode/skills/sequential-thinking/.env.example +8 -0
- package/CHANGELOG.md +10 -0
- 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 -7
- package/dist/web/assets/{api-settings-Byph7lae.js → api-settings-BJTjIG4U.js} +1 -1
- package/dist/web/assets/architecture-PBZL5I3N-CkdUQjA_.js +1 -0
- package/dist/web/assets/{audio-preview-DXCxll7f.js → audio-preview-DFrv27cv.js} +1 -1
- package/dist/web/assets/chat-tab-DNmhvaZ_.js +16 -0
- package/dist/web/assets/code-editor-CHwXYDhx.js +10 -0
- package/dist/web/assets/{conflict-editor-RMsNwUKp.js → conflict-editor-DGm0Z6Mc.js} +1 -1
- package/dist/web/assets/{csv-preview-CwEbP_iZ.js → csv-preview-asMfgR0r.js} +1 -1
- package/dist/web/assets/{data-grid-overlay-editor-C36FRqE8.js → data-grid-overlay-editor-DGjqvYn6.js} +1 -1
- package/dist/web/assets/database-viewer-D1nO6a11.js +1 -0
- package/dist/web/assets/{diff-viewer--SSMwMoS.js → diff-viewer-Blji3pAc.js} +1 -1
- package/dist/web/assets/{docx-preview-BL398ELS.js → docx-preview-BRpopR6E.js} +1 -1
- package/dist/web/assets/{esm-DH3rpl0I.js → esm-xVTUq__o.js} +1 -1
- package/dist/web/assets/{extension-webview-DrnDwQpM.js → extension-webview-BXeDxyVt.js} +2 -2
- package/dist/web/assets/git-log-panel-B5n35kot.js +1 -0
- package/dist/web/assets/gitGraph-HDMCJU4V-D3UR56AG.js +1 -0
- package/dist/web/assets/glide-data-grid-4mwS1Swl.js +138 -0
- package/dist/web/assets/{image-preview-DeNH71Ez.js → image-preview-Bu5XcdqW.js} +1 -1
- package/dist/web/assets/index-CuOntRL_.js +27 -0
- package/dist/web/assets/info-3K5VOQVL-DUhLSKI2.js +1 -0
- package/dist/web/assets/{input-DSELw5zU.js → input-CArJe9WS.js} +1 -1
- package/dist/web/assets/keybindings-store-Clt4mfff.js +1 -0
- package/dist/web/assets/{markdown-renderer-D5B629qw.js → markdown-renderer-Be-gcsCi.js} +3 -3
- package/dist/web/assets/notification-store-B0D4A68q.js +1 -0
- package/dist/web/assets/{number-overlay-editor-JsUdft7z.js → number-overlay-editor-DtUBprPW.js} +1 -1
- package/dist/web/assets/packet-RMMSAZCW-BIpeVUGW.js +1 -0
- package/dist/web/assets/{panel-store-DlvwzOll.js → panel-store-C9VAhbZz.js} +1 -1
- package/dist/web/assets/{pdf-preview-yUMARG8r.js → pdf-preview-hiA6Dkic.js} +1 -1
- package/dist/web/assets/pie-UPGHQEXC-CNoizzjb.js +1 -0
- package/dist/web/assets/port-forwarding-tab-DTPLT4nk.js +1 -0
- package/dist/web/assets/{postgres-viewer-C28tRuh5.js → postgres-viewer-LimIiFby.js} +3 -3
- package/dist/web/assets/{project-store-CpC02pIv.js → project-store-DlbHpIq0.js} +1 -1
- package/dist/web/assets/radar-KQ55EAFF-7dns-ho5.js +1 -0
- package/dist/web/assets/{settings-store-MXJgFUnl.js → settings-store-DQUFTPk2.js} +2 -2
- package/dist/web/assets/settings-tab-B1wiEtFH.js +1 -0
- package/dist/web/assets/sql-query-editor-DGcroNAs.js +1 -0
- package/dist/web/assets/sqlite-viewer-DIfCI2va.js +1 -0
- package/dist/web/assets/system-monitor-tab-CIVm3sgY.js +1 -0
- package/dist/web/assets/{tab-store-Bdw8DIbZ.js → tab-store-CIcbSn0c.js} +1 -1
- package/dist/web/assets/{terminal-tab-B1_sAuIi.js → terminal-tab-Dj9xDdbc.js} +2 -2
- package/dist/web/assets/treemap-KZPCXAKY-D3DZCLoE.js +1 -0
- package/dist/web/assets/{use-blob-url-CBi0HMq5.js → use-blob-url-DrPfBQBM.js} +1 -1
- package/dist/web/assets/{use-monaco-theme-CbzQcrwD.js → use-monaco-theme-BLIgarH5.js} +1 -1
- package/dist/web/assets/{vendor-mermaid-D2cOxeao.js → vendor-mermaid-DkqjpqJK.js} +3 -3
- package/dist/web/assets/{video-preview-D-nAiQsv.js → video-preview-CnRJmbG8.js} +1 -1
- package/dist/web/index.html +17 -20
- package/dist/web/sw.js +1 -1
- package/package.json +1 -1
- package/src/index.ts +0 -0
- package/src/server/index.ts +0 -2
- package/src/services/cloud-ws.service.ts +27 -1
- package/src/services/config.service.ts +1 -1
- package/src/services/db.service.ts +0 -24
- package/src/services/notification.service.ts +14 -5
- package/src/types/config.ts +0 -7
- package/src/web/components/database/sql-completion-provider.ts +28 -1
- package/src/web/components/database/sql-query-editor.tsx +1 -30
- package/src/web/components/editor/code-editor.tsx +14 -1
- package/src/web/components/settings/settings-tab.tsx +12 -66
- package/src/web/sw.ts +0 -45
- package/bun.lock +0 -2142
- package/bunfig.toml +0 -2
- package/dist/web/assets/ai-settings-section-D0VMZ4aE.js +0 -1
- package/dist/web/assets/architecture-PBZL5I3N-DyeqgxGw.js +0 -1
- package/dist/web/assets/chat-tab-D5j5gP5j.js +0 -16
- package/dist/web/assets/code-editor-CL2gcvDj.js +0 -10
- package/dist/web/assets/database-viewer-2TbU0m7s.js +0 -1
- package/dist/web/assets/git-log-panel-u6ehykcl.js +0 -1
- package/dist/web/assets/gitGraph-HDMCJU4V-CZAWeLUi.js +0 -1
- package/dist/web/assets/glide-data-grid-Benw7NI4.js +0 -136
- package/dist/web/assets/globe-CQ8NAYvi.js +0 -1
- package/dist/web/assets/index-BS3CQIT3.js +0 -27
- package/dist/web/assets/info-3K5VOQVL-BqVOLnRc.js +0 -1
- package/dist/web/assets/keybindings-store-gFa7vUoe.js +0 -1
- package/dist/web/assets/notification-store-qViiZZaY.js +0 -1
- package/dist/web/assets/packet-RMMSAZCW-BGMrAgbD.js +0 -1
- package/dist/web/assets/pie-UPGHQEXC-9IRPAyAe.js +0 -1
- package/dist/web/assets/port-forwarding-tab-D7rVcasa.js +0 -1
- package/dist/web/assets/radar-KQ55EAFF-CxjdSb6M.js +0 -1
- package/dist/web/assets/refresh-cw-CRD2qr4U.js +0 -1
- package/dist/web/assets/settings-tab-0kWZtlCi.js +0 -1
- package/dist/web/assets/sql-query-editor-DCx7kPlY.js +0 -3
- package/dist/web/assets/sqlite-viewer-W1RhaCr0.js +0 -1
- package/dist/web/assets/system-monitor-tab-CJojQd3x.js +0 -1
- package/dist/web/assets/treemap-KZPCXAKY-BYrmfSj5.js +0 -1
- package/src/server/routes/push.ts +0 -54
- package/src/services/push-notification.service.ts +0 -104
- package/src/web/hooks/use-push-notification.ts +0 -114
- /package/dist/web/assets/{api-client-DG9qwosT.js → api-client-BK4NPNoY.js} +0 -0
- /package/dist/web/assets/{chevron-down-BMo4cBth.js → chevron-down-CiFNPrfI.js} +0 -0
- /package/dist/web/assets/{chevron-right-CD8e6Aj4.js → chevron-right-BzAdxJRG.js} +0 -0
- /package/dist/web/assets/{code-DiNmA3eR.js → code-CuravVys.js} +0 -0
- /package/dist/web/assets/{csv-parser-B_TuHmnd.js → csv-parser-D1b_lg2T.js} +0 -0
- /package/dist/web/assets/{data-grid-types-CO_3iSwd.js → data-grid-types-DzL5W2em.js} +0 -0
- /package/dist/web/assets/{database-Dc8mr-dP.js → database-NmqHg29g.js} +0 -0
- /package/dist/web/assets/{dist-D4dFaZkK.js → dist-BM2EHhLH.js} +0 -0
- /package/dist/web/assets/{dist-C1jciI67.js → dist-CohudVKa.js} +0 -0
- /package/dist/web/assets/{file-exclamation-point-B__2Hrd6.js → file-exclamation-point-Baz81y5z.js} +0 -0
- /package/dist/web/assets/{katex-DveWxdWJ.js → katex-CHaeM9QC.js} +0 -0
- /package/dist/web/assets/{lib-D4YDpYv4.js → lib-LPmTkMu4.js} +0 -0
- /package/dist/web/assets/{react-BXxixfbh.js → react-DHBl6KRc.js} +0 -0
- /package/dist/web/assets/{search-D90WJ5fo.js → search-BEy08Exr.js} +0 -0
- /package/dist/web/assets/{shield-check-DeIMQtEj.js → shield-check-77W0OMbn.js} +0 -0
- /package/dist/web/assets/{shield-off-D4jBmG5E.js → shield-off-C_MK1u09.js} +0 -0
- /package/dist/web/assets/{sparkles-DyeiGE7Q.js → sparkles-CulWHe4c.js} +0 -0
- /package/dist/web/assets/{table-DCYlHUNQ.js → table-BzjWcs87.js} +0 -0
- /package/dist/web/assets/{text-wrap-B3mYv9Yo.js → text-wrap-DJz9Bgpa.js} +0 -0
- /package/dist/web/assets/{trash-2-DkIfBY8d.js → trash-2-D5P4y8p_.js} +0 -0
- /package/dist/web/assets/{utils-Bs_TFEQf.js → utils-CSCvNZxE.js} +0 -0
- /package/dist/web/assets/{vendor-xterm-BHJtSw6L.js → vendor-xterm-t3d5xZdz.js} +0 -0
- /package/dist/web/assets/{wifi-DifNnmbA.js → wifi-CgM9T6HR.js} +0 -0
- /package/dist/web/assets/{x-WwAMX3EB.js → x-Dx3jsRgu.js} +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
import{b as e}from"./vendor-markdown-0Mxgxy0L.js";import{t}from"./file-exclamation-point-
|
|
1
|
+
import{b as e}from"./vendor-markdown-0Mxgxy0L.js";import{t}from"./file-exclamation-point-Baz81y5z.js";import"./api-client-BK4NPNoY.js";import{pt as n}from"./index-CuOntRL_.js";import{t as r}from"./use-blob-url-DrPfBQBM.js";var i=e();function a({filePath:e,projectName:a}){let{blobUrl:o,error:s}=r(e,a);return s?(0,i.jsxs)(`div`,{className:`flex flex-col items-center justify-center h-full gap-3 text-text-secondary`,children:[(0,i.jsx)(t,{className:`size-10 text-text-subtle`}),(0,i.jsx)(`p`,{className:`text-sm`,children:`Failed to load video.`})]}):o?(0,i.jsx)(`div`,{className:`flex items-center justify-center h-full p-4 bg-surface overflow-auto`,children:(0,i.jsx)(`video`,{src:o,controls:!0,className:`max-w-full max-h-full`})}):(0,i.jsx)(`div`,{className:`flex items-center justify-center h-full`,children:(0,i.jsx)(n,{className:`size-5 animate-spin text-text-subtle`})})}export{a as VideoPreview};
|
package/dist/web/index.html
CHANGED
|
@@ -39,31 +39,28 @@
|
|
|
39
39
|
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
|
40
40
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
|
41
41
|
<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" />
|
|
42
|
-
<script type="module" crossorigin src="/assets/index-
|
|
42
|
+
<script type="module" crossorigin src="/assets/index-CuOntRL_.js"></script>
|
|
43
43
|
<link rel="modulepreload" crossorigin href="/assets/rolldown-runtime-FhOqtrmT.js">
|
|
44
|
-
<link rel="modulepreload" crossorigin href="/assets/vendor-mermaid-
|
|
44
|
+
<link rel="modulepreload" crossorigin href="/assets/vendor-mermaid-DkqjpqJK.js">
|
|
45
45
|
<link rel="modulepreload" crossorigin href="/assets/vendor-markdown-0Mxgxy0L.js">
|
|
46
46
|
<link rel="modulepreload" crossorigin href="/assets/vendor-ui-UXCWAcmi.js">
|
|
47
|
-
<link rel="modulepreload" crossorigin href="/assets/utils-
|
|
47
|
+
<link rel="modulepreload" crossorigin href="/assets/utils-CSCvNZxE.js">
|
|
48
48
|
<link rel="modulepreload" crossorigin href="/assets/createLucideIcon-BjHrJDVb.js">
|
|
49
|
-
<link rel="modulepreload" crossorigin href="/assets/x-
|
|
50
|
-
<link rel="modulepreload" crossorigin href="/assets/input-
|
|
51
|
-
<link rel="modulepreload" crossorigin href="/assets/react-
|
|
52
|
-
<link rel="modulepreload" crossorigin href="/assets/api-client-
|
|
53
|
-
<link rel="modulepreload" crossorigin href="/assets/settings-store-
|
|
49
|
+
<link rel="modulepreload" crossorigin href="/assets/x-Dx3jsRgu.js">
|
|
50
|
+
<link rel="modulepreload" crossorigin href="/assets/input-CArJe9WS.js">
|
|
51
|
+
<link rel="modulepreload" crossorigin href="/assets/react-DHBl6KRc.js">
|
|
52
|
+
<link rel="modulepreload" crossorigin href="/assets/api-client-BK4NPNoY.js">
|
|
53
|
+
<link rel="modulepreload" crossorigin href="/assets/settings-store-DQUFTPk2.js">
|
|
54
54
|
<link rel="modulepreload" crossorigin href="/assets/eye-off-BacF7RVS.js">
|
|
55
|
-
<link rel="modulepreload" crossorigin href="/assets/chevron-down-
|
|
56
|
-
<link rel="modulepreload" crossorigin href="/assets/
|
|
57
|
-
<link rel="modulepreload" crossorigin href="/assets/
|
|
58
|
-
<link rel="modulepreload" crossorigin href="/assets/
|
|
59
|
-
<link rel="modulepreload" crossorigin href="/assets/
|
|
60
|
-
<link rel="modulepreload" crossorigin href="/assets/
|
|
61
|
-
<link rel="modulepreload" crossorigin href="/assets/
|
|
62
|
-
<link rel="modulepreload" crossorigin href="/assets/
|
|
63
|
-
<link rel="modulepreload" crossorigin href="/assets/
|
|
64
|
-
<link rel="modulepreload" crossorigin href="/assets/panel-store-DlvwzOll.js">
|
|
65
|
-
<link rel="modulepreload" crossorigin href="/assets/project-store-CpC02pIv.js">
|
|
66
|
-
<link rel="modulepreload" crossorigin href="/assets/tab-store-Bdw8DIbZ.js">
|
|
55
|
+
<link rel="modulepreload" crossorigin href="/assets/chevron-down-CiFNPrfI.js">
|
|
56
|
+
<link rel="modulepreload" crossorigin href="/assets/database-NmqHg29g.js">
|
|
57
|
+
<link rel="modulepreload" crossorigin href="/assets/chevron-right-BzAdxJRG.js">
|
|
58
|
+
<link rel="modulepreload" crossorigin href="/assets/search-BEy08Exr.js">
|
|
59
|
+
<link rel="modulepreload" crossorigin href="/assets/trash-2-D5P4y8p_.js">
|
|
60
|
+
<link rel="modulepreload" crossorigin href="/assets/api-settings-BJTjIG4U.js">
|
|
61
|
+
<link rel="modulepreload" crossorigin href="/assets/panel-store-C9VAhbZz.js">
|
|
62
|
+
<link rel="modulepreload" crossorigin href="/assets/project-store-DlbHpIq0.js">
|
|
63
|
+
<link rel="modulepreload" crossorigin href="/assets/tab-store-CIcbSn0c.js">
|
|
67
64
|
<link rel="stylesheet" crossorigin href="/assets/index-fyMt5gpO.css">
|
|
68
65
|
<link rel="manifest" href="/manifest.webmanifest"><script id="vite-plugin-pwa:register-sw" src="/registerSW.js"></script></head>
|
|
69
66
|
<body class="bg-[#0f1419] text-[#e5e7eb] font-sans antialiased">
|
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))}function B(e){O().precache(e)}function V(e,t){B(e),z(t)}V([{"revision":"1872c500de691dce40960bb85481de07","url":"registerSW.js"},{"revision":"71f8ebcbe9a661db4591c19ba9a24294","url":"index.html"},{"revision":"a0fb34fc84eb148d51812cd62669f20d","url":"icon-512.svg"},{"revision":"a0fb34fc84eb148d51812cd62669f20d","url":"icon-192.svg"},{"revision":"948e060affb598c339be40d69e1f6f9c","url":"monacoeditorwork/ts.worker.bundle.js"},{"revision":"a5d8a1acfc29c2a4c882a54ffc93def3","url":"monacoeditorwork/json.worker.bundle.js"},{"revision":"d0f94ce046cf8cf09605ee7664dac557","url":"monacoeditorwork/html.worker.bundle.js"},{"revision":"a424156a79b9c1b907db93aa3180585a","url":"monacoeditorwork/editor.worker.bundle.js"},{"revision":"b3a7f967560c9816492a1567b3f7f0dc","url":"monacoeditorwork/css.worker.bundle.js"},{"revision":null,"url":"assets/x-WwAMX3EB.js"},{"revision":null,"url":"assets/wifi-DifNnmbA.js"},{"revision":null,"url":"assets/video-preview-D-nAiQsv.js"},{"revision":null,"url":"assets/vendor-xterm-BrP-ENHg.css"},{"revision":null,"url":"assets/vendor-xterm-BHJtSw6L.js"},{"revision":null,"url":"assets/vendor-ui-UXCWAcmi.js"},{"revision":null,"url":"assets/vendor-mermaid-D2cOxeao.js"},{"revision":null,"url":"assets/vendor-markdown-0Mxgxy0L.js"},{"revision":null,"url":"assets/utils-Bs_TFEQf.js"},{"revision":null,"url":"assets/use-monaco-theme-CbzQcrwD.js"},{"revision":null,"url":"assets/use-blob-url-CBi0HMq5.js"},{"revision":null,"url":"assets/treemap-KZPCXAKY-BYrmfSj5.js"},{"revision":null,"url":"assets/trash-2-DkIfBY8d.js"},{"revision":null,"url":"assets/text-wrap-B3mYv9Yo.js"},{"revision":null,"url":"assets/terminal-tab-B1_sAuIi.js"},{"revision":null,"url":"assets/table-DCYlHUNQ.js"},{"revision":null,"url":"assets/tab-store-Bdw8DIbZ.js"},{"revision":null,"url":"assets/system-monitor-tab-CJojQd3x.js"},{"revision":null,"url":"assets/sqlite-viewer-W1RhaCr0.js"},{"revision":null,"url":"assets/sql-query-editor-DCx7kPlY.js"},{"revision":null,"url":"assets/sparkles-DyeiGE7Q.js"},{"revision":null,"url":"assets/shield-off-D4jBmG5E.js"},{"revision":null,"url":"assets/shield-check-DeIMQtEj.js"},{"revision":null,"url":"assets/settings-tab-0kWZtlCi.js"},{"revision":null,"url":"assets/settings-store-MXJgFUnl.js"},{"revision":null,"url":"assets/search-D90WJ5fo.js"},{"revision":null,"url":"assets/rolldown-runtime-FhOqtrmT.js"},{"revision":null,"url":"assets/refresh-cw-CRD2qr4U.js"},{"revision":null,"url":"assets/react-BXxixfbh.js"},{"revision":null,"url":"assets/radar-KQ55EAFF-CxjdSb6M.js"},{"revision":null,"url":"assets/project-store-CpC02pIv.js"},{"revision":null,"url":"assets/postgres-viewer-C28tRuh5.js"},{"revision":null,"url":"assets/port-forwarding-tab-D7rVcasa.js"},{"revision":null,"url":"assets/pie-UPGHQEXC-9IRPAyAe.js"},{"revision":null,"url":"assets/pdf-preview-yUMARG8r.js"},{"revision":null,"url":"assets/panel-store-DlvwzOll.js"},{"revision":null,"url":"assets/packet-RMMSAZCW-BGMrAgbD.js"},{"revision":null,"url":"assets/number-overlay-editor-JsUdft7z.js"},{"revision":null,"url":"assets/notification-store-qViiZZaY.js"},{"revision":null,"url":"assets/markdown-renderer-D5B629qw.js"},{"revision":null,"url":"assets/lib-D4YDpYv4.js"},{"revision":null,"url":"assets/keybindings-store-gFa7vUoe.js"},{"revision":null,"url":"assets/katex-DveWxdWJ.js"},{"revision":null,"url":"assets/input-DSELw5zU.js"},{"revision":null,"url":"assets/info-3K5VOQVL-BqVOLnRc.js"},{"revision":null,"url":"assets/index-fyMt5gpO.css"},{"revision":null,"url":"assets/index-BS3CQIT3.js"},{"revision":null,"url":"assets/image-preview-DeNH71Ez.js"},{"revision":null,"url":"assets/globe-CQ8NAYvi.js"},{"revision":null,"url":"assets/glide-data-grid-nthEL3fk.css"},{"revision":null,"url":"assets/glide-data-grid-Benw7NI4.js"},{"revision":null,"url":"assets/github.min-D2BCvnWf.css"},{"revision":null,"url":"assets/github-dark-dimmed.min-BrpRStFV.css"},{"revision":null,"url":"assets/gitGraph-HDMCJU4V-CZAWeLUi.js"},{"revision":null,"url":"assets/git-log-panel-u6ehykcl.js"},{"revision":null,"url":"assets/file-exclamation-point-B__2Hrd6.js"},{"revision":null,"url":"assets/eye-off-BacF7RVS.js"},{"revision":null,"url":"assets/extension-webview-DrnDwQpM.js"},{"revision":null,"url":"assets/esm-DH3rpl0I.js"},{"revision":null,"url":"assets/docx-preview-BL398ELS.js"},{"revision":null,"url":"assets/dist-D4dFaZkK.js"},{"revision":null,"url":"assets/dist-C1jciI67.js"},{"revision":null,"url":"assets/diff-viewer--SSMwMoS.js"},{"revision":null,"url":"assets/database-viewer-2TbU0m7s.js"},{"revision":null,"url":"assets/database-Dc8mr-dP.js"},{"revision":null,"url":"assets/data-grid-types-CO_3iSwd.js"},{"revision":null,"url":"assets/data-grid-overlay-editor-C36FRqE8.js"},{"revision":null,"url":"assets/csv-preview-CwEbP_iZ.js"},{"revision":null,"url":"assets/csv-parser-B_TuHmnd.js"},{"revision":null,"url":"assets/createLucideIcon-BjHrJDVb.js"},{"revision":null,"url":"assets/conflict-editor-RMsNwUKp.js"},{"revision":null,"url":"assets/code-editor-CL2gcvDj.js"},{"revision":null,"url":"assets/code-DiNmA3eR.js"},{"revision":null,"url":"assets/chevron-right-CD8e6Aj4.js"},{"revision":null,"url":"assets/chevron-down-BMo4cBth.js"},{"revision":null,"url":"assets/chat-tab-D5j5gP5j.js"},{"revision":null,"url":"assets/audio-preview-DXCxll7f.js"},{"revision":null,"url":"assets/arrow-up-Rcw6_KKu.js"},{"revision":null,"url":"assets/arrow-down-D825m4vm.js"},{"revision":null,"url":"assets/architecture-PBZL5I3N-DyeqgxGw.js"},{"revision":null,"url":"assets/api-settings-Byph7lae.js"},{"revision":null,"url":"assets/api-client-DG9qwosT.js"},{"revision":null,"url":"assets/ai-settings-section-D0VMZ4aE.js"},{"revision":null,"url":"assets/KaTeX_Typewriter-Regular-CO6r4hn1.woff2"},{"revision":null,"url":"assets/KaTeX_Size4-Regular-Dl5lxZxV.woff2"},{"revision":null,"url":"assets/KaTeX_Size2-Regular-Dy4dx90m.woff2"},{"revision":null,"url":"assets/KaTeX_Size1-Regular-mCD8mA8B.woff2"},{"revision":null,"url":"assets/KaTeX_Script-Regular-D3wIWfF6.woff2"},{"revision":null,"url":"assets/KaTeX_SansSerif-Regular-DDBCnlJ7.woff2"},{"revision":null,"url":"assets/KaTeX_SansSerif-Italic-C3H0VqGB.woff2"},{"revision":null,"url":"assets/KaTeX_SansSerif-Bold-D1sUS0GD.woff2"},{"revision":null,"url":"assets/KaTeX_Math-Italic-t53AETM-.woff2"},{"revision":null,"url":"assets/KaTeX_Math-BoldItalic-CZnvNsCZ.woff2"},{"revision":null,"url":"assets/KaTeX_Main-Regular-B22Nviop.woff2"},{"revision":null,"url":"assets/KaTeX_Main-Italic-NWA7e6Wa.woff2"},{"revision":null,"url":"assets/KaTeX_Main-BoldItalic-DxDJ3AOS.woff2"},{"revision":null,"url":"assets/KaTeX_Main-Bold-Cx986IdX.woff2"},{"revision":null,"url":"assets/KaTeX_Fraktur-Regular-CTYiF6lA.woff2"},{"revision":null,"url":"assets/KaTeX_Fraktur-Bold-CL6g_b3V.woff2"},{"revision":null,"url":"assets/KaTeX_Caligraphic-Regular-Di6jR-x-.woff2"},{"revision":null,"url":"assets/KaTeX_Caligraphic-Bold-Dq_IR9rO.woff2"},{"revision":null,"url":"assets/KaTeX_AMS-Regular-BQhdFMY1.woff2"},{"revision":"a0fb34fc84eb148d51812cd62669f20d","url":"icon-192.svg"},{"revision":"a0fb34fc84eb148d51812cd62669f20d","url":"icon-512.svg"},{"revision":"26dccd02a2ef7522892015154f5e3680","url":"manifest.webmanifest"}]),self.addEventListener(`push`,e=>{e.waitUntil(self.clients.matchAll({type:`window`,includeUncontrolled:!0}).then(t=>{if(t.some(e=>e.visibilityState===`visible`))return;let n=e.data?.json()??{title:`PPM`,body:`Chat completed`};return self.registration.showNotification(n.title,{body:n.body,icon:`/icon-192.svg`,badge:`/icon-192.svg`,tag:`ppm-chat-done`,silent:!1,data:{url:self.location.origin}})}))}),self.addEventListener(`notificationclick`,e=>{e.notification.close(),e.waitUntil(self.clients.matchAll({type:`window`,includeUncontrolled:!0}).then(t=>{for(let e of t)if(e.url.includes(self.location.origin)&&`focus`in e)return e.focus();return self.clients.openWindow(e.notification.data?.url||`/`)}))});
|
|
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))}function B(e){O().precache(e)}function V(e,t){B(e),z(t)}V([{"revision":"1872c500de691dce40960bb85481de07","url":"registerSW.js"},{"revision":"a0fb34fc84eb148d51812cd62669f20d","url":"icon-192.svg"},{"revision":"93dce4eb86e16c19a6622c9a6b554b39","url":"index.html"},{"revision":"a0fb34fc84eb148d51812cd62669f20d","url":"icon-512.svg"},{"revision":null,"url":"assets/project-store-DlbHpIq0.js"},{"revision":null,"url":"assets/utils-CSCvNZxE.js"},{"revision":null,"url":"assets/KaTeX_Fraktur-Bold-CL6g_b3V.woff2"},{"revision":null,"url":"assets/KaTeX_AMS-Regular-BQhdFMY1.woff2"},{"revision":null,"url":"assets/glide-data-grid-4mwS1Swl.js"},{"revision":null,"url":"assets/conflict-editor-DGm0Z6Mc.js"},{"revision":null,"url":"assets/katex-CHaeM9QC.js"},{"revision":null,"url":"assets/arrow-down-D825m4vm.js"},{"revision":null,"url":"assets/index-fyMt5gpO.css"},{"revision":null,"url":"assets/api-settings-BJTjIG4U.js"},{"revision":null,"url":"assets/pie-UPGHQEXC-CNoizzjb.js"},{"revision":null,"url":"assets/x-Dx3jsRgu.js"},{"revision":null,"url":"assets/esm-xVTUq__o.js"},{"revision":null,"url":"assets/index-CuOntRL_.js"},{"revision":null,"url":"assets/chat-tab-DNmhvaZ_.js"},{"revision":null,"url":"assets/table-BzjWcs87.js"},{"revision":null,"url":"assets/text-wrap-DJz9Bgpa.js"},{"revision":null,"url":"assets/KaTeX_Main-Regular-B22Nviop.woff2"},{"revision":null,"url":"assets/keybindings-store-Clt4mfff.js"},{"revision":null,"url":"assets/trash-2-D5P4y8p_.js"},{"revision":null,"url":"assets/markdown-renderer-Be-gcsCi.js"},{"revision":null,"url":"assets/radar-KQ55EAFF-7dns-ho5.js"},{"revision":null,"url":"assets/sparkles-CulWHe4c.js"},{"revision":null,"url":"assets/react-DHBl6KRc.js"},{"revision":null,"url":"assets/file-exclamation-point-Baz81y5z.js"},{"revision":null,"url":"assets/github.min-D2BCvnWf.css"},{"revision":null,"url":"assets/sql-query-editor-DGcroNAs.js"},{"revision":null,"url":"assets/treemap-KZPCXAKY-D3DZCLoE.js"},{"revision":null,"url":"assets/KaTeX_Fraktur-Regular-CTYiF6lA.woff2"},{"revision":null,"url":"assets/port-forwarding-tab-DTPLT4nk.js"},{"revision":null,"url":"assets/chevron-right-BzAdxJRG.js"},{"revision":null,"url":"assets/dist-CohudVKa.js"},{"revision":null,"url":"assets/glide-data-grid-nthEL3fk.css"},{"revision":null,"url":"assets/settings-store-DQUFTPk2.js"},{"revision":null,"url":"assets/KaTeX_Main-BoldItalic-DxDJ3AOS.woff2"},{"revision":null,"url":"assets/shield-off-C_MK1u09.js"},{"revision":null,"url":"assets/vendor-markdown-0Mxgxy0L.js"},{"revision":null,"url":"assets/pdf-preview-hiA6Dkic.js"},{"revision":null,"url":"assets/audio-preview-DFrv27cv.js"},{"revision":null,"url":"assets/wifi-CgM9T6HR.js"},{"revision":null,"url":"assets/sqlite-viewer-DIfCI2va.js"},{"revision":null,"url":"assets/tab-store-CIcbSn0c.js"},{"revision":null,"url":"assets/KaTeX_Main-Italic-NWA7e6Wa.woff2"},{"revision":null,"url":"assets/video-preview-CnRJmbG8.js"},{"revision":null,"url":"assets/use-monaco-theme-BLIgarH5.js"},{"revision":null,"url":"assets/KaTeX_Typewriter-Regular-CO6r4hn1.woff2"},{"revision":null,"url":"assets/panel-store-C9VAhbZz.js"},{"revision":null,"url":"assets/data-grid-types-DzL5W2em.js"},{"revision":null,"url":"assets/database-NmqHg29g.js"},{"revision":null,"url":"assets/chevron-down-CiFNPrfI.js"},{"revision":null,"url":"assets/docx-preview-BRpopR6E.js"},{"revision":null,"url":"assets/notification-store-B0D4A68q.js"},{"revision":null,"url":"assets/KaTeX_Caligraphic-Bold-Dq_IR9rO.woff2"},{"revision":null,"url":"assets/KaTeX_Caligraphic-Regular-Di6jR-x-.woff2"},{"revision":null,"url":"assets/data-grid-overlay-editor-DGjqvYn6.js"},{"revision":null,"url":"assets/settings-tab-B1wiEtFH.js"},{"revision":null,"url":"assets/gitGraph-HDMCJU4V-D3UR56AG.js"},{"revision":null,"url":"assets/rolldown-runtime-FhOqtrmT.js"},{"revision":null,"url":"assets/vendor-ui-UXCWAcmi.js"},{"revision":null,"url":"assets/git-log-panel-B5n35kot.js"},{"revision":null,"url":"assets/packet-RMMSAZCW-BIpeVUGW.js"},{"revision":null,"url":"assets/KaTeX_Math-Italic-t53AETM-.woff2"},{"revision":null,"url":"assets/github-dark-dimmed.min-BrpRStFV.css"},{"revision":null,"url":"assets/KaTeX_SansSerif-Bold-D1sUS0GD.woff2"},{"revision":null,"url":"assets/KaTeX_Script-Regular-D3wIWfF6.woff2"},{"revision":null,"url":"assets/arrow-up-Rcw6_KKu.js"},{"revision":null,"url":"assets/eye-off-BacF7RVS.js"},{"revision":null,"url":"assets/system-monitor-tab-CIVm3sgY.js"},{"revision":null,"url":"assets/vendor-mermaid-DkqjpqJK.js"},{"revision":null,"url":"assets/lib-LPmTkMu4.js"},{"revision":null,"url":"assets/KaTeX_Main-Bold-Cx986IdX.woff2"},{"revision":null,"url":"assets/diff-viewer-Blji3pAc.js"},{"revision":null,"url":"assets/database-viewer-D1nO6a11.js"},{"revision":null,"url":"assets/KaTeX_Size2-Regular-Dy4dx90m.woff2"},{"revision":null,"url":"assets/vendor-xterm-t3d5xZdz.js"},{"revision":null,"url":"assets/code-editor-CHwXYDhx.js"},{"revision":null,"url":"assets/KaTeX_SansSerif-Regular-DDBCnlJ7.woff2"},{"revision":null,"url":"assets/KaTeX_Size1-Regular-mCD8mA8B.woff2"},{"revision":null,"url":"assets/architecture-PBZL5I3N-CkdUQjA_.js"},{"revision":null,"url":"assets/number-overlay-editor-DtUBprPW.js"},{"revision":null,"url":"assets/csv-preview-asMfgR0r.js"},{"revision":null,"url":"assets/createLucideIcon-BjHrJDVb.js"},{"revision":null,"url":"assets/KaTeX_Size4-Regular-Dl5lxZxV.woff2"},{"revision":null,"url":"assets/code-CuravVys.js"},{"revision":null,"url":"assets/use-blob-url-DrPfBQBM.js"},{"revision":null,"url":"assets/KaTeX_Math-BoldItalic-CZnvNsCZ.woff2"},{"revision":null,"url":"assets/image-preview-Bu5XcdqW.js"},{"revision":null,"url":"assets/postgres-viewer-LimIiFby.js"},{"revision":null,"url":"assets/search-BEy08Exr.js"},{"revision":null,"url":"assets/extension-webview-BXeDxyVt.js"},{"revision":null,"url":"assets/api-client-BK4NPNoY.js"},{"revision":null,"url":"assets/shield-check-77W0OMbn.js"},{"revision":null,"url":"assets/terminal-tab-Dj9xDdbc.js"},{"revision":null,"url":"assets/input-CArJe9WS.js"},{"revision":null,"url":"assets/vendor-xterm-BrP-ENHg.css"},{"revision":null,"url":"assets/info-3K5VOQVL-DUhLSKI2.js"},{"revision":null,"url":"assets/KaTeX_SansSerif-Italic-C3H0VqGB.woff2"},{"revision":null,"url":"assets/dist-BM2EHhLH.js"},{"revision":null,"url":"assets/csv-parser-D1b_lg2T.js"},{"revision":"d0f94ce046cf8cf09605ee7664dac557","url":"monacoeditorwork/html.worker.bundle.js"},{"revision":"a424156a79b9c1b907db93aa3180585a","url":"monacoeditorwork/editor.worker.bundle.js"},{"revision":"b3a7f967560c9816492a1567b3f7f0dc","url":"monacoeditorwork/css.worker.bundle.js"},{"revision":"a5d8a1acfc29c2a4c882a54ffc93def3","url":"monacoeditorwork/json.worker.bundle.js"},{"revision":"948e060affb598c339be40d69e1f6f9c","url":"monacoeditorwork/ts.worker.bundle.js"},{"revision":"a0fb34fc84eb148d51812cd62669f20d","url":"icon-512.svg"},{"revision":"a0fb34fc84eb148d51812cd62669f20d","url":"icon-192.svg"},{"revision":"26dccd02a2ef7522892015154f5e3680","url":"manifest.webmanifest"}]);
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
File without changes
|
package/src/server/index.ts
CHANGED
|
@@ -5,7 +5,6 @@ import { VERSION } from "../version.ts";
|
|
|
5
5
|
import { authMiddleware } from "./middleware/auth.ts";
|
|
6
6
|
import { projectRoutes } from "./routes/projects.ts";
|
|
7
7
|
import { settingsRoutes } from "./routes/settings.ts";
|
|
8
|
-
import { pushRoutes } from "./routes/push.ts";
|
|
9
8
|
import { tunnelRoutes } from "./routes/tunnel.ts";
|
|
10
9
|
import { staticRoutes } from "./routes/static.ts";
|
|
11
10
|
import { projectScopedRouter } from "./routes/project-scoped.ts";
|
|
@@ -147,7 +146,6 @@ app.route("/api/system", resourceRoutes);
|
|
|
147
146
|
app.route("/api/settings", settingsRoutes);
|
|
148
147
|
app.route("/api/settings/mcp", mcpRoutes);
|
|
149
148
|
app.route("/api/tunnel", tunnelRoutes);
|
|
150
|
-
app.route("/api/push", pushRoutes);
|
|
151
149
|
app.route("/api/projects", projectRoutes);
|
|
152
150
|
app.route("/api/project/:projectName", projectScopedRouter);
|
|
153
151
|
app.route("/api/postgres", postgresRoutes);
|
|
@@ -44,7 +44,17 @@ interface CommandResultMsg extends WsMessage {
|
|
|
44
44
|
data?: Record<string, unknown>;
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
-
|
|
47
|
+
interface NotificationMsg extends WsMessage {
|
|
48
|
+
type: "notification";
|
|
49
|
+
title: string;
|
|
50
|
+
body: string;
|
|
51
|
+
project: string;
|
|
52
|
+
sessionId: string;
|
|
53
|
+
sessionTitle?: string;
|
|
54
|
+
notificationType: "done" | "approval_request" | "question";
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
type OutboundMsg = HeartbeatMsg | StateChangeMsg | CommandAckMsg | CommandResultMsg | NotificationMsg;
|
|
48
58
|
|
|
49
59
|
interface CommandMsg extends WsMessage {
|
|
50
60
|
type: "command";
|
|
@@ -131,6 +141,22 @@ export function isConnected(): boolean {
|
|
|
131
141
|
return ws !== null && ws.readyState <= WebSocket.OPEN;
|
|
132
142
|
}
|
|
133
143
|
|
|
144
|
+
/** Send a push notification via Cloud WS (Cloud dispatches Web Push to subscribed browsers) */
|
|
145
|
+
export function sendNotification(payload: {
|
|
146
|
+
title: string;
|
|
147
|
+
body: string;
|
|
148
|
+
project: string;
|
|
149
|
+
sessionId: string;
|
|
150
|
+
sessionTitle?: string;
|
|
151
|
+
notificationType: "done" | "approval_request" | "question";
|
|
152
|
+
}): void {
|
|
153
|
+
send({
|
|
154
|
+
type: "notification",
|
|
155
|
+
...payload,
|
|
156
|
+
timestamp: new Date().toISOString(),
|
|
157
|
+
} as NotificationMsg);
|
|
158
|
+
}
|
|
159
|
+
|
|
134
160
|
// ─── Internal ───────────────────────────────────────
|
|
135
161
|
|
|
136
162
|
function doConnect(): void {
|
|
@@ -16,7 +16,7 @@ import {
|
|
|
16
16
|
|
|
17
17
|
/** Top-level config keys stored in the config table (not projects) */
|
|
18
18
|
const CONFIG_TABLE_KEYS: (keyof PpmConfig)[] = [
|
|
19
|
-
"device_name", "port", "host", "theme", "auth", "ai", "
|
|
19
|
+
"device_name", "port", "host", "theme", "auth", "ai", "telegram", "clawbot",
|
|
20
20
|
];
|
|
21
21
|
|
|
22
22
|
/** File filter config keys stored in the config table */
|
|
@@ -907,30 +907,6 @@ export function deleteSessionTitle(sessionId: string): void {
|
|
|
907
907
|
}
|
|
908
908
|
|
|
909
909
|
// ---------------------------------------------------------------------------
|
|
910
|
-
// Push subscription helpers
|
|
911
|
-
// ---------------------------------------------------------------------------
|
|
912
|
-
|
|
913
|
-
export interface PushSubRow {
|
|
914
|
-
endpoint: string;
|
|
915
|
-
p256dh: string;
|
|
916
|
-
auth: string;
|
|
917
|
-
expiration_time: string | null;
|
|
918
|
-
}
|
|
919
|
-
|
|
920
|
-
export function getPushSubscriptions(): PushSubRow[] {
|
|
921
|
-
return getDb().query("SELECT endpoint, p256dh, auth, expiration_time FROM push_subscriptions").all() as PushSubRow[];
|
|
922
|
-
}
|
|
923
|
-
|
|
924
|
-
export function upsertPushSubscription(endpoint: string, p256dh: string, auth: string, expirationTime?: string | null): void {
|
|
925
|
-
getDb().query(
|
|
926
|
-
"INSERT INTO push_subscriptions (endpoint, p256dh, auth, expiration_time) VALUES (?, ?, ?, ?) ON CONFLICT(endpoint) DO UPDATE SET p256dh = excluded.p256dh, auth = excluded.auth, expiration_time = excluded.expiration_time",
|
|
927
|
-
).run(endpoint, p256dh, auth, expirationTime ?? null);
|
|
928
|
-
}
|
|
929
|
-
|
|
930
|
-
export function deletePushSubscription(endpoint: string): void {
|
|
931
|
-
getDb().query("DELETE FROM push_subscriptions WHERE endpoint = ?").run(endpoint);
|
|
932
|
-
}
|
|
933
|
-
|
|
934
910
|
// ---------------------------------------------------------------------------
|
|
935
911
|
// Session log helpers
|
|
936
912
|
// ---------------------------------------------------------------------------
|
|
@@ -19,15 +19,24 @@ class NotificationService {
|
|
|
19
19
|
broadcastGlobalEvent(event);
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
-
/** Broadcast notification to all channels (push, telegram). Fire-and-forget. */
|
|
23
|
-
async broadcast(
|
|
22
|
+
/** Broadcast notification to all channels (cloud push, telegram). Fire-and-forget. */
|
|
23
|
+
async broadcast(type: NotificationType, payload: NotificationPayload): Promise<void> {
|
|
24
24
|
const tasks: Promise<void>[] = [];
|
|
25
25
|
const userOnline = hasActiveClient();
|
|
26
26
|
|
|
27
|
-
// Push
|
|
27
|
+
// Cloud Push (replaces local Web Push) — Cloud dispatches to all subscribed browsers
|
|
28
28
|
tasks.push(
|
|
29
|
-
import("./
|
|
30
|
-
.then(({
|
|
29
|
+
import("./cloud-ws.service.ts")
|
|
30
|
+
.then(({ sendNotification }) => {
|
|
31
|
+
sendNotification({
|
|
32
|
+
title: payload.title,
|
|
33
|
+
body: payload.body,
|
|
34
|
+
project: payload.project,
|
|
35
|
+
sessionId: payload.sessionId,
|
|
36
|
+
sessionTitle: payload.sessionTitle,
|
|
37
|
+
notificationType: type,
|
|
38
|
+
});
|
|
39
|
+
})
|
|
31
40
|
.catch(() => {}),
|
|
32
41
|
);
|
|
33
42
|
|
package/src/types/config.ts
CHANGED
|
@@ -1,9 +1,3 @@
|
|
|
1
|
-
export interface PushConfig {
|
|
2
|
-
vapid_public_key: string;
|
|
3
|
-
vapid_private_key: string;
|
|
4
|
-
vapid_subject: string;
|
|
5
|
-
}
|
|
6
|
-
|
|
7
1
|
export interface TelegramConfig {
|
|
8
2
|
bot_token: string;
|
|
9
3
|
}
|
|
@@ -28,7 +22,6 @@ export interface PpmConfig {
|
|
|
28
22
|
auth: AuthConfig;
|
|
29
23
|
projects: ProjectConfig[];
|
|
30
24
|
ai: AIConfig;
|
|
31
|
-
push?: PushConfig;
|
|
32
25
|
telegram?: TelegramConfig;
|
|
33
26
|
clawbot?: PPMBotConfig;
|
|
34
27
|
cloud_url?: string;
|
|
@@ -22,6 +22,32 @@ export const AGGREGATE_FNS = ["COUNT", "SUM", "AVG", "MIN", "MAX"];
|
|
|
22
22
|
export const OPERATORS = ["=", "!=", "<>", ">", "<", ">=", "<=", "LIKE", "ILIKE", "IN", "NOT IN", "BETWEEN", "IS NULL", "IS NOT NULL"];
|
|
23
23
|
export const SORT_DIRS = ["ASC", "DESC"];
|
|
24
24
|
|
|
25
|
+
/** Find the SQL statement surrounding the cursor line (split by ;) */
|
|
26
|
+
export function getStatementAtCursor(text: string, cursorLine: number): string {
|
|
27
|
+
const lines = text.split("\n");
|
|
28
|
+
let stmtStart = 0;
|
|
29
|
+
for (let i = 0; i < lines.length; i++) {
|
|
30
|
+
const trimmed = lines[i]!.trim();
|
|
31
|
+
if (i < cursorLine - 1 && trimmed.endsWith(";")) {
|
|
32
|
+
stmtStart = i + 1;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
let stmtEnd = lines.length - 1;
|
|
36
|
+
for (let i = cursorLine - 1; i < lines.length; i++) {
|
|
37
|
+
const trimmed = lines[i]!.trim();
|
|
38
|
+
if (trimmed.endsWith(";")) {
|
|
39
|
+
stmtEnd = i;
|
|
40
|
+
break;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
while (stmtStart <= stmtEnd) {
|
|
44
|
+
const t = lines[stmtStart]!.trim();
|
|
45
|
+
if (t && !t.startsWith("--")) break;
|
|
46
|
+
stmtStart++;
|
|
47
|
+
}
|
|
48
|
+
return lines.slice(stmtStart, stmtEnd + 1).join("\n").trim();
|
|
49
|
+
}
|
|
50
|
+
|
|
25
51
|
/** Client-side column cache to avoid redundant fetches */
|
|
26
52
|
const columnCache = new Map<string, { name: string; type: string }[]>();
|
|
27
53
|
|
|
@@ -153,7 +179,8 @@ export function createSqlCompletionProvider(
|
|
|
153
179
|
startColumn: word.startColumn, endColumn: word.endColumn,
|
|
154
180
|
};
|
|
155
181
|
const fullText = model.getValue();
|
|
156
|
-
const
|
|
182
|
+
const currentStmt = getStatementAtCursor(fullText, position.lineNumber);
|
|
183
|
+
const { tableRefs, aliasMap } = extractTableRefs(currentStmt);
|
|
157
184
|
const suggestions: MonacoType.languages.CompletionItem[] = [];
|
|
158
185
|
const ctx = getCompletionContext(textUntilPosition);
|
|
159
186
|
|
|
@@ -2,7 +2,7 @@ import { useState, useCallback, useRef, useEffect } from "react";
|
|
|
2
2
|
import Editor, { type OnMount } from "@monaco-editor/react";
|
|
3
3
|
import type * as MonacoType from "monaco-editor";
|
|
4
4
|
import { useMonacoTheme } from "@/lib/use-monaco-theme";
|
|
5
|
-
import { createSqlCompletionProvider, clearCompletionCache, type SchemaInfo } from "./sql-completion-provider";
|
|
5
|
+
import { createSqlCompletionProvider, clearCompletionCache, getStatementAtCursor, type SchemaInfo } from "./sql-completion-provider";
|
|
6
6
|
|
|
7
7
|
interface SqlQueryEditorProps {
|
|
8
8
|
onExecute: (sql: string) => void;
|
|
@@ -15,35 +15,6 @@ interface SqlQueryEditorProps {
|
|
|
15
15
|
persistedSql?: string;
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
-
/** Find the SQL statement surrounding the cursor line (split by ;) */
|
|
19
|
-
export function getStatementAtCursor(text: string, cursorLine: number): string {
|
|
20
|
-
const lines = text.split("\n");
|
|
21
|
-
// Find statement boundaries (lines where a statement ends with ;)
|
|
22
|
-
let stmtStart = 0;
|
|
23
|
-
for (let i = 0; i < lines.length; i++) {
|
|
24
|
-
const trimmed = lines[i]!.trim();
|
|
25
|
-
if (i < cursorLine - 1 && trimmed.endsWith(";")) {
|
|
26
|
-
stmtStart = i + 1;
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
// Find statement end
|
|
30
|
-
let stmtEnd = lines.length - 1;
|
|
31
|
-
for (let i = cursorLine - 1; i < lines.length; i++) {
|
|
32
|
-
const trimmed = lines[i]!.trim();
|
|
33
|
-
if (trimmed.endsWith(";")) {
|
|
34
|
-
stmtEnd = i;
|
|
35
|
-
break;
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
// Skip leading empty/comment lines
|
|
39
|
-
while (stmtStart <= stmtEnd) {
|
|
40
|
-
const t = lines[stmtStart]!.trim();
|
|
41
|
-
if (t && !t.startsWith("--")) break;
|
|
42
|
-
stmtStart++;
|
|
43
|
-
}
|
|
44
|
-
return lines.slice(stmtStart, stmtEnd + 1).join("\n").trim();
|
|
45
|
-
}
|
|
46
|
-
|
|
47
18
|
/** Shared Monaco-based SQL query editor (editor only, no results) */
|
|
48
19
|
export function SqlQueryEditor({ onExecute, loading, defaultValue = "SELECT * FROM ", schemaInfo, onSqlChange, persistedSql }: SqlQueryEditorProps) {
|
|
49
20
|
const [query, setQuery] = useState(() => persistedSql ?? defaultValue);
|
|
@@ -13,7 +13,7 @@ import { EditorBreadcrumb } from "./editor-breadcrumb";
|
|
|
13
13
|
import { EditorToolbar } from "./editor-toolbar";
|
|
14
14
|
import { SaveAsDialog } from "./save-as-dialog";
|
|
15
15
|
import { EditorMobileToolbar } from "./editor-mobile-toolbar";
|
|
16
|
-
import { createSqlCompletionProvider, clearCompletionCache, type SchemaInfo } from "../database/sql-completion-provider";
|
|
16
|
+
import { createSqlCompletionProvider, clearCompletionCache, getStatementAtCursor, type SchemaInfo } from "../database/sql-completion-provider";
|
|
17
17
|
import { useConnections, type Connection } from "../database/use-connections";
|
|
18
18
|
import { GlideDataGrid } from "../database/glide-data-grid";
|
|
19
19
|
import type { GridColumnSchema } from "../database/glide-grid-types";
|
|
@@ -427,6 +427,19 @@ export const CodeEditor = memo(function CodeEditor({ metadata, tabId }: CodeEdit
|
|
|
427
427
|
|
|
428
428
|
// Register CodeLens for inline Run buttons on .sql files (scoped to this editor's model)
|
|
429
429
|
if (isSql) {
|
|
430
|
+
// Ctrl/Cmd+Enter → run statement at cursor
|
|
431
|
+
editor.addAction({
|
|
432
|
+
id: "run-sql-at-cursor",
|
|
433
|
+
label: "Run Statement at Cursor",
|
|
434
|
+
keybindings: [monaco.KeyMod.CtrlCmd | monaco.KeyCode.Enter],
|
|
435
|
+
run: (ed) => {
|
|
436
|
+
const pos = ed.getPosition();
|
|
437
|
+
if (!pos) return;
|
|
438
|
+
const stmt = getStatementAtCursor(ed.getValue(), pos.lineNumber);
|
|
439
|
+
if (stmt) runSqlRef.current(stmt);
|
|
440
|
+
},
|
|
441
|
+
});
|
|
442
|
+
|
|
430
443
|
codeLensDisposable.current.forEach((d) => d.dispose());
|
|
431
444
|
codeLensDisposable.current = [];
|
|
432
445
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { useState, useCallback, useRef } from "react";
|
|
2
2
|
import {
|
|
3
|
-
Moon, Sun, Monitor, Bell,
|
|
3
|
+
Moon, Sun, Monitor, Bell, Check, ChevronRight, ArrowLeft,
|
|
4
4
|
Bot, BellRing, Keyboard, Globe, Plug, Puzzle, Bug, FolderSearch,
|
|
5
5
|
} from "lucide-react";
|
|
6
6
|
import { Button } from "@/components/ui/button";
|
|
@@ -19,18 +19,12 @@ import { ExtensionManagerSection } from "./extension-manager-section";
|
|
|
19
19
|
import { PPMBotSettingsSection } from "./ppmbot-settings-section";
|
|
20
20
|
import { ChangePasswordSection } from "./change-password-section";
|
|
21
21
|
import { FilesSettingsSection } from "./files-settings-section";
|
|
22
|
-
import { usePushNotification } from "@/hooks/use-push-notification";
|
|
23
|
-
|
|
24
22
|
const THEME_OPTIONS: { value: Theme; label: string; icon: React.ElementType }[] = [
|
|
25
23
|
{ value: "light", label: "Light", icon: Sun },
|
|
26
24
|
{ value: "dark", label: "Dark", icon: Moon },
|
|
27
25
|
{ value: "system", label: "System", icon: Monitor },
|
|
28
26
|
];
|
|
29
27
|
|
|
30
|
-
const pushSupported = "PushManager" in window && "serviceWorker" in navigator;
|
|
31
|
-
const isIosNonPwa = /iPhone|iPad/.test(navigator.userAgent) &&
|
|
32
|
-
!window.matchMedia("(display-mode: standalone)").matches;
|
|
33
|
-
|
|
34
28
|
type SettingsCategory = "ai" | "notifications" | "clawbot" | "jira" | "proxy" | "shortcuts" | "mcp" | "extensions" | "files";
|
|
35
29
|
|
|
36
30
|
const CATEGORIES: { value: SettingsCategory; label: string; subtitle: string; icon: React.ElementType }[] = [
|
|
@@ -47,7 +41,6 @@ const CATEGORIES: { value: SettingsCategory; label: string; subtitle: string; ic
|
|
|
47
41
|
|
|
48
42
|
export function SettingsTab() {
|
|
49
43
|
const { theme, setTheme, deviceName, setDeviceName, version, jiraEnabled, setJiraEnabled } = useSettingsStore(useShallow((s) => ({ theme: s.theme, setTheme: s.setTheme, deviceName: s.deviceName, setDeviceName: s.setDeviceName, version: s.version, jiraEnabled: s.jiraEnabled, setJiraEnabled: s.setJiraEnabled })));
|
|
50
|
-
const { permission, isSubscribed, loading, error: pushError, subscribe, unsubscribe } = usePushNotification();
|
|
51
44
|
const [activeCategory, setActiveCategory] = useState<SettingsCategory | null>(null);
|
|
52
45
|
const [nameInput, setNameInput] = useState(deviceName ?? "");
|
|
53
46
|
const [nameSaving, setNameSaving] = useState(false);
|
|
@@ -92,7 +85,7 @@ export function SettingsTab() {
|
|
|
92
85
|
<ScrollArea className="flex-1 min-h-0">
|
|
93
86
|
<div className="p-3">
|
|
94
87
|
{activeCategory === "ai" && <AISettingsSection compact />}
|
|
95
|
-
{activeCategory === "notifications" && <NotificationsContent
|
|
88
|
+
{activeCategory === "notifications" && <NotificationsContent />}
|
|
96
89
|
{activeCategory === "clawbot" && <PPMBotSettingsSection />}
|
|
97
90
|
{/* Jira is now a sidebar tab with a toggle below */}
|
|
98
91
|
{activeCategory === "proxy" && <ProxySettingsSection />}
|
|
@@ -231,67 +224,20 @@ export function SettingsTab() {
|
|
|
231
224
|
}
|
|
232
225
|
|
|
233
226
|
/** Notifications detail content — extracted to keep SettingsTab clean */
|
|
234
|
-
function NotificationsContent(
|
|
235
|
-
isSubscribed: boolean;
|
|
236
|
-
loading: boolean;
|
|
237
|
-
permission: NotificationPermission;
|
|
238
|
-
pushError: string | null;
|
|
239
|
-
subscribe: () => void;
|
|
240
|
-
unsubscribe: () => void;
|
|
241
|
-
}) {
|
|
227
|
+
function NotificationsContent() {
|
|
242
228
|
return (
|
|
243
229
|
<div className="space-y-4">
|
|
244
|
-
{/* Push */}
|
|
230
|
+
{/* Cloud Push */}
|
|
245
231
|
<section className="space-y-2">
|
|
246
232
|
<h3 className="text-xs font-medium text-muted-foreground">Push Notifications</h3>
|
|
247
|
-
|
|
248
|
-
<
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
{isSubscribed ? <Bell className="size-3.5" /> : <BellOff className="size-3.5" />}
|
|
256
|
-
<span className="text-xs">Push notifications</span>
|
|
257
|
-
</div>
|
|
258
|
-
<Button
|
|
259
|
-
variant={isSubscribed ? "default" : "outline"}
|
|
260
|
-
size="sm"
|
|
261
|
-
className="h-7 text-xs cursor-pointer"
|
|
262
|
-
disabled={loading || permission === "denied"}
|
|
263
|
-
onClick={() => (isSubscribed ? unsubscribe() : subscribe())}
|
|
264
|
-
>
|
|
265
|
-
{loading ? "..." : isSubscribed ? "On" : "Off"}
|
|
266
|
-
</Button>
|
|
267
|
-
</div>
|
|
268
|
-
{isSubscribed && (
|
|
269
|
-
<Button
|
|
270
|
-
variant="outline"
|
|
271
|
-
size="sm"
|
|
272
|
-
className="h-7 text-xs w-full cursor-pointer"
|
|
273
|
-
onClick={() => {
|
|
274
|
-
new Notification("PPM Test", { body: "Push notifications are working!" });
|
|
275
|
-
}}
|
|
276
|
-
>
|
|
277
|
-
Test notification
|
|
278
|
-
</Button>
|
|
279
|
-
)}
|
|
280
|
-
{pushError && (
|
|
281
|
-
<p className="text-[11px] text-destructive">{pushError}</p>
|
|
282
|
-
)}
|
|
283
|
-
{permission === "denied" && (
|
|
284
|
-
<p className="text-[11px] text-destructive">
|
|
285
|
-
Notifications blocked. Enable in browser settings.
|
|
286
|
-
</p>
|
|
287
|
-
)}
|
|
288
|
-
{isIosNonPwa && (
|
|
289
|
-
<p className="text-[11px] text-muted-foreground">
|
|
290
|
-
On iOS, install PPM to Home Screen for push notifications.
|
|
291
|
-
</p>
|
|
292
|
-
)}
|
|
293
|
-
</div>
|
|
294
|
-
)}
|
|
233
|
+
<div className="flex items-center gap-1.5">
|
|
234
|
+
<Bell className="size-3.5 text-muted-foreground" />
|
|
235
|
+
<span className="text-xs">Managed via PPM Cloud</span>
|
|
236
|
+
</div>
|
|
237
|
+
<p className="text-[11px] text-muted-foreground">
|
|
238
|
+
Push notifications are now dispatched through PPM Cloud.
|
|
239
|
+
Visit your Cloud dashboard to manage subscriptions.
|
|
240
|
+
</p>
|
|
295
241
|
</section>
|
|
296
242
|
|
|
297
243
|
<Separator />
|