mirror of
https://github.com/arsvendg/Stirling-PDF.git
synced 2026-07-14 10:34:06 +02:00
Fix any type usage in desktop/ (#6033)
# Description of Changes Follow on from #5949, expanding any type usage ban to the `desktop/` folder Also gets rid of a bunch of really verbose desktop logging that I don't think we really need anymore (or ever needed tbh, most of it doesn't make sense) because it was using a bunch of `any` typing and wasn't worth fixing.
This commit is contained in:
@@ -78,6 +78,7 @@ export default defineConfig(
|
|||||||
// Folders that have been cleaned up and are now conformant - stricter rules enforced here
|
// Folders that have been cleaned up and are now conformant - stricter rules enforced here
|
||||||
{
|
{
|
||||||
files: [
|
files: [
|
||||||
|
"src/desktop/**/*.{js,mjs,jsx,ts,tsx}",
|
||||||
"src/proprietary/**/*.{js,mjs,jsx,ts,tsx}",
|
"src/proprietary/**/*.{js,mjs,jsx,ts,tsx}",
|
||||||
"src/saas/**/*.{js,mjs,jsx,ts,tsx}",
|
"src/saas/**/*.{js,mjs,jsx,ts,tsx}",
|
||||||
"src/prototypes/**/*.{js,mjs,jsx,ts,tsx}",
|
"src/prototypes/**/*.{js,mjs,jsx,ts,tsx}",
|
||||||
|
|||||||
@@ -95,9 +95,9 @@ export function DesktopOnboardingModal() {
|
|||||||
<div className={styles.heroWrapper} style={{ flexShrink: 0 }}>
|
<div className={styles.heroWrapper} style={{ flexShrink: 0 }}>
|
||||||
<AnimatedSlideBackground
|
<AnimatedSlideBackground
|
||||||
gradientStops={
|
gradientStops={
|
||||||
(step === 0
|
step === 0
|
||||||
? welcomeSlide.background.gradientStops
|
? welcomeSlide.background.gradientStops
|
||||||
: SIGN_IN_GRADIENT) as [string, string]
|
: SIGN_IN_GRADIENT
|
||||||
}
|
}
|
||||||
circles={welcomeSlide.background.circles}
|
circles={welcomeSlide.background.circles}
|
||||||
isActive
|
isActive
|
||||||
|
|||||||
@@ -24,9 +24,7 @@ export const ServerSelection: React.FC<ServerSelectionProps> = ({
|
|||||||
const [securityDisabled, setSecurityDisabled] = useState(false);
|
const [securityDisabled, setSecurityDisabled] = useState(false);
|
||||||
const serverUrl = localStorage.getItem("server_url") || "";
|
const serverUrl = localStorage.getItem("server_url") || "";
|
||||||
|
|
||||||
const handleSubmit = async (e: React.FormEvent) => {
|
const submitServerUrl = async () => {
|
||||||
e.preventDefault();
|
|
||||||
|
|
||||||
// Normalize and validate URL
|
// Normalize and validate URL
|
||||||
let url = customUrl.trim().replace(/\/+$/, "") || serverUrl;
|
let url = customUrl.trim().replace(/\/+$/, "") || serverUrl;
|
||||||
|
|
||||||
@@ -243,7 +241,12 @@ export const ServerSelection: React.FC<ServerSelectionProps> = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<form onSubmit={handleSubmit}>
|
<form
|
||||||
|
onSubmit={(e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
void submitServerUrl();
|
||||||
|
}}
|
||||||
|
>
|
||||||
<Stack gap="md">
|
<Stack gap="md">
|
||||||
<TextInput
|
<TextInput
|
||||||
label={t("setup.server.url.label", "Server URL")}
|
label={t("setup.server.url.label", "Server URL")}
|
||||||
@@ -321,7 +324,7 @@ export const ServerSelection: React.FC<ServerSelectionProps> = ({
|
|||||||
setCustomUrl(serverUrl);
|
setCustomUrl(serverUrl);
|
||||||
// Auto-submit the form after setting the URL
|
// Auto-submit the form after setting the URL
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
handleSubmit(new Event("submit") as any);
|
void submitServerUrl();
|
||||||
}, 0);
|
}, 0);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -140,7 +140,7 @@ export function SelfHostedOfflineBanner() {
|
|||||||
toolAvailability[id]?.reason === "selfHostedOffline",
|
toolAvailability[id]?.reason === "selfHostedOffline",
|
||||||
)
|
)
|
||||||
.map((id) => toolRegistry[id]?.name ?? id)
|
.map((id) => toolRegistry[id]?.name ?? id)
|
||||||
.filter(Boolean) as string[];
|
.filter(Boolean);
|
||||||
|
|
||||||
// Use translated tool names from the registry as prefixes
|
// Use translated tool names from the registry as prefixes
|
||||||
const convertPrefix = toolRegistry["convert" as ToolId]?.name ?? "Convert";
|
const convertPrefix = toolRegistry["convert" as ToolId]?.name ?? "Convert";
|
||||||
|
|||||||
@@ -3,12 +3,10 @@ import CoreToolButton from "@core/components/tools/toolPicker/ToolButton";
|
|||||||
import { getToolDisabledReason } from "@app/components/tools/fullscreen/shared";
|
import { getToolDisabledReason } from "@app/components/tools/fullscreen/shared";
|
||||||
import { useToolWorkflow } from "@app/contexts/ToolWorkflowContext";
|
import { useToolWorkflow } from "@app/contexts/ToolWorkflowContext";
|
||||||
import { useAppConfig } from "@app/contexts/AppConfigContext";
|
import { useAppConfig } from "@app/contexts/AppConfigContext";
|
||||||
import { ToolRegistryEntry } from "@app/data/toolsTaxonomy";
|
|
||||||
import {
|
import {
|
||||||
connectionModeService,
|
connectionModeService,
|
||||||
type ConnectionMode,
|
type ConnectionMode,
|
||||||
} from "@app/services/connectionModeService";
|
} from "@app/services/connectionModeService";
|
||||||
import type { ToolId } from "@app/types/toolId";
|
|
||||||
|
|
||||||
type CoreToolButtonProps = React.ComponentProps<typeof CoreToolButton>;
|
type CoreToolButtonProps = React.ComponentProps<typeof CoreToolButton>;
|
||||||
|
|
||||||
@@ -35,8 +33,8 @@ const ToolButton: React.FC<CoreToolButtonProps> = (props) => {
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const disabledReason = getToolDisabledReason(
|
const disabledReason = getToolDisabledReason(
|
||||||
props.id as string,
|
props.id,
|
||||||
props.tool as ToolRegistryEntry,
|
props.tool,
|
||||||
toolAvailability,
|
toolAvailability,
|
||||||
premiumEnabled,
|
premiumEnabled,
|
||||||
);
|
);
|
||||||
@@ -49,7 +47,7 @@ const ToolButton: React.FC<CoreToolButtonProps> = (props) => {
|
|||||||
connectionMode === "local" &&
|
connectionMode === "local" &&
|
||||||
disabledReason !== "comingSoon" &&
|
disabledReason !== "comingSoon" &&
|
||||||
disabledReason !== "selfHostedOffline"
|
disabledReason !== "selfHostedOffline"
|
||||||
? () => handleToolSelectForced(props.id as ToolId)
|
? () => handleToolSelectForced(props.id)
|
||||||
: undefined;
|
: undefined;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -15,11 +15,8 @@ import { isTauri } from "@tauri-apps/api/core";
|
|||||||
export function getApiBaseUrl(): string {
|
export function getApiBaseUrl(): string {
|
||||||
if (!isTauri()) {
|
if (!isTauri()) {
|
||||||
// Runtime override to fix hardcoded localhost in builds
|
// Runtime override to fix hardcoded localhost in builds
|
||||||
if (
|
if (typeof window !== "undefined" && window.STIRLING_PDF_API_BASE_URL) {
|
||||||
typeof window !== "undefined" &&
|
return window.STIRLING_PDF_API_BASE_URL;
|
||||||
(window as any).STIRLING_PDF_API_BASE_URL
|
|
||||||
) {
|
|
||||||
return (window as any).STIRLING_PDF_API_BASE_URL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return import.meta.env.VITE_API_BASE_URL;
|
return import.meta.env.VITE_API_BASE_URL;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { invoke } from "@tauri-apps/api/core";
|
import { invoke, isTauri } from "@tauri-apps/api/core";
|
||||||
import { fetch } from "@tauri-apps/plugin-http";
|
import { fetch } from "@tauri-apps/plugin-http";
|
||||||
import { endpointAvailabilityService } from "@app/services/endpointAvailabilityService";
|
import { endpointAvailabilityService } from "@app/services/endpointAvailabilityService";
|
||||||
import { selfHostedServerMonitor } from "@app/services/selfHostedServerMonitor";
|
import { selfHostedServerMonitor } from "@app/services/selfHostedServerMonitor";
|
||||||
@@ -240,90 +240,11 @@ export class ConnectionModeService {
|
|||||||
*/
|
*/
|
||||||
async testConnection(url: string): Promise<ConnectionTestResult> {
|
async testConnection(url: string): Promise<ConnectionTestResult> {
|
||||||
console.log(
|
console.log(
|
||||||
`[ConnectionModeService] 🔍 Starting comprehensive connection diagnostics for: ${url}`,
|
`[ConnectionModeService] 🔍 Starting connection diagnostics for: ${url}`,
|
||||||
);
|
);
|
||||||
console.log(
|
console.log(
|
||||||
`[ConnectionModeService] ==================== DIAGNOSTIC SESSION START ====================`,
|
`[ConnectionModeService] System: online=${navigator.onLine}, tauri=${isTauri()}, concurrency=${navigator.hardwareConcurrency || "unknown"}`,
|
||||||
);
|
);
|
||||||
console.log(`[ConnectionModeService] System Information:`);
|
|
||||||
console.log(
|
|
||||||
`[ConnectionModeService] - User Agent: ${navigator.userAgent}`,
|
|
||||||
);
|
|
||||||
console.log(`[ConnectionModeService] - Platform: ${navigator.platform}`);
|
|
||||||
console.log(`[ConnectionModeService] - Online: ${navigator.onLine}`);
|
|
||||||
console.log(
|
|
||||||
`[ConnectionModeService] - Connection Type: ${(navigator as any).connection?.effectiveType || "unknown"}`,
|
|
||||||
);
|
|
||||||
console.log(`[ConnectionModeService] - Language: ${navigator.language}`);
|
|
||||||
console.log(
|
|
||||||
`[ConnectionModeService] - Cookies Enabled: ${navigator.cookieEnabled}`,
|
|
||||||
);
|
|
||||||
console.log(
|
|
||||||
`[ConnectionModeService] - Hardware Concurrency: ${navigator.hardwareConcurrency || "unknown"} cores`,
|
|
||||||
);
|
|
||||||
console.log(
|
|
||||||
`[ConnectionModeService] - Max Touch Points: ${navigator.maxTouchPoints}`,
|
|
||||||
);
|
|
||||||
|
|
||||||
// Check for proxy environment variables
|
|
||||||
console.log(`[ConnectionModeService] Environment Check:`);
|
|
||||||
const envProxy =
|
|
||||||
(window as any).process?.env?.HTTP_PROXY ||
|
|
||||||
(window as any).process?.env?.HTTPS_PROXY;
|
|
||||||
if (envProxy) {
|
|
||||||
console.log(`[ConnectionModeService] - Proxy detected: ${envProxy}`);
|
|
||||||
} else {
|
|
||||||
console.log(
|
|
||||||
`[ConnectionModeService] - No proxy environment variables detected`,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if running in Tauri (v2 uses different detection)
|
|
||||||
console.log(`[ConnectionModeService] - Checking Tauri context...`);
|
|
||||||
console.log(
|
|
||||||
`[ConnectionModeService] - window.__TAURI__ type: ${typeof (window as any).__TAURI__}`,
|
|
||||||
);
|
|
||||||
console.log(
|
|
||||||
`[ConnectionModeService] - window.__TAURI_INTERNALS__ type: ${typeof (window as any).__TAURI_INTERNALS__}`,
|
|
||||||
);
|
|
||||||
console.log(
|
|
||||||
`[ConnectionModeService] - window.location.href:`,
|
|
||||||
window.location.href,
|
|
||||||
);
|
|
||||||
console.log(
|
|
||||||
`[ConnectionModeService] - window.location.protocol:`,
|
|
||||||
window.location.protocol,
|
|
||||||
);
|
|
||||||
|
|
||||||
// Tauri v2 detection: check for __TAURI_INTERNALS__ or tauri:// protocol
|
|
||||||
const isTauriV2 =
|
|
||||||
typeof (window as any).__TAURI_INTERNALS__ !== "undefined" ||
|
|
||||||
window.location.protocol === "tauri:" ||
|
|
||||||
window.location.hostname === "tauri.localhost";
|
|
||||||
const isTauriV1 = typeof (window as any).__TAURI__ !== "undefined";
|
|
||||||
const isTauri = isTauriV1 || isTauriV2;
|
|
||||||
|
|
||||||
console.log(
|
|
||||||
`[ConnectionModeService] - Running in Tauri v1: ${isTauriV1}`,
|
|
||||||
);
|
|
||||||
console.log(
|
|
||||||
`[ConnectionModeService] - Running in Tauri v2: ${isTauriV2}`,
|
|
||||||
);
|
|
||||||
console.log(`[ConnectionModeService] - Running in Tauri: ${isTauri}`);
|
|
||||||
|
|
||||||
if (isTauri) {
|
|
||||||
if (isTauriV1) {
|
|
||||||
const tauriApi = (window as any).__TAURI__;
|
|
||||||
console.log(`[ConnectionModeService] - Tauri v1 API:`, tauriApi);
|
|
||||||
}
|
|
||||||
if (isTauriV2) {
|
|
||||||
console.log(
|
|
||||||
`[ConnectionModeService] - Tauri v2 detected via internals/protocol`,
|
|
||||||
);
|
|
||||||
const internals = (window as any).__TAURI_INTERNALS__;
|
|
||||||
console.log(`[ConnectionModeService] - Tauri internals:`, internals);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const diagnostics: DiagnosticResult[] = [];
|
const diagnostics: DiagnosticResult[] = [];
|
||||||
const healthUrl = `${url.replace(/\/$/, "")}/api/v1/info/status`;
|
const healthUrl = `${url.replace(/\/$/, "")}/api/v1/info/status`;
|
||||||
@@ -723,7 +644,13 @@ export class ConnectionModeService {
|
|||||||
`[ConnectionModeService] - Certificate validation: ${disableCertValidation ? "DISABLED" : "ENABLED"}`,
|
`[ConnectionModeService] - Certificate validation: ${disableCertValidation ? "DISABLED" : "ENABLED"}`,
|
||||||
);
|
);
|
||||||
|
|
||||||
const fetchOptions: any = {
|
const fetchOptions: RequestInit & {
|
||||||
|
connectTimeout?: number;
|
||||||
|
danger?: {
|
||||||
|
acceptInvalidCerts: boolean;
|
||||||
|
acceptInvalidHostnames: boolean;
|
||||||
|
};
|
||||||
|
} = {
|
||||||
method: "GET",
|
method: "GET",
|
||||||
connectTimeout: 10000,
|
connectTimeout: 10000,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -200,11 +200,14 @@ export class EndpointAvailabilityService {
|
|||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
const now = Date.now();
|
const now = Date.now();
|
||||||
|
|
||||||
Object.entries(data).forEach(([endpoint, details]: [string, any]) => {
|
Object.entries(data).forEach(
|
||||||
const available = details?.enabled ?? false;
|
([endpoint, details]: [string, unknown]) => {
|
||||||
this.localCache.set(endpoint, available);
|
const available =
|
||||||
this.localCacheExpiry.set(endpoint, now + this.CACHE_DURATION);
|
(details as { enabled?: boolean })?.enabled ?? false;
|
||||||
});
|
this.localCache.set(endpoint, available);
|
||||||
|
this.localCacheExpiry.set(endpoint, now + this.CACHE_DURATION);
|
||||||
|
},
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
console.warn(
|
console.warn(
|
||||||
`[endpointAvailabilityService] Failed to preload endpoints: ${response.status}`,
|
`[endpointAvailabilityService] Failed to preload endpoints: ${response.status}`,
|
||||||
@@ -313,5 +316,5 @@ export const endpointAvailabilityService = new EndpointAvailabilityService();
|
|||||||
|
|
||||||
// Expose to window for debugging
|
// Expose to window for debugging
|
||||||
if (typeof window !== "undefined") {
|
if (typeof window !== "undefined") {
|
||||||
(window as any).endpointAvailabilityService = endpointAvailabilityService;
|
window.endpointAvailabilityService = endpointAvailabilityService;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { isAxiosError } from "axios";
|
||||||
import { handleHttpError as coreHandleHttpError } from "@core/services/httpErrorHandler";
|
import { handleHttpError as coreHandleHttpError } from "@core/services/httpErrorHandler";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -6,8 +7,8 @@ import { handleHttpError as coreHandleHttpError } from "@core/services/httpError
|
|||||||
* login page must not appear. Instead, open the SignInModal for re-authentication.
|
* login page must not appear. Instead, open the SignInModal for re-authentication.
|
||||||
* All other error handling delegates to the core implementation.
|
* All other error handling delegates to the core implementation.
|
||||||
*/
|
*/
|
||||||
export async function handleHttpError(error: any): Promise<boolean> {
|
export async function handleHttpError(error: unknown): Promise<boolean> {
|
||||||
const status: number | undefined = error?.response?.status;
|
const status = isAxiosError(error) ? error.response?.status : undefined;
|
||||||
|
|
||||||
if (status === 401) {
|
if (status === 401) {
|
||||||
// In desktop builds, 401s are handled by the auth service (token refresh + toast
|
// In desktop builds, 401s are handled by the auth service (token refresh + toast
|
||||||
|
|||||||
@@ -98,7 +98,7 @@ export async function saveMultipleFilesWithPrompt(
|
|||||||
try {
|
try {
|
||||||
const fileName =
|
const fileName =
|
||||||
file instanceof File ? file.name : `output_${savedCount + 1}.pdf`;
|
file instanceof File ? file.name : `output_${savedCount + 1}.pdf`;
|
||||||
const filePath = await join(selectedFolder as string, fileName);
|
const filePath = await join(selectedFolder, fileName);
|
||||||
const arrayBuffer = await file.arrayBuffer();
|
const arrayBuffer = await file.arrayBuffer();
|
||||||
await writeFile(filePath, new Uint8Array(arrayBuffer));
|
await writeFile(filePath, new Uint8Array(arrayBuffer));
|
||||||
savedCount++;
|
savedCount++;
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { isAxiosError } from "axios";
|
||||||
import { extractAxiosErrorMessage } from "@app/services/httpErrorUtils";
|
import { extractAxiosErrorMessage } from "@app/services/httpErrorUtils";
|
||||||
import { alert } from "@app/components/toast";
|
import { alert } from "@app/components/toast";
|
||||||
|
|
||||||
@@ -12,7 +13,11 @@ import { alert } from "@app/components/toast";
|
|||||||
* false if this is not a SaaS error.
|
* false if this is not a SaaS error.
|
||||||
*/
|
*/
|
||||||
export function handleSaaSError(error: unknown): boolean {
|
export function handleSaaSError(error: unknown): boolean {
|
||||||
if ((error as any)?.config?._isSaaSRequest !== true) return false;
|
if (
|
||||||
|
!isAxiosError(error) ||
|
||||||
|
(error.config as { _isSaaSRequest?: boolean })?._isSaaSRequest !== true
|
||||||
|
)
|
||||||
|
return false;
|
||||||
|
|
||||||
const { title: originalTitle, body: originalBody } =
|
const { title: originalTitle, body: originalBody } =
|
||||||
extractAxiosErrorMessage(error);
|
extractAxiosErrorMessage(error);
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
/* eslint-disable @typescript-eslint/no-explicit-any -- Axios-compatible API requires matching axios's `any` signatures */
|
||||||
import { fetch } from "@tauri-apps/plugin-http";
|
import { fetch } from "@tauri-apps/plugin-http";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -231,7 +232,12 @@ class TauriHttpClient {
|
|||||||
|
|
||||||
// Make the request using Tauri's native HTTP client (standard Fetch API)
|
// Make the request using Tauri's native HTTP client (standard Fetch API)
|
||||||
// Enable certificate bypass for HTTPS to handle missing intermediate certs and self-signed certs
|
// Enable certificate bypass for HTTPS to handle missing intermediate certs and self-signed certs
|
||||||
const fetchOptions: any = {
|
const fetchOptions: RequestInit & {
|
||||||
|
danger?: {
|
||||||
|
acceptInvalidCerts: boolean;
|
||||||
|
acceptInvalidHostnames: boolean;
|
||||||
|
};
|
||||||
|
} = {
|
||||||
method,
|
method,
|
||||||
headers,
|
headers,
|
||||||
body,
|
body,
|
||||||
|
|||||||
Vendored
+2
@@ -15,6 +15,8 @@ declare module "assets/material-symbols-icons.json" {
|
|||||||
declare global {
|
declare global {
|
||||||
interface Window {
|
interface Window {
|
||||||
__STIRLING_PDF_BASE_URL__?: string;
|
__STIRLING_PDF_BASE_URL__?: string;
|
||||||
|
STIRLING_PDF_API_BASE_URL?: string;
|
||||||
|
endpointAvailabilityService?: unknown;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user