mirror of
https://github.com/Stirling-Tools/Stirling-PDF.git
synced 2026-09-03 05:10:16 +03:00
Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
98080a24d4 | ||
|
|
96e03dfe94 |
Generated
+34
-8
@@ -59,7 +59,7 @@
|
||||
"@tauri-apps/plugin-shell": "^2.3.5",
|
||||
"@userback/widget": "^0.3.12",
|
||||
"autoprefixer": "^10.4.21",
|
||||
"axios": "^1.15.0",
|
||||
"axios": "^1.15.2",
|
||||
"d3": "^7.9.0",
|
||||
"globals": "^17.5.0",
|
||||
"i18next": "^25.5.2",
|
||||
@@ -5903,16 +5903,42 @@
|
||||
}
|
||||
},
|
||||
"node_modules/axios": {
|
||||
"version": "1.15.0",
|
||||
"resolved": "https://registry.npmjs.org/axios/-/axios-1.15.0.tgz",
|
||||
"integrity": "sha512-wWyJDlAatxk30ZJer+GeCWS209sA42X+N5jU2jy6oHTp7ufw8uzUTVFBX9+wTfAlhiJXGS0Bq7X6efruWjuK9Q==",
|
||||
"version": "1.16.1",
|
||||
"resolved": "https://registry.npmjs.org/axios/-/axios-1.16.1.tgz",
|
||||
"integrity": "sha512-caYkukvroVPO8KrzuJEb50Hm07KwfBZPEC3VeFHTsqWHvKTsy54hjJz9BS/cdaypROE2rH6xvm9mHX4fgWkr3A==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"follow-redirects": "^1.15.11",
|
||||
"follow-redirects": "^1.16.0",
|
||||
"form-data": "^4.0.5",
|
||||
"https-proxy-agent": "^5.0.1",
|
||||
"proxy-from-env": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/axios/node_modules/agent-base": {
|
||||
"version": "6.0.2",
|
||||
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
|
||||
"integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"debug": "4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/axios/node_modules/https-proxy-agent": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz",
|
||||
"integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"agent-base": "6",
|
||||
"debug": "4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 6"
|
||||
}
|
||||
},
|
||||
"node_modules/axios/node_modules/proxy-from-env": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-2.1.0.tgz",
|
||||
@@ -9197,9 +9223,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/ip-address": {
|
||||
"version": "10.1.0",
|
||||
"resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.1.0.tgz",
|
||||
"integrity": "sha512-XXADHxXmvT9+CRxhXg56LJovE+bmWnEWB78LB83VZTprKTmaC5QfruXocxzTZ2Kl0DNwKuBdlIhjL8LeY8Sf8Q==",
|
||||
"version": "10.2.0",
|
||||
"resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.2.0.tgz",
|
||||
"integrity": "sha512-/+S6j4E9AHvW9SWMSEY9Xfy66O5PWvVEJ08O0y5JGyEKQpojb0K0GKpz/v5HJ/G0vi3D2sjGK78119oXZeE0qA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
|
||||
@@ -55,7 +55,7 @@
|
||||
"@tauri-apps/plugin-shell": "^2.3.5",
|
||||
"@userback/widget": "^0.3.12",
|
||||
"autoprefixer": "^10.4.21",
|
||||
"axios": "^1.15.0",
|
||||
"axios": "^1.15.2",
|
||||
"d3": "^7.9.0",
|
||||
"globals": "^17.5.0",
|
||||
"i18next": "^25.5.2",
|
||||
|
||||
@@ -1,105 +1,88 @@
|
||||
{
|
||||
"$schema": "../node_modules/@tauri-apps/cli/config.schema.json",
|
||||
"productName": "Stirling-PDF",
|
||||
"version": "2.11.0",
|
||||
"identifier": "stirling.pdf.dev",
|
||||
"build": {
|
||||
"frontendDist": "../dist",
|
||||
"devUrl": "http://localhost:5173",
|
||||
"beforeDevCommand": "npx vite --mode desktop",
|
||||
"beforeBuildCommand": "npx vite build --mode desktop"
|
||||
"$schema": "../node_modules/@tauri-apps/cli/config.schema.json",
|
||||
"productName": "Stirling-PDF",
|
||||
"version": "2.11.0",
|
||||
"identifier": "stirling.pdf.dev",
|
||||
"build": {
|
||||
"frontendDist": "../dist",
|
||||
"devUrl": "http://localhost:5173",
|
||||
"beforeDevCommand": "npx vite --mode desktop",
|
||||
"beforeBuildCommand": "npx vite build --mode desktop"
|
||||
},
|
||||
"app": {
|
||||
"windows": [
|
||||
{
|
||||
"title": "Stirling-PDF",
|
||||
"width": 1280,
|
||||
"height": 800,
|
||||
"resizable": true,
|
||||
"fullscreen": false,
|
||||
"additionalBrowserArgs": "--enable-features=CertVerifierBuiltinFeature"
|
||||
}
|
||||
]
|
||||
},
|
||||
"bundle": {
|
||||
"active": true,
|
||||
"publisher": "Stirling PDF Inc.",
|
||||
"targets": ["deb", "rpm", "appimage", "dmg", "msi"],
|
||||
"icon": [
|
||||
"icons/icon.png",
|
||||
"icons/icon.icns",
|
||||
"icons/icon.ico",
|
||||
"icons/16x16.png",
|
||||
"icons/32x32.png",
|
||||
"icons/64x64.png",
|
||||
"icons/128x128.png",
|
||||
"icons/192x192.png"
|
||||
],
|
||||
"resources": ["libs/*.jar", "runtime/jre/**/*"],
|
||||
"fileAssociations": [
|
||||
{
|
||||
"ext": ["pdf"],
|
||||
"name": "PDF Document",
|
||||
"role": "Editor",
|
||||
"mimeType": "application/pdf"
|
||||
}
|
||||
],
|
||||
"linux": {
|
||||
"deb": {
|
||||
"desktopTemplate": "stirling-pdf.desktop"
|
||||
},
|
||||
"rpm": {
|
||||
"desktopTemplate": "stirling-pdf.desktop"
|
||||
},
|
||||
"appimage": {
|
||||
"bundleMediaFramework": false
|
||||
}
|
||||
},
|
||||
"app": {
|
||||
"windows": [
|
||||
{
|
||||
"title": "Stirling-PDF",
|
||||
"width": 1280,
|
||||
"height": 800,
|
||||
"resizable": true,
|
||||
"fullscreen": false,
|
||||
"additionalBrowserArgs": "--enable-features=CertVerifierBuiltinFeature"
|
||||
}
|
||||
]
|
||||
"windows": {
|
||||
"certificateThumbprint": null,
|
||||
"digestAlgorithm": "sha256",
|
||||
"timestampUrl": "http://timestamp.digicert.com",
|
||||
"wix": {
|
||||
"fragmentPaths": ["windows/wix/provisioning.wxs"],
|
||||
"componentGroupRefs": ["ProvisioningComponentGroup"]
|
||||
}
|
||||
},
|
||||
"bundle": {
|
||||
"active": true,
|
||||
"publisher": "Stirling PDF Inc.",
|
||||
"targets": [
|
||||
"deb",
|
||||
"rpm",
|
||||
"appimage",
|
||||
"dmg",
|
||||
"msi"
|
||||
],
|
||||
"icon": [
|
||||
"icons/icon.png",
|
||||
"icons/icon.icns",
|
||||
"icons/icon.ico",
|
||||
"icons/16x16.png",
|
||||
"icons/32x32.png",
|
||||
"icons/64x64.png",
|
||||
"icons/128x128.png",
|
||||
"icons/192x192.png"
|
||||
],
|
||||
"resources": [
|
||||
"libs/*.jar",
|
||||
"runtime/jre/**/*"
|
||||
],
|
||||
"fileAssociations": [
|
||||
{
|
||||
"ext": [
|
||||
"pdf"
|
||||
],
|
||||
"name": "PDF Document",
|
||||
"role": "Editor",
|
||||
"mimeType": "application/pdf"
|
||||
}
|
||||
],
|
||||
"linux": {
|
||||
"deb": {
|
||||
"desktopTemplate": "stirling-pdf.desktop"
|
||||
},
|
||||
"rpm": {
|
||||
"desktopTemplate": "stirling-pdf.desktop"
|
||||
},
|
||||
"appimage": {
|
||||
"bundleMediaFramework": false
|
||||
}
|
||||
},
|
||||
"windows": {
|
||||
"certificateThumbprint": null,
|
||||
"digestAlgorithm": "sha256",
|
||||
"timestampUrl": "http://timestamp.digicert.com",
|
||||
"wix": {
|
||||
"fragmentPaths": [
|
||||
"windows/wix/provisioning.wxs"
|
||||
],
|
||||
"componentGroupRefs": [
|
||||
"ProvisioningComponentGroup"
|
||||
]
|
||||
}
|
||||
},
|
||||
"macOS": {
|
||||
"minimumSystemVersion": "10.15",
|
||||
"signingIdentity": null,
|
||||
"entitlements": null,
|
||||
"providerShortName": null,
|
||||
"infoPlist": "Info.plist"
|
||||
}
|
||||
},
|
||||
"plugins": {
|
||||
"shell": {
|
||||
"open": true
|
||||
},
|
||||
"fs": {
|
||||
"requireLiteralLeadingDot": false
|
||||
},
|
||||
"deep-link": {
|
||||
"desktop": {
|
||||
"schemes": [
|
||||
"stirlingpdf"
|
||||
]
|
||||
}
|
||||
}
|
||||
"macOS": {
|
||||
"minimumSystemVersion": "10.15",
|
||||
"signingIdentity": null,
|
||||
"entitlements": null,
|
||||
"providerShortName": null,
|
||||
"infoPlist": "Info.plist"
|
||||
}
|
||||
},
|
||||
"plugins": {
|
||||
"shell": {
|
||||
"open": true
|
||||
},
|
||||
"fs": {
|
||||
"requireLiteralLeadingDot": false
|
||||
},
|
||||
"deep-link": {
|
||||
"desktop": {
|
||||
"schemes": ["stirlingpdf"]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ import {
|
||||
extractLatestFilesFromBundle,
|
||||
parseContentDispositionFilename,
|
||||
} from "@app/services/shareBundleUtils";
|
||||
import { getHeaderValue } from "@app/services/httpHeaderUtils";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { openFilesFromDisk } from "@app/services/openFilesFromDisk";
|
||||
export { pendingFilePathMappings } from "@app/services/pendingFilePathMappings";
|
||||
@@ -893,16 +894,11 @@ export const FileManagerProvider: React.FC<FileManagerProviderProps> = ({
|
||||
skipAuthRedirect: true,
|
||||
} as any,
|
||||
);
|
||||
const contentType =
|
||||
(response.headers &&
|
||||
(response.headers["content-type"] ||
|
||||
response.headers["Content-Type"])) ||
|
||||
"";
|
||||
const disposition =
|
||||
(response.headers &&
|
||||
(response.headers["content-disposition"] ||
|
||||
response.headers["Content-Disposition"])) ||
|
||||
"";
|
||||
const contentType = getHeaderValue(response.headers, "content-type");
|
||||
const disposition = getHeaderValue(
|
||||
response.headers,
|
||||
"content-disposition",
|
||||
);
|
||||
const filename =
|
||||
parseContentDispositionFilename(disposition) ||
|
||||
file.name ||
|
||||
|
||||
@@ -20,6 +20,7 @@ import {
|
||||
loadShareBundleEntries,
|
||||
parseContentDispositionFilename,
|
||||
} from "@app/services/shareBundleUtils";
|
||||
import { getHeaderValue } from "@app/services/httpHeaderUtils";
|
||||
|
||||
interface FilesModalContextType {
|
||||
isFilesModalOpen: boolean;
|
||||
@@ -173,16 +174,8 @@ export const FilesModalProvider: React.FC<{ children: React.ReactNode }> = ({
|
||||
skipAuthRedirect: true,
|
||||
} as any,
|
||||
);
|
||||
const contentType =
|
||||
(response.headers &&
|
||||
(response.headers["content-type"] ||
|
||||
response.headers["Content-Type"])) ||
|
||||
"";
|
||||
const disposition =
|
||||
(response.headers &&
|
||||
(response.headers["content-disposition"] ||
|
||||
response.headers["Content-Disposition"])) ||
|
||||
"";
|
||||
const contentType = getHeaderValue(response.headers, "content-type");
|
||||
const disposition = getHeaderValue(response.headers, "content-disposition");
|
||||
const filename =
|
||||
parseContentDispositionFilename(disposition) || "server-file";
|
||||
const blob = response.data as Blob;
|
||||
@@ -199,16 +192,8 @@ export const FilesModalProvider: React.FC<{ children: React.ReactNode }> = ({
|
||||
skipAuthRedirect: true,
|
||||
} as any,
|
||||
);
|
||||
const contentType =
|
||||
(response.headers &&
|
||||
(response.headers["content-type"] ||
|
||||
response.headers["Content-Type"])) ||
|
||||
"";
|
||||
const disposition =
|
||||
(response.headers &&
|
||||
(response.headers["content-disposition"] ||
|
||||
response.headers["Content-Disposition"])) ||
|
||||
"";
|
||||
const contentType = getHeaderValue(response.headers, "content-type");
|
||||
const disposition = getHeaderValue(response.headers, "content-disposition");
|
||||
const filename =
|
||||
parseContentDispositionFilename(disposition) || "shared-file";
|
||||
const blob = response.data as Blob;
|
||||
@@ -241,6 +226,11 @@ export const FilesModalProvider: React.FC<{ children: React.ReactNode }> = ({
|
||||
// Use custom handler for special cases (like page insertion)
|
||||
customHandler(files, insertAfterPage);
|
||||
} else {
|
||||
// Snapshot selection before upload; addFiles may replace the current
|
||||
// selection with only newly uploaded files.
|
||||
const previouslySelected = fileCtx.selectors
|
||||
.getSelectedStirlingFileStubs()
|
||||
.map((s) => s.id);
|
||||
// 1) Add via standard flow (auto-selects new files)
|
||||
await addFiles(files);
|
||||
// 2) Merge all requested file IDs (covers already-present files too)
|
||||
@@ -252,7 +242,7 @@ export const FilesModalProvider: React.FC<{ children: React.ReactNode }> = ({
|
||||
.getSelectedStirlingFileStubs()
|
||||
.map((s) => s.id);
|
||||
const nextSelection = Array.from(
|
||||
new Set([...currentSelected, ...ids]),
|
||||
new Set([...previouslySelected, ...currentSelected, ...ids]),
|
||||
);
|
||||
actions.setSelectedFiles(nextSelection);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
type HeaderPrimitive = string | number | boolean;
|
||||
|
||||
function normalizeHeaderValue(value: unknown): string | undefined {
|
||||
if (typeof value === "string") {
|
||||
return value;
|
||||
}
|
||||
if (typeof value === "number" || typeof value === "boolean") {
|
||||
return String(value);
|
||||
}
|
||||
if (Array.isArray(value)) {
|
||||
const stringValues = value.filter(
|
||||
(entry): entry is HeaderPrimitive =>
|
||||
typeof entry === "string" ||
|
||||
typeof entry === "number" ||
|
||||
typeof entry === "boolean",
|
||||
);
|
||||
return stringValues.length > 0
|
||||
? stringValues.map(String).join(", ")
|
||||
: undefined;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
export function getHeaderValue(headers: unknown, headerName: string): string {
|
||||
const normalizedName = headerName.toLowerCase();
|
||||
|
||||
if (!headers || typeof headers !== "object") {
|
||||
return "";
|
||||
}
|
||||
|
||||
const maybeHeaders = headers as Record<string, unknown> & {
|
||||
get?: (name: string) => unknown;
|
||||
};
|
||||
|
||||
const directValue =
|
||||
maybeHeaders[headerName] ??
|
||||
maybeHeaders[normalizedName] ??
|
||||
maybeHeaders[headerName.toUpperCase()];
|
||||
const normalizedDirect = normalizeHeaderValue(directValue);
|
||||
if (normalizedDirect) {
|
||||
return normalizedDirect;
|
||||
}
|
||||
|
||||
if (typeof maybeHeaders.get === "function") {
|
||||
const fromGetter = normalizeHeaderValue(maybeHeaders.get(headerName));
|
||||
if (fromGetter) {
|
||||
return fromGetter;
|
||||
}
|
||||
}
|
||||
|
||||
for (const [key, value] of Object.entries(maybeHeaders)) {
|
||||
if (key.toLowerCase() === normalizedName) {
|
||||
const normalized = normalizeHeaderValue(value);
|
||||
if (normalized) {
|
||||
return normalized;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
import apiClient from "@app/services/apiClient";
|
||||
import { getHeaderValue } from "@app/services/httpHeaderUtils";
|
||||
import type { SavedSignature } from "@app/types/signature";
|
||||
|
||||
export type StorageType = "backend" | "localStorage";
|
||||
@@ -166,7 +167,9 @@ class SignatureStorageService {
|
||||
|
||||
// Convert to data URL (base64) for both display and use
|
||||
const blob = new Blob([imageResponse.data], {
|
||||
type: imageResponse.headers["content-type"] || "image/png",
|
||||
type:
|
||||
getHeaderValue(imageResponse.headers, "content-type") ||
|
||||
"image/png",
|
||||
});
|
||||
|
||||
const dataUrl = await new Promise<string>((resolve, reject) => {
|
||||
|
||||
@@ -16,6 +16,7 @@ import {
|
||||
loadShareBundleEntries,
|
||||
parseContentDispositionFilename,
|
||||
} from "@app/services/shareBundleUtils";
|
||||
import { getHeaderValue } from "@app/services/httpHeaderUtils";
|
||||
|
||||
interface ShareLinkLoaderProps {
|
||||
token: string;
|
||||
@@ -78,16 +79,11 @@ export default function ShareLinkLoader({ token }: ShareLinkLoaderProps) {
|
||||
);
|
||||
if (signal.aborted) return;
|
||||
|
||||
const contentType =
|
||||
(response.headers &&
|
||||
(response.headers["content-type"] ||
|
||||
response.headers["Content-Type"])) ||
|
||||
"";
|
||||
const disposition =
|
||||
(response.headers &&
|
||||
(response.headers["content-disposition"] ||
|
||||
response.headers["Content-Disposition"])) ||
|
||||
"";
|
||||
const contentType = getHeaderValue(response.headers, "content-type");
|
||||
const disposition = getHeaderValue(
|
||||
response.headers,
|
||||
"content-disposition",
|
||||
);
|
||||
const filename =
|
||||
parseContentDispositionFilename(disposition) || "shared-file";
|
||||
const blob = response.data as Blob;
|
||||
|
||||
@@ -9,6 +9,7 @@ import {
|
||||
loadShareBundleEntries,
|
||||
parseContentDispositionFilename,
|
||||
} from "@app/services/shareBundleUtils";
|
||||
import { getHeaderValue } from "@app/services/httpHeaderUtils";
|
||||
|
||||
export interface ShareLinkMetadata {
|
||||
shareToken?: string;
|
||||
@@ -44,15 +45,8 @@ export async function downloadShareLink(token: string): Promise<{
|
||||
suppressErrorToast: true,
|
||||
skipAuthRedirect: true,
|
||||
});
|
||||
const contentType =
|
||||
(response.headers &&
|
||||
(response.headers["content-type"] || response.headers["Content-Type"])) ||
|
||||
"";
|
||||
const disposition =
|
||||
(response.headers &&
|
||||
(response.headers["content-disposition"] ||
|
||||
response.headers["Content-Disposition"])) ||
|
||||
"";
|
||||
const contentType = getHeaderValue(response.headers, "content-type");
|
||||
const disposition = getHeaderValue(response.headers, "content-disposition");
|
||||
const filename =
|
||||
parseContentDispositionFilename(disposition) || "shared-file";
|
||||
const blob = response.data as Blob;
|
||||
|
||||
Reference in New Issue
Block a user