Compare commits

..

1 Commits

Author SHA1 Message Date
NimBold ac0e288cd8 test(startup): isolate Aria2 WebSocket crash path (#37)
- Issue #37: add a smoke-only switch that stops the Aria2 WebSocket loop.\n- Keep the daemon and poller paths active for a focused delayed-startup comparison.\n\nRefs #37.
2026-08-27 20:01:13 +03:30
3 changed files with 73 additions and 9 deletions
+2 -1
View File
@@ -29,7 +29,8 @@ const child = spawn(executable, [], {
detached: process.platform !== 'win32',
env: {
...process.env,
FIRELINK_SMOKE_TEST: '1',
FIRELINK_SMOKE_TEST: '1',
FIRELINK_DISABLE_ARIA2_WEBSOCKET: '1',
WEBKIT_DISABLE_COMPOSITING_MODE: '1',
GDK_BACKEND: 'x11',
},
+3
View File
@@ -18854,6 +18854,9 @@ pub fn run() {
}
}
if std::env::var_os("FIRELINK_DISABLE_ARIA2_WEBSOCKET").is_some() {
return;
}
let mut ws_retries = 0;
loop {
if ws_retries == 10 {
+68 -8
View File
@@ -1,4 +1,4 @@
import { StrictMode } from "react";
import { StrictMode, type ComponentType } from "react";
import { createRoot } from "react-dom/client";
import "@fontsource-variable/inter/wght.css";
import "@fontsource-variable/noto-sans-hebrew/wght.css";
@@ -7,11 +7,15 @@ import "@fontsource-variable/outfit/wght.css";
import "@fontsource-variable/roboto/wght.css";
import "@fontsource-variable/vazirmatn/wght.css";
import "./index.css";
import App from "./App";
import { i18nReady } from "./i18n";
import { ErrorBoundary } from "./components/ErrorBoundary";
import { ToastProvider } from "./contexts/ToastContext";
import { error as logError, warn as logWarn, initLogger } from "./utils/logger";
import { getCurrentWindow } from '@tauri-apps/api/window';
import { invokeCommand as invoke } from './ipc';
const isPropertiesWindow = getCurrentWindow().label.startsWith('properties-');
void initLogger();
const serializeConsoleArguments = (values: unknown[]) => values.map(value => {
@@ -40,24 +44,80 @@ console.warn = (...values: unknown[]) => {
};
const rootElement = document.getElementById("root");
const renderApp = () => {
const renderRoot = (RootComponent: ComponentType) => {
if (!rootElement) return;
createRoot(rootElement).render(
<StrictMode>
<ErrorBoundary>
<ToastProvider>
<App />
<RootComponent />
</ToastProvider>
</ErrorBoundary>
</StrictMode>,
);
};
void i18nReady.then(renderApp).catch(error => {
console.error('Failed to initialize localization:', error);
renderApp();
});
const PropertiesStartupFailure = () => (
<main className="properties-window-shell flex h-screen min-h-0 flex-col items-center justify-center gap-4 bg-main-bg p-6 text-text-primary">
<p role="alert">Download Properties could not be loaded.</p>
<button
type="button"
className="app-button app-button-primary px-3 text-xs"
onClick={() => {
void getCurrentWindow().close().catch(error => {
console.error('[PropertiesStartupFailure] close failed', error);
});
}}
>
Close
</button>
</main>
);
const renderMainApp = async () => {
if (!rootElement) return;
// Keep the child entrypoint isolated from the main application module. App
// imports the persistent Zustand stores, whose module initialization issues
// main-window-only IPC commands. Loading it in a Properties child creates a
// second persistence owner and can race the bridge handshake.
const RootComponent = (await import('./App')).default;
renderRoot(RootComponent);
};
const renderPropertiesApp = async () => {
if (!rootElement) return;
try {
// Properties starts with the synchronous English catalog and changes locale
// after its first paint. Waiting for a lazy locale chunk here delays the
// loading shell and makes native window startup visible to the user.
const RootComponent = (await import('./components/PropertiesWindowApp')).PropertiesWindowApp;
renderRoot(RootComponent);
} catch (error) {
// A failed lazy chunk must not leave the native window hidden forever. Show
// a styled, closable failure state and use the same caller-validated native
// reveal command as the normal child path.
console.error('Failed to initialize the Properties window:', error);
renderRoot(PropertiesStartupFailure);
const fallbackSessionId = crypto.randomUUID();
void invoke('properties_window_send_ready', { sessionId: fallbackSessionId })
.then(() => invoke('properties_window_reveal', { sessionId: fallbackSessionId }))
.catch(revealError => {
console.error('Failed to reveal the Properties startup error:', revealError);
});
}
};
if (isPropertiesWindow) {
void renderPropertiesApp();
} else {
void i18nReady.then(renderMainApp).catch(error => {
console.error('Failed to initialize localization:', error);
void renderMainApp();
});
}
// Prevent the webview's default context menu ("Reload", etc.) on right-click.
// Individual components that provide custom context menus call preventDefault()