velxio/frontend/src/desktop/menu.ts

176 lines
5.8 KiB
TypeScript
Raw Normal View History

/**
* Native menubar event bridge.
*
* The Tauri shell (pro/desktop/src-tauri/src/menu.rs in velxio-prod)
* builds a Velxio / File / Edit / View / Help menubar. Internal items
* (Save .vlx, Open .vlx, Toggle Serial Monitor, Find, ) emit a
* `velxio://menu` event with `{ action: '<id>' }`. URL items (Docs,
* Examples, Discord, GitHub) are opened directly from Rust and don't
* reach this listener.
*
* Actions handled directly here (no further plumbing needed):
* - save-vlx, open-vlx triggerDownloadVlx / file picker
* - toggle-serial-monitor useSimulatorStore.toggleSerialMonitor()
* - check-for-updates tauri-plugin-updater check()
*
* Actions forwarded to whoever's listening as a window CustomEvent
* `velxio:menu:<action>`:
* - new-project, find-in-editor, toggle-file-explorer
*
* No-op outside Tauri (e.g. running the bundle in a regular browser
* for debugging) listen() returns a no-op when the global event
* API isn't present.
*/
import { listen } from './tauriBridge';
import { dlog } from './log';
import { triggerDownloadVlx, importVlxFile } from '../utils/vlxFile';
import { useSimulatorStore } from '../store/useSimulatorStore';
feat(desktop): hide header strip, splash screen, native locale switcher Three QoL fixes for the Tauri shell: 1. Hide the entire AppHeader strip in VITE_DESKTOP, not just the marketing nav. The previous gate left the black bar painting over the editor with the brand + auto-save + share + auth slot, all of which are irrelevant in desktop (cloud Pro features, license is handled by DesktopWelcomePage, the title bar already says "Velxio Desktop"). Return null at the top so the editor takes the full window height. 2. Splash screen during sidecar boot + Monaco hydration. Cold launch was a 3-8 s black window — now there's an inline SVG logo, "Velxio" wordmark, slogan, animated spinner, and a "Starting local backend…" caption. Lives in index.html as a fixed-position overlay with display:none by default; the inline script reveals it only when `window.__TAURI__` is present, so web users never see it. main.tsx fades it out (250 ms ease-out) after two animation frames — guarantees React's first paint has committed before the handoff, no black flash. Self-contained: inline styles, inline SVG, inline CSS keyframes, zero external requests. 3. Native locale switcher under View → Language. Emits `velxio://menu` with action='set-locale' + the locale code; the desktop/menu.ts handler navigates via history.pushState + popstate so React Router picks it up without a hard reload (Monaco + simulator state preserved). Locale list mirrors i18n/config.ts::LOCALES. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-23 05:39:10 +07:00
import { switchLocale } from '../i18n/path';
import { LOCALES, type Locale } from '../i18n/config';
type MenuAction =
| 'new-project'
| 'save-vlx'
| 'open-vlx'
| 'find-in-editor'
| 'toggle-file-explorer'
| 'toggle-serial-monitor'
feat(desktop): hide header strip, splash screen, native locale switcher Three QoL fixes for the Tauri shell: 1. Hide the entire AppHeader strip in VITE_DESKTOP, not just the marketing nav. The previous gate left the black bar painting over the editor with the brand + auto-save + share + auth slot, all of which are irrelevant in desktop (cloud Pro features, license is handled by DesktopWelcomePage, the title bar already says "Velxio Desktop"). Return null at the top so the editor takes the full window height. 2. Splash screen during sidecar boot + Monaco hydration. Cold launch was a 3-8 s black window — now there's an inline SVG logo, "Velxio" wordmark, slogan, animated spinner, and a "Starting local backend…" caption. Lives in index.html as a fixed-position overlay with display:none by default; the inline script reveals it only when `window.__TAURI__` is present, so web users never see it. main.tsx fades it out (250 ms ease-out) after two animation frames — guarantees React's first paint has committed before the handoff, no black flash. Self-contained: inline styles, inline SVG, inline CSS keyframes, zero external requests. 3. Native locale switcher under View → Language. Emits `velxio://menu` with action='set-locale' + the locale code; the desktop/menu.ts handler navigates via history.pushState + popstate so React Router picks it up without a hard reload (Monaco + simulator state preserved). Locale list mirrors i18n/config.ts::LOCALES. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-23 05:39:10 +07:00
| 'check-for-updates'
feat(desktop): skip welcome screen, robust openExternal, in-app nav Three coordinated changes that fix the "Waiting for browser…" hang and unblock first-launch UX on the Tauri desktop build: 1. desktop/index.ts — DON'T mountWelcome unconditionally on first launch. Before, an empty keychain (no key yet) forced the welcome / sign-in screen on top of the editor, gating 100% of the app behind an account. Now the editor opens directly: compile + run + sim + save .vlx all work for free (they're upstream OSS features), and the license check still runs in the background just to populate state for the GraceBanner (which shows for invalid keys — locked, tampered, in soft/hard grace). Pro-only features (ESP32 QEMU download, agent IA) prompt for license at use time, where it actually matters. Matches the "try before you buy" expectation a desktop install creates. 2. desktop/tauriBridge.ts — rewrite `openExternal` to try every known IPC path in cascade order and log via the desktop debug file which one worked. The previous implementation invoked `plugin:shell|open` with `{ path: url }`, which silently failed (no ACL match + wrong arg shape) and fell back to `window.open`, which inside a Tauri webview is a no-op for external URLs — the browser never opened. New cascade: plugin:opener|open_url (paired with tauri-plugin-opener which ships in this revision), then plugin:shell|open with both `{ path, with: null }` and `{ url }` shapes, then the window.__TAURI__.shell / opener high-level wrappers that specific Tauri 2.x flag combos expose. Each attempt logged via the dlog helper so the next operator can see exactly which path was used (or that all failed) without devtools. 3. desktop/menu.ts — new `navigate-route` action type. Routes bundled in the SPA (DocsPage, ExamplesPage, AboutPage) that used to open velxio.dev in the system browser now navigate in-window via history.pushState + popstate (mirrors the locale-switch handler). Respects the current locale prefix so `/examples` from `/es/editor` lands at `/es/examples` instead of jumping back to English. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-24 03:57:46 +07:00
| 'set-locale'
| 'navigate-route';
interface MenuEventPayload {
action: MenuAction;
feat(desktop): hide header strip, splash screen, native locale switcher Three QoL fixes for the Tauri shell: 1. Hide the entire AppHeader strip in VITE_DESKTOP, not just the marketing nav. The previous gate left the black bar painting over the editor with the brand + auto-save + share + auth slot, all of which are irrelevant in desktop (cloud Pro features, license is handled by DesktopWelcomePage, the title bar already says "Velxio Desktop"). Return null at the top so the editor takes the full window height. 2. Splash screen during sidecar boot + Monaco hydration. Cold launch was a 3-8 s black window — now there's an inline SVG logo, "Velxio" wordmark, slogan, animated spinner, and a "Starting local backend…" caption. Lives in index.html as a fixed-position overlay with display:none by default; the inline script reveals it only when `window.__TAURI__` is present, so web users never see it. main.tsx fades it out (250 ms ease-out) after two animation frames — guarantees React's first paint has committed before the handoff, no black flash. Self-contained: inline styles, inline SVG, inline CSS keyframes, zero external requests. 3. Native locale switcher under View → Language. Emits `velxio://menu` with action='set-locale' + the locale code; the desktop/menu.ts handler navigates via history.pushState + popstate so React Router picks it up without a hard reload (Monaco + simulator state preserved). Locale list mirrors i18n/config.ts::LOCALES. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-23 05:39:10 +07:00
// Only present when action='set-locale'. Matches an entry in
// i18n/config.ts::LOCALES.
locale?: string;
feat(desktop): skip welcome screen, robust openExternal, in-app nav Three coordinated changes that fix the "Waiting for browser…" hang and unblock first-launch UX on the Tauri desktop build: 1. desktop/index.ts — DON'T mountWelcome unconditionally on first launch. Before, an empty keychain (no key yet) forced the welcome / sign-in screen on top of the editor, gating 100% of the app behind an account. Now the editor opens directly: compile + run + sim + save .vlx all work for free (they're upstream OSS features), and the license check still runs in the background just to populate state for the GraceBanner (which shows for invalid keys — locked, tampered, in soft/hard grace). Pro-only features (ESP32 QEMU download, agent IA) prompt for license at use time, where it actually matters. Matches the "try before you buy" expectation a desktop install creates. 2. desktop/tauriBridge.ts — rewrite `openExternal` to try every known IPC path in cascade order and log via the desktop debug file which one worked. The previous implementation invoked `plugin:shell|open` with `{ path: url }`, which silently failed (no ACL match + wrong arg shape) and fell back to `window.open`, which inside a Tauri webview is a no-op for external URLs — the browser never opened. New cascade: plugin:opener|open_url (paired with tauri-plugin-opener which ships in this revision), then plugin:shell|open with both `{ path, with: null }` and `{ url }` shapes, then the window.__TAURI__.shell / opener high-level wrappers that specific Tauri 2.x flag combos expose. Each attempt logged via the dlog helper so the next operator can see exactly which path was used (or that all failed) without devtools. 3. desktop/menu.ts — new `navigate-route` action type. Routes bundled in the SPA (DocsPage, ExamplesPage, AboutPage) that used to open velxio.dev in the system browser now navigate in-window via history.pushState + popstate (mirrors the locale-switch handler). Respects the current locale prefix so `/examples` from `/es/editor` lands at `/es/examples` instead of jumping back to English. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-24 03:57:46 +07:00
// Only present when action='navigate-route'. Absolute pathname
// (e.g. '/examples', '/docs', '/about') — navigated via React
// Router so the current locale prefix gets applied.
route?: string;
}
let installed = false;
export async function installDesktopMenuListener(): Promise<void> {
if (installed) return;
installed = true;
await listen<MenuEventPayload>('velxio://menu', (event) => {
dlog('menu event', event.payload);
feat(desktop): hide header strip, splash screen, native locale switcher Three QoL fixes for the Tauri shell: 1. Hide the entire AppHeader strip in VITE_DESKTOP, not just the marketing nav. The previous gate left the black bar painting over the editor with the brand + auto-save + share + auth slot, all of which are irrelevant in desktop (cloud Pro features, license is handled by DesktopWelcomePage, the title bar already says "Velxio Desktop"). Return null at the top so the editor takes the full window height. 2. Splash screen during sidecar boot + Monaco hydration. Cold launch was a 3-8 s black window — now there's an inline SVG logo, "Velxio" wordmark, slogan, animated spinner, and a "Starting local backend…" caption. Lives in index.html as a fixed-position overlay with display:none by default; the inline script reveals it only when `window.__TAURI__` is present, so web users never see it. main.tsx fades it out (250 ms ease-out) after two animation frames — guarantees React's first paint has committed before the handoff, no black flash. Self-contained: inline styles, inline SVG, inline CSS keyframes, zero external requests. 3. Native locale switcher under View → Language. Emits `velxio://menu` with action='set-locale' + the locale code; the desktop/menu.ts handler navigates via history.pushState + popstate so React Router picks it up without a hard reload (Monaco + simulator state preserved). Locale list mirrors i18n/config.ts::LOCALES. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-23 05:39:10 +07:00
void handle(event.payload.action, event.payload);
});
}
feat(desktop): hide header strip, splash screen, native locale switcher Three QoL fixes for the Tauri shell: 1. Hide the entire AppHeader strip in VITE_DESKTOP, not just the marketing nav. The previous gate left the black bar painting over the editor with the brand + auto-save + share + auth slot, all of which are irrelevant in desktop (cloud Pro features, license is handled by DesktopWelcomePage, the title bar already says "Velxio Desktop"). Return null at the top so the editor takes the full window height. 2. Splash screen during sidecar boot + Monaco hydration. Cold launch was a 3-8 s black window — now there's an inline SVG logo, "Velxio" wordmark, slogan, animated spinner, and a "Starting local backend…" caption. Lives in index.html as a fixed-position overlay with display:none by default; the inline script reveals it only when `window.__TAURI__` is present, so web users never see it. main.tsx fades it out (250 ms ease-out) after two animation frames — guarantees React's first paint has committed before the handoff, no black flash. Self-contained: inline styles, inline SVG, inline CSS keyframes, zero external requests. 3. Native locale switcher under View → Language. Emits `velxio://menu` with action='set-locale' + the locale code; the desktop/menu.ts handler navigates via history.pushState + popstate so React Router picks it up without a hard reload (Monaco + simulator state preserved). Locale list mirrors i18n/config.ts::LOCALES. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-23 05:39:10 +07:00
async function handle(action: MenuAction, payload?: MenuEventPayload): Promise<void> {
switch (action) {
case 'save-vlx':
triggerDownloadVlx();
return;
case 'open-vlx':
pickAndImportVlx();
return;
case 'toggle-serial-monitor':
useSimulatorStore.getState().toggleSerialMonitor();
return;
case 'new-project':
case 'find-in-editor':
case 'toggle-file-explorer':
window.dispatchEvent(new CustomEvent(`velxio:menu:${action}`));
return;
case 'check-for-updates':
await checkForUpdates();
return;
feat(desktop): hide header strip, splash screen, native locale switcher Three QoL fixes for the Tauri shell: 1. Hide the entire AppHeader strip in VITE_DESKTOP, not just the marketing nav. The previous gate left the black bar painting over the editor with the brand + auto-save + share + auth slot, all of which are irrelevant in desktop (cloud Pro features, license is handled by DesktopWelcomePage, the title bar already says "Velxio Desktop"). Return null at the top so the editor takes the full window height. 2. Splash screen during sidecar boot + Monaco hydration. Cold launch was a 3-8 s black window — now there's an inline SVG logo, "Velxio" wordmark, slogan, animated spinner, and a "Starting local backend…" caption. Lives in index.html as a fixed-position overlay with display:none by default; the inline script reveals it only when `window.__TAURI__` is present, so web users never see it. main.tsx fades it out (250 ms ease-out) after two animation frames — guarantees React's first paint has committed before the handoff, no black flash. Self-contained: inline styles, inline SVG, inline CSS keyframes, zero external requests. 3. Native locale switcher under View → Language. Emits `velxio://menu` with action='set-locale' + the locale code; the desktop/menu.ts handler navigates via history.pushState + popstate so React Router picks it up without a hard reload (Monaco + simulator state preserved). Locale list mirrors i18n/config.ts::LOCALES. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-23 05:39:10 +07:00
case 'set-locale':
if (payload?.locale) setLocale(payload.locale);
return;
feat(desktop): skip welcome screen, robust openExternal, in-app nav Three coordinated changes that fix the "Waiting for browser…" hang and unblock first-launch UX on the Tauri desktop build: 1. desktop/index.ts — DON'T mountWelcome unconditionally on first launch. Before, an empty keychain (no key yet) forced the welcome / sign-in screen on top of the editor, gating 100% of the app behind an account. Now the editor opens directly: compile + run + sim + save .vlx all work for free (they're upstream OSS features), and the license check still runs in the background just to populate state for the GraceBanner (which shows for invalid keys — locked, tampered, in soft/hard grace). Pro-only features (ESP32 QEMU download, agent IA) prompt for license at use time, where it actually matters. Matches the "try before you buy" expectation a desktop install creates. 2. desktop/tauriBridge.ts — rewrite `openExternal` to try every known IPC path in cascade order and log via the desktop debug file which one worked. The previous implementation invoked `plugin:shell|open` with `{ path: url }`, which silently failed (no ACL match + wrong arg shape) and fell back to `window.open`, which inside a Tauri webview is a no-op for external URLs — the browser never opened. New cascade: plugin:opener|open_url (paired with tauri-plugin-opener which ships in this revision), then plugin:shell|open with both `{ path, with: null }` and `{ url }` shapes, then the window.__TAURI__.shell / opener high-level wrappers that specific Tauri 2.x flag combos expose. Each attempt logged via the dlog helper so the next operator can see exactly which path was used (or that all failed) without devtools. 3. desktop/menu.ts — new `navigate-route` action type. Routes bundled in the SPA (DocsPage, ExamplesPage, AboutPage) that used to open velxio.dev in the system browser now navigate in-window via history.pushState + popstate (mirrors the locale-switch handler). Respects the current locale prefix so `/examples` from `/es/editor` lands at `/es/examples` instead of jumping back to English. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-24 03:57:46 +07:00
case 'navigate-route':
if (payload?.route) navigateTo(payload.route);
return;
feat(desktop): hide header strip, splash screen, native locale switcher Three QoL fixes for the Tauri shell: 1. Hide the entire AppHeader strip in VITE_DESKTOP, not just the marketing nav. The previous gate left the black bar painting over the editor with the brand + auto-save + share + auth slot, all of which are irrelevant in desktop (cloud Pro features, license is handled by DesktopWelcomePage, the title bar already says "Velxio Desktop"). Return null at the top so the editor takes the full window height. 2. Splash screen during sidecar boot + Monaco hydration. Cold launch was a 3-8 s black window — now there's an inline SVG logo, "Velxio" wordmark, slogan, animated spinner, and a "Starting local backend…" caption. Lives in index.html as a fixed-position overlay with display:none by default; the inline script reveals it only when `window.__TAURI__` is present, so web users never see it. main.tsx fades it out (250 ms ease-out) after two animation frames — guarantees React's first paint has committed before the handoff, no black flash. Self-contained: inline styles, inline SVG, inline CSS keyframes, zero external requests. 3. Native locale switcher under View → Language. Emits `velxio://menu` with action='set-locale' + the locale code; the desktop/menu.ts handler navigates via history.pushState + popstate so React Router picks it up without a hard reload (Monaco + simulator state preserved). Locale list mirrors i18n/config.ts::LOCALES. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-23 05:39:10 +07:00
}
}
feat(desktop): skip welcome screen, robust openExternal, in-app nav Three coordinated changes that fix the "Waiting for browser…" hang and unblock first-launch UX on the Tauri desktop build: 1. desktop/index.ts — DON'T mountWelcome unconditionally on first launch. Before, an empty keychain (no key yet) forced the welcome / sign-in screen on top of the editor, gating 100% of the app behind an account. Now the editor opens directly: compile + run + sim + save .vlx all work for free (they're upstream OSS features), and the license check still runs in the background just to populate state for the GraceBanner (which shows for invalid keys — locked, tampered, in soft/hard grace). Pro-only features (ESP32 QEMU download, agent IA) prompt for license at use time, where it actually matters. Matches the "try before you buy" expectation a desktop install creates. 2. desktop/tauriBridge.ts — rewrite `openExternal` to try every known IPC path in cascade order and log via the desktop debug file which one worked. The previous implementation invoked `plugin:shell|open` with `{ path: url }`, which silently failed (no ACL match + wrong arg shape) and fell back to `window.open`, which inside a Tauri webview is a no-op for external URLs — the browser never opened. New cascade: plugin:opener|open_url (paired with tauri-plugin-opener which ships in this revision), then plugin:shell|open with both `{ path, with: null }` and `{ url }` shapes, then the window.__TAURI__.shell / opener high-level wrappers that specific Tauri 2.x flag combos expose. Each attempt logged via the dlog helper so the next operator can see exactly which path was used (or that all failed) without devtools. 3. desktop/menu.ts — new `navigate-route` action type. Routes bundled in the SPA (DocsPage, ExamplesPage, AboutPage) that used to open velxio.dev in the system browser now navigate in-window via history.pushState + popstate (mirrors the locale-switch handler). Respects the current locale prefix so `/examples` from `/es/editor` lands at `/es/examples` instead of jumping back to English. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-24 03:57:46 +07:00
function navigateTo(route: string): void {
// Prefix with the current locale if we're on a non-default one,
// so `/examples` from `/es/editor` lands at `/es/examples` instead
// of switching back to English. Mirrors how LanguageSwitcher does it.
const cur = window.location.pathname;
const localeMatch = cur.match(/^\/([a-z]{2}(?:-[a-z]{2})?)\b/);
const prefix = localeMatch && LOCALES.includes(localeMatch[1] as Locale)
? `/${localeMatch[1]}`
: '';
const normalised = route.startsWith('/') ? route : `/${route}`;
const next = `${prefix}${normalised}`;
if (next === cur) return;
// history.pushState + popstate keeps React Router happy without
// reloading the SPA (Monaco state, simulator state, sidecar
// connection all preserved).
window.history.pushState(null, '', next);
window.dispatchEvent(new PopStateEvent('popstate'));
}
feat(desktop): hide header strip, splash screen, native locale switcher Three QoL fixes for the Tauri shell: 1. Hide the entire AppHeader strip in VITE_DESKTOP, not just the marketing nav. The previous gate left the black bar painting over the editor with the brand + auto-save + share + auth slot, all of which are irrelevant in desktop (cloud Pro features, license is handled by DesktopWelcomePage, the title bar already says "Velxio Desktop"). Return null at the top so the editor takes the full window height. 2. Splash screen during sidecar boot + Monaco hydration. Cold launch was a 3-8 s black window — now there's an inline SVG logo, "Velxio" wordmark, slogan, animated spinner, and a "Starting local backend…" caption. Lives in index.html as a fixed-position overlay with display:none by default; the inline script reveals it only when `window.__TAURI__` is present, so web users never see it. main.tsx fades it out (250 ms ease-out) after two animation frames — guarantees React's first paint has committed before the handoff, no black flash. Self-contained: inline styles, inline SVG, inline CSS keyframes, zero external requests. 3. Native locale switcher under View → Language. Emits `velxio://menu` with action='set-locale' + the locale code; the desktop/menu.ts handler navigates via history.pushState + popstate so React Router picks it up without a hard reload (Monaco + simulator state preserved). Locale list mirrors i18n/config.ts::LOCALES. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-23 05:39:10 +07:00
function setLocale(locale: string): void {
// Defensive: ignore unknown locales coming from the menu so a
// stale shell doesn't navigate to a broken URL.
if (!(LOCALES as readonly string[]).includes(locale)) {
dlog('set-locale: ignoring unknown locale', { locale });
return;
}
const target = locale as Locale;
const next =
switchLocale(window.location.pathname, target) +
window.location.search +
window.location.hash;
if (next === window.location.pathname + window.location.search + window.location.hash) {
return;
}
feat(desktop): hide header strip, splash screen, native locale switcher Three QoL fixes for the Tauri shell: 1. Hide the entire AppHeader strip in VITE_DESKTOP, not just the marketing nav. The previous gate left the black bar painting over the editor with the brand + auto-save + share + auth slot, all of which are irrelevant in desktop (cloud Pro features, license is handled by DesktopWelcomePage, the title bar already says "Velxio Desktop"). Return null at the top so the editor takes the full window height. 2. Splash screen during sidecar boot + Monaco hydration. Cold launch was a 3-8 s black window — now there's an inline SVG logo, "Velxio" wordmark, slogan, animated spinner, and a "Starting local backend…" caption. Lives in index.html as a fixed-position overlay with display:none by default; the inline script reveals it only when `window.__TAURI__` is present, so web users never see it. main.tsx fades it out (250 ms ease-out) after two animation frames — guarantees React's first paint has committed before the handoff, no black flash. Self-contained: inline styles, inline SVG, inline CSS keyframes, zero external requests. 3. Native locale switcher under View → Language. Emits `velxio://menu` with action='set-locale' + the locale code; the desktop/menu.ts handler navigates via history.pushState + popstate so React Router picks it up without a hard reload (Monaco + simulator state preserved). Locale list mirrors i18n/config.ts::LOCALES. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-23 05:39:10 +07:00
// history.pushState + popstate lets React Router pick the change up
// without a full reload, preserving the editor state. Reload would
// re-spawn the sidecar handshake and lose Monaco/sim state for ~5s.
window.history.pushState(null, '', next);
window.dispatchEvent(new PopStateEvent('popstate'));
}
function pickAndImportVlx(): void {
const input = document.createElement('input');
input.type = 'file';
input.accept = '.vlx,application/json';
input.style.display = 'none';
document.body.appendChild(input);
input.addEventListener('change', async () => {
const file = input.files?.[0];
if (file) {
try {
await importVlxFile(file);
} catch (err) {
// eslint-disable-next-line no-alert
alert(`Failed to open .vlx: ${(err as Error).message}`);
}
}
document.body.removeChild(input);
});
input.click();
}
async function checkForUpdates(): Promise<void> {
try {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const updater = (window as any).__TAURI__?.updater;
if (!updater?.check) {
// eslint-disable-next-line no-alert
alert('Update plugin not available in this build.');
return;
}
const update = await updater.check();
if (update) {
await update.downloadAndInstall();
} else {
// eslint-disable-next-line no-alert
alert('Velxio Desktop is up to date.');
}
} catch (err) {
// eslint-disable-next-line no-alert
alert(`Update check failed: ${(err as Error).message}`);
}
}