mirror of
https://github.com/mountain-loop/yaak.git
synced 2026-08-24 04:13:59 +02:00
The browser host now stores data through yaak-models compiled to wasm — the same queries, migrations, cascade rules, duplicate naming and first-run bootstrap the desktop and CLI use — instead of a TypeScript port of them. - crates/yaak-web: the wasm crate. boot() registers an IndexedDB-backed VFS and calls init_standalone; rpc(cmd, payload, label) answers the models_* commands via ClientDb and returns the model_writes it caused; blob get/put through blob_manager. Built like yaak-templates (pkg/ committed); the build script keeps pkg/ and says so when no wasm-capable clang is present, so a desktop bootstrap never depends on one. - models_ops moves from crates/yaak into yaak-models so the wasm crate can use it without the send engine. - The database lives in a SharedWorker (packages/platform/src/web/worker.ts): one process holds the data and pushes writes to every tab, as on the desktop. Where SharedWorker is missing or its script cannot be fetched, a dedicated worker guarded by a Web Lock takes over and a second tab is told so. The worker imports the wasm lazily so a tab's connect is answered instantly; the tab reconnects if it isn't. - packages/platform/src/web loses models.ts, schema.ts, db.ts and the BroadcastChannel; commands.ts forwards model commands to the worker and keeps the fixed answers and refusals. Verified in Chrome, dev and production builds: bootstrap, CRUD across every model type, serde defaults, engine-format ids, Rust copy naming, folder cascade with per-descendant events, single-event workspace delete, reload persistence, two tabs coherent, Send declined with a toast, 8/8 reloads rendering in ~100 ms.
40 lines
1.5 KiB
TypeScript
40 lines
1.5 KiB
TypeScript
import { platform } from "@yaakapp-internal/platform";
|
|
import type { SettingsTab } from "../components/Settings/Settings";
|
|
import { activeWorkspaceIdAtom } from "../hooks/useActiveWorkspace";
|
|
import { createFastMutation } from "../hooks/useFastMutation";
|
|
import { jotaiStore } from "../lib/jotai";
|
|
import { router } from "../lib/router";
|
|
import { rpc } from "../lib/rpc";
|
|
|
|
// Allow tab with optional subtab (e.g., "plugins:installed")
|
|
type SettingsTabWithSubtab = SettingsTab | `${SettingsTab}:${string}` | null;
|
|
|
|
export const openSettings = createFastMutation<void, string, SettingsTabWithSubtab>({
|
|
mutationKey: ["open_settings"],
|
|
mutationFn: async (tab) => {
|
|
const workspaceId = jotaiStore.get(activeWorkspaceIdAtom);
|
|
if (workspaceId == null) return;
|
|
|
|
const to = "/workspaces/$workspaceId/settings" as const;
|
|
const params = { workspaceId };
|
|
const search = { tab: (tab ?? undefined) as SettingsTab | undefined };
|
|
|
|
// Settings is its own window where the host has windows to give. Where it
|
|
// doesn't — a browser tab — the same route opens in place, which is the
|
|
// whole difference: it is already a route, not a separate app.
|
|
if (!platform.capabilities.multiWindow) {
|
|
await router.navigate({ to, params, search });
|
|
return;
|
|
}
|
|
|
|
const location = router.buildLocation({ to, params, search });
|
|
|
|
await rpc("cmd_new_child_window", {
|
|
url: location.href,
|
|
label: "settings",
|
|
title: "Yaak Settings",
|
|
innerSize: [750, 600],
|
|
});
|
|
},
|
|
});
|