This commit is contained in:
saqib mir
2026-05-21 12:51:18 +05:30
7 changed files with 41 additions and 44 deletions
+12 -23
View File
@@ -57,6 +57,7 @@
"integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"@babel/code-frame": "^7.29.0",
"@babel/generator": "^7.29.0",
@@ -266,29 +267,6 @@
"node": ">=6.9.0"
}
},
"node_modules/@emnapi/core": {
"version": "1.10.0",
"resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.10.0.tgz",
"integrity": "sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw==",
"dev": true,
"license": "MIT",
"optional": true,
"dependencies": {
"@emnapi/wasi-threads": "1.2.1",
"tslib": "^2.4.0"
}
},
"node_modules/@emnapi/runtime": {
"version": "1.10.0",
"resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.10.0.tgz",
"integrity": "sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==",
"dev": true,
"license": "MIT",
"optional": true,
"dependencies": {
"tslib": "^2.4.0"
}
},
"node_modules/@emnapi/wasi-threads": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.1.tgz",
@@ -875,6 +853,7 @@
"integrity": "sha512-GUUEShf+PBCGW2KaXwcIt3Yk+e3pkKwWKb9GSyM9WQVE+ep2jzmHdGsHzu4wgcZy5fN9FBdVzjpBQsYlpfpgLA==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"undici-types": "~7.16.0"
}
@@ -885,6 +864,7 @@
"integrity": "sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"csstype": "^3.2.2"
}
@@ -944,6 +924,7 @@
"integrity": "sha512-HPwA+hVkfcriajbNvTmZv4VRauibay+cWArYUYq7u7W7PmGShMxbPxLvrwDme55a6d5alG3nrYfhyJ/G28XlLg==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"@typescript-eslint/scope-manager": "8.59.3",
"@typescript-eslint/types": "8.59.3",
@@ -1174,6 +1155,7 @@
"integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==",
"dev": true,
"license": "MIT",
"peer": true,
"bin": {
"acorn": "bin/acorn"
},
@@ -1264,6 +1246,7 @@
}
],
"license": "MIT",
"peer": true,
"dependencies": {
"baseline-browser-mapping": "^2.10.12",
"caniuse-lite": "^1.0.30001782",
@@ -1399,6 +1382,7 @@
"integrity": "sha512-loXy6bWOoP3EP6JA7jo6p5jMpBJmHmsNZM5SFRHLdh1MGOPurMnNBj4ZlAbaqUAaQWbCr7jHV4P7gzAyryZWkQ==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"@eslint-community/eslint-utils": "^4.8.0",
"@eslint-community/regexpp": "^4.12.2",
@@ -2287,6 +2271,7 @@
"integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==",
"dev": true,
"license": "MIT",
"peer": true,
"engines": {
"node": ">=12"
},
@@ -2348,6 +2333,7 @@
"resolved": "https://registry.npmjs.org/react/-/react-19.2.6.tgz",
"integrity": "sha512-sfWGGfavi0xr8Pg0sVsyHMAOziVYKgPLNrS7ig+ivMNb3wbCBw3KxtflsGBAwD3gYQlE/AEZsTLgToRrSCjb0Q==",
"license": "MIT",
"peer": true,
"engines": {
"node": ">=0.10.0"
}
@@ -2504,6 +2490,7 @@
"integrity": "sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw==",
"dev": true,
"license": "Apache-2.0",
"peer": true,
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
@@ -2590,6 +2577,7 @@
"integrity": "sha512-MFtjBYgzmSxmgA4RAfjIyXWpGe1oALnjgUTzzV7QLx/TKxCzjtMH6Fd9/eVK+5Fg1qNoz5VAwsmMs/NofrmJvw==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"lightningcss": "^1.32.0",
"picomatch": "^4.0.4",
@@ -2714,6 +2702,7 @@
"integrity": "sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ==",
"dev": true,
"license": "MIT",
"peer": true,
"funding": {
"url": "https://github.com/sponsors/colinhacks"
}
+1 -1
View File
@@ -31,7 +31,7 @@ function App() {
try {
const health = await gatewayService.getHealth();
setBackendHealthy(health.engine_available || true);
} catch (err) {
} catch {
setBackendHealthy(false);
}
};
+1 -1
View File
@@ -24,7 +24,7 @@ export interface RenderParams {
export interface EditOperation {
type: 'add_text' | 'delete_text' | 'draw_shape' | 'add_annotation';
pageIndex: number;
data: any;
data: unknown;
}
class GatewayService {
-4
View File
@@ -22,10 +22,6 @@ class WasmLoader {
}
try {
// In a real production setup, we load the wasm glue script:
// @ts-ignore
// const Module = await import('@/wasm/pdfengine.js');
// For Phase 0 / Gate G0a, we stub/mock the WASM loading process gracefully:
return new Promise((resolve) => {
setTimeout(() => {
this.isLoaded = true;
-1
View File
@@ -20,7 +20,6 @@ interface AnnotationLayerProps {
}
export const AnnotationLayer: React.FC<AnnotationLayerProps> = ({
pageIndex: _pageIndex,
width,
height,
zoom,
+26 -12
View File
@@ -25,6 +25,8 @@ interface PageLayout {
top: number;
}
const generateUniqueId = () => `anno_${Math.random().toString(36).substring(2, 11)}`;
export const PDFViewer: React.FC<PDFViewerProps> = ({
documentId,
totalPages,
@@ -136,32 +138,44 @@ export const PDFViewer: React.FC<PDFViewerProps> = ({
// Load the rendered SVG/Image URL for each visible page
useEffect(() => {
let active = true;
const fetchPageImages = async () => {
const newUrls = [...renderedPages];
const missingPages = visiblePages.filter((page) => !renderedPages[page.index]);
if (missingPages.length === 0) return;
const renderPromises = visiblePages.map(async (page) => {
if (!newUrls[page.index]) {
const renders = await Promise.all(
missingPages.map(async (page) => {
const url = await gatewayService.renderPage({
documentId,
pageIndex: page.index,
zoom,
rotation,
});
newUrls[page.index] = url;
}
});
return { index: page.index, url };
})
);
await Promise.all(renderPromises);
setRenderedPages(newUrls);
if (!active) return;
setRenderedPages((prev) => {
const next = [...prev];
renders.forEach(({ index, url }) => {
next[index] = url;
});
return next;
});
};
fetchPageImages();
}, [visiblePages, documentId, zoom, rotation]);
return () => {
active = false;
};
}, [visiblePages, documentId, zoom, rotation, renderedPages]);
const handleTextSelection = (text: string, bbox: Rect, _pageIndex: number) => {
const handleTextSelection = (text: string, bbox: Rect) => {
if (activeTool === 'highlight') {
const newAnno: Annotation = {
id: `anno_${Math.random().toString(36).substr(2, 9)}`,
id: generateUniqueId(),
type: 'highlight',
bbox: {
x: bbox.x / zoom,
@@ -226,7 +240,7 @@ export const PDFViewer: React.FC<PDFViewerProps> = ({
width={page.width}
height={page.height}
zoom={zoom}
onTextSelected={(text, bbox) => handleTextSelection(text, bbox, page.index)}
onTextSelected={(text, bbox) => handleTextSelection(text, bbox)}
/>
{/* signature/ink overlay tool layer */}
-1
View File
@@ -13,7 +13,6 @@ export const SelectionLayer: React.FC<SelectionLayerProps> = ({
pageIndex,
width,
height,
zoom: _zoom,
onTextSelected,
}) => {
const [dragStart, setDragStart] = useState<Point | null>(null);