mirror of
https://github.com/nimbold/Firelink.git
synced 2026-09-02 14:07:57 +00:00
fix(properties): harden child window startup and lifecycle
This commit is contained in:
+60
-14
@@ -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";
|
||||
@@ -12,6 +12,7 @@ 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-');
|
||||
|
||||
@@ -43,17 +44,9 @@ console.warn = (...values: unknown[]) => {
|
||||
};
|
||||
|
||||
const rootElement = document.getElementById("root");
|
||||
const renderApp = async () => {
|
||||
const renderRoot = (RootComponent: ComponentType) => {
|
||||
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 = isPropertiesWindow
|
||||
? (await import('./components/PropertiesWindowApp')).PropertiesWindowApp
|
||||
: (await import('./App')).default;
|
||||
|
||||
createRoot(rootElement).render(
|
||||
<StrictMode>
|
||||
<ErrorBoundary>
|
||||
@@ -65,10 +58,63 @@ const renderApp = async () => {
|
||||
);
|
||||
};
|
||||
|
||||
void i18nReady.then(renderApp).catch(error => {
|
||||
console.error('Failed to initialize localization:', error);
|
||||
void 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);
|
||||
void invoke('properties_window_reveal').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()
|
||||
|
||||
Reference in New Issue
Block a user