@hienlh/ppm 0.13.58 → 0.13.59
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 +2 -2
- package/assets/skills/ppm/SKILL.md +1 -1
- package/assets/skills/ppm/references/http-api.md +1 -1
- package/dist/web/assets/{audio-preview-DEiWicib.js → audio-preview-DPUWgkFM.js} +1 -1
- package/dist/web/assets/{chat-tab-cTNzjeke.js → chat-tab-jeH2KOyI.js} +3 -3
- package/dist/web/assets/{code-editor-DfI-ziOx.js → code-editor-D689bNqg.js} +2 -2
- package/dist/web/assets/{conflict-editor-D3O6LScu.js → conflict-editor-BBLBwDP3.js} +1 -1
- package/dist/web/assets/{database-viewer--56cGHzb.js → database-viewer-Dn_XmPuG.js} +1 -1
- package/dist/web/assets/{diff-viewer-DcodJCRl.js → diff-viewer-BawweIzs.js} +1 -1
- package/dist/web/assets/{extension-webview-D4B6-SMy.js → extension-webview-CnW4FmbT.js} +1 -1
- package/dist/web/assets/{git-log-panel-DNzozRgD.js → git-log-panel-DOtefVWL.js} +1 -1
- package/dist/web/assets/{glide-data-grid-DNkYYw65.js → glide-data-grid-ckYYsHxU.js} +1 -1
- package/dist/web/assets/{image-preview-Z_2ryPZN.js → image-preview-vivCL0Rz.js} +1 -1
- package/dist/web/assets/{index-BD-x9C-z.js → index-tXhZwam6.js} +3 -3
- package/dist/web/assets/keybindings-store-BPLIbuiX.js +1 -0
- package/dist/web/assets/{markdown-renderer-CyYPNwWJ.js → markdown-renderer-BiLohd4E.js} +1 -1
- package/dist/web/assets/notification-store-DfPnCRYc.js +1 -0
- package/dist/web/assets/pdf-preview-CZxInEra.js +1 -0
- package/dist/web/assets/{port-forwarding-tab-Do8vqJWR.js → port-forwarding-tab-cEuRXpkT.js} +1 -1
- package/dist/web/assets/{postgres-viewer-Caj1bdFn.js → postgres-viewer-DotG-n6G.js} +1 -1
- package/dist/web/assets/{settings-tab-Dd85LS_2.js → settings-tab-DCNSHpkk.js} +1 -1
- package/dist/web/assets/{sql-query-editor-KIv3CAg8.js → sql-query-editor-wMM7vxn4.js} +1 -1
- package/dist/web/assets/{sqlite-viewer-CoeXNWfR.js → sqlite-viewer-fczUQ3pm.js} +1 -1
- package/dist/web/assets/{system-monitor-tab-Dax2F-1U.js → system-monitor-tab-DnjKZ6kX.js} +1 -1
- package/dist/web/assets/{terminal-tab-DVeEspLf.js → terminal-tab-4VTsRAv_.js} +1 -1
- package/dist/web/assets/{video-preview-T9iHZknc.js → video-preview-Aabd59Fv.js} +1 -1
- package/dist/web/index.html +1 -1
- package/dist/web/sw.js +1 -1
- package/package.json +1 -1
- package/src/server/middleware/auth.ts +9 -6
- package/src/web/components/editor/pdf-preview.tsx +35 -25
- package/dist/web/assets/keybindings-store-CtCmu4r4.js +0 -1
- package/dist/web/assets/notification-store-g7oIcSzX.js +0 -1
- package/dist/web/assets/pdf-preview-DP53VE-6.js +0 -1
|
@@ -1,35 +1,36 @@
|
|
|
1
|
-
import { useCallback, useEffect, useRef, useState } from "react";
|
|
1
|
+
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
2
2
|
import { Loader2, FileWarning, ExternalLink } from "lucide-react";
|
|
3
|
-
import {
|
|
3
|
+
import { projectUrl, getAuthToken } from "@/lib/api-client";
|
|
4
4
|
|
|
5
5
|
export function PdfPreview({ filePath, projectName }: { filePath: string; projectName: string }) {
|
|
6
|
-
const [refreshKey, setRefreshKey] = useState(0);
|
|
7
6
|
const iframeRef = useRef<HTMLIFrameElement>(null);
|
|
8
|
-
const
|
|
7
|
+
const [loaded, setLoaded] = useState(false);
|
|
8
|
+
const [error, setError] = useState(false);
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
// Build stable direct URL (no blob) so reload() preserves scroll
|
|
11
|
+
const iframeSrc = useMemo(() => {
|
|
12
|
+
const isExternal = /^(\/|[A-Za-z]:[/\\])/.test(filePath);
|
|
13
|
+
const base = isExternal
|
|
14
|
+
? `/api/fs/raw?path=${encodeURIComponent(filePath)}`
|
|
15
|
+
: `${projectUrl(projectName)}/files/raw?path=${encodeURIComponent(filePath)}`;
|
|
16
|
+
const token = getAuthToken();
|
|
17
|
+
return token ? `${base}&token=${encodeURIComponent(token)}` : base;
|
|
18
|
+
}, [filePath, projectName]);
|
|
11
19
|
|
|
12
|
-
// Auto-reload
|
|
20
|
+
// Auto-reload on file change — reload() preserves browser PDF viewer scroll
|
|
13
21
|
useEffect(() => {
|
|
14
22
|
const handler = (e: Event) => {
|
|
15
23
|
const detail = (e as CustomEvent).detail;
|
|
16
24
|
if (detail.projectName !== projectName || detail.path !== filePath) return;
|
|
17
|
-
// Save current page hash before re-fetch (Chrome PDF viewer uses #page=N&zoom=...)
|
|
18
25
|
try {
|
|
19
|
-
|
|
20
|
-
} catch { /* cross-origin */ }
|
|
21
|
-
setRefreshKey((k) => k + 1);
|
|
26
|
+
iframeRef.current?.contentWindow?.location.reload();
|
|
27
|
+
} catch { /* cross-origin fallback — shouldn't happen for same-origin */ }
|
|
22
28
|
};
|
|
23
29
|
window.addEventListener("file:changed", handler);
|
|
24
30
|
return () => window.removeEventListener("file:changed", handler);
|
|
25
31
|
}, [filePath, projectName]);
|
|
26
32
|
|
|
27
|
-
const openInNewTab = useCallback(() => {
|
|
28
|
-
|
|
29
|
-
// Append saved page hash to blob URL so PDF viewer restores position
|
|
30
|
-
const iframeSrc = blobUrl
|
|
31
|
-
? `${blobUrl}${pageHashRef.current}`
|
|
32
|
-
: undefined;
|
|
33
|
+
const openInNewTab = useCallback(() => { window.open(iframeSrc, "_blank"); }, [iframeSrc]);
|
|
33
34
|
|
|
34
35
|
if (error) {
|
|
35
36
|
return (
|
|
@@ -39,18 +40,27 @@ export function PdfPreview({ filePath, projectName }: { filePath: string; projec
|
|
|
39
40
|
</div>
|
|
40
41
|
);
|
|
41
42
|
}
|
|
42
|
-
if (!blobUrl) {
|
|
43
|
-
return <div className="flex items-center justify-center h-full"><Loader2 className="size-5 animate-spin text-text-subtle" /></div>;
|
|
44
|
-
}
|
|
45
43
|
return (
|
|
46
44
|
<div className="flex flex-col h-full">
|
|
47
|
-
|
|
48
|
-
<
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
45
|
+
{!loaded && (
|
|
46
|
+
<div className="flex items-center justify-center h-full"><Loader2 className="size-5 animate-spin text-text-subtle" /></div>
|
|
47
|
+
)}
|
|
48
|
+
<div className={`flex flex-col h-full ${loaded ? "" : "hidden"}`}>
|
|
49
|
+
<div className="flex items-center justify-between px-3 py-1.5 border-b border-border bg-background shrink-0">
|
|
50
|
+
<span className="text-xs text-text-secondary truncate">{filePath}</span>
|
|
51
|
+
<button onClick={openInNewTab} className="flex items-center gap-1 text-xs text-text-secondary hover:text-text-primary transition-colors">
|
|
52
|
+
<ExternalLink className="size-3" /> Open in new tab
|
|
53
|
+
</button>
|
|
54
|
+
</div>
|
|
55
|
+
<iframe
|
|
56
|
+
ref={iframeRef}
|
|
57
|
+
src={iframeSrc}
|
|
58
|
+
title={filePath}
|
|
59
|
+
className="flex-1 w-full border-none"
|
|
60
|
+
onLoad={() => setLoaded(true)}
|
|
61
|
+
onError={() => setError(true)}
|
|
62
|
+
/>
|
|
52
63
|
</div>
|
|
53
|
-
<iframe ref={iframeRef} src={iframeSrc} title={filePath} className="flex-1 w-full border-none" />
|
|
54
64
|
</div>
|
|
55
65
|
);
|
|
56
66
|
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import"./vendor-markdown-0Mxgxy0L.js";import"./api-client-DiZgVOok.js";import{D as e}from"./index-BD-x9C-z.js";export{e as useKeybindingsStore};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import"./vendor-markdown-0Mxgxy0L.js";import"./api-client-DiZgVOok.js";import{P as e}from"./index-BD-x9C-z.js";export{e as useNotificationStore};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{o as e}from"./rolldown-runtime-FhOqtrmT.js";import{b as t,x as n}from"./vendor-markdown-0Mxgxy0L.js";import{t as r}from"./file-exclamation-point-B__2Hrd6.js";import"./api-client-DiZgVOok.js";import{$ as i,ct as a}from"./index-BD-x9C-z.js";import{t as o}from"./use-blob-url-DCUIEzjB.js";var s=e(n(),1),c=t();function l({filePath:e,projectName:t}){let[n,l]=(0,s.useState)(0),u=(0,s.useRef)(null),d=(0,s.useRef)(``),{blobUrl:f,error:p}=o(e,t,`application/pdf`,n);(0,s.useEffect)(()=>{let n=n=>{let r=n.detail;if(!(r.projectName!==t||r.path!==e)){try{d.current=u.current?.contentWindow?.location.hash||``}catch{}l(e=>e+1)}};return window.addEventListener(`file:changed`,n),()=>window.removeEventListener(`file:changed`,n)},[e,t]);let m=(0,s.useCallback)(()=>{f&&window.open(f,`_blank`)},[f]),h=f?`${f}${d.current}`:void 0;return p?(0,c.jsxs)(`div`,{className:`flex flex-col items-center justify-center h-full gap-3 text-text-secondary`,children:[(0,c.jsx)(r,{className:`size-10 text-text-subtle`}),(0,c.jsx)(`p`,{className:`text-sm`,children:`Failed to load PDF.`})]}):f?(0,c.jsxs)(`div`,{className:`flex flex-col h-full`,children:[(0,c.jsxs)(`div`,{className:`flex items-center justify-between px-3 py-1.5 border-b border-border bg-background shrink-0`,children:[(0,c.jsx)(`span`,{className:`text-xs text-text-secondary truncate`,children:e}),(0,c.jsxs)(`button`,{onClick:m,className:`flex items-center gap-1 text-xs text-text-secondary hover:text-text-primary transition-colors`,children:[(0,c.jsx)(a,{className:`size-3`}),` Open in new tab`]})]}),(0,c.jsx)(`iframe`,{ref:u,src:h,title:e,className:`flex-1 w-full border-none`})]}):(0,c.jsx)(`div`,{className:`flex items-center justify-center h-full`,children:(0,c.jsx)(i,{className:`size-5 animate-spin text-text-subtle`})})}export{l as PdfPreview};
|