resolve workspace and appearance from the warm cache at boot

This commit is contained in:
Nystik
2026-06-16 23:44:26 +02:00
parent b6c538fb33
commit 0aa2b2bd45
3 changed files with 45 additions and 88 deletions

View File

@@ -171,8 +171,7 @@ function applyCoreSyncGuard(plugins) {
return data;
}
let text =
typeof data === "string" ? data : new TextDecoder().decode(data);
let text = typeof data === "string" ? data : new TextDecoder().decode(data);
try {
const config = JSON.parse(text);
@@ -226,6 +225,13 @@ function updateBootProgress(received, total) {
label.textContent = `Loading plugins... ${mb(received)}/${mb(total)} MB`;
}
// Resolve the active workspace and snapshot the appearance config.
function resolveWorkspaceAndAppearance() {
resolveWorkspaceName();
loadPresetIfRequested();
initNativeMenuGuard();
}
export function initialize() {
if (maybeProvisionDemoVault()) {
window.__ignisBootReady = Promise.resolve();
@@ -233,9 +239,6 @@ export function initialize() {
}
resolveVaultId();
resolveWorkspaceName();
loadPresetIfRequested();
initNativeMenuGuard(window.__currentVaultId);
const bootstrap = fetchBootstrap();
@@ -258,13 +261,16 @@ export function initialize() {
{ onProgress: updateBootProgress },
);
window.__ignisBootReady = priority;
// Chain workspace/appearance resolution onto readiness so its config reads hit the warm priority slice instead of the network.
window.__ignisBootReady = priority.then(resolveWorkspaceAndAppearance);
} else {
window.__ignisBootReady = Promise.resolve();
initVaultConfigFallback();
initVaultListFallback();
initMetadataCacheFallback();
initCoreSyncGuardFallback();
// No prefetch on the fallback path, so resolve directly; the reads fall through to the network.
resolveWorkspaceAndAppearance();
window.__ignisBootReady = Promise.resolve();
}
installRequestUrlShim();

View File

@@ -6,34 +6,16 @@ import {
registerReadTransform,
registerWriteTransform,
} from "./fs/transforms.js";
import { fsShim } from "./fs/index.js";
const APPEARANCE_PATH = ".obsidian/appearance.json";
// undefined = key absent on disk; write transform keeps it absent.
let preservedNativeMenus = undefined;
function snapshotAppearance(vaultId) {
if (!vaultId) {
return;
}
function snapshotAppearance() {
try {
const xhr = new XMLHttpRequest();
const url =
"/api/fs/readFile?vault=" +
encodeURIComponent(vaultId) +
"&path=" +
encodeURIComponent(APPEARANCE_PATH) +
"&encoding=utf-8";
xhr.open("GET", url, false);
xhr.send();
if (xhr.status !== 200) {
return;
}
const obj = JSON.parse(xhr.responseText);
const obj = JSON.parse(fsShim.readFileSync(APPEARANCE_PATH, "utf-8"));
if ("nativeMenus" in obj) {
preservedNativeMenus = obj.nativeMenus;
@@ -158,9 +140,9 @@ function disableNativeMenuToggle() {
});
}
export function initNativeMenuGuard(vaultId) {
// Snapshot before registering transforms so the write transform has the original disk value to substitute back.
snapshotAppearance(vaultId);
export function initNativeMenuGuard() {
// Snapshot before registering the read transform so the captured value is the original on disk, not the forced value.
snapshotAppearance();
registerReadTransform(APPEARANCE_PATH, readTransform);
registerWriteTransform(APPEARANCE_PATH, writeTransform);
patchSetConfig();

View File

@@ -86,71 +86,40 @@ export function loadPresetIfRequested() {
}
}
export function resolveWorkspaceName() {
function readJsonIfPresent(path) {
try {
const vaultParam = window.__currentVaultId
? "?vault=" + encodeURIComponent(window.__currentVaultId)
: "";
return JSON.parse(fsShim.readFileSync(path, "utf-8"));
} catch {
return null;
}
}
const sep = vaultParam ? "&" : "?";
export function resolveWorkspaceName() {
// With no URL param, only resolve a workspace when the workspaces core plugin is enabled.
if (!window.__workspaceName) {
const corePlugins = readJsonIfPresent(".obsidian/core-plugins.json");
// If no param provided, check if workspaces plugin is enabled before resolving.
if (!window.__workspaceName) {
const coreXhr = new XMLHttpRequest();
coreXhr.open(
"GET",
"/api/fs/readFile" +
vaultParam +
sep +
"path=.obsidian/core-plugins.json&encoding=utf-8",
false,
);
coreXhr.send();
if (coreXhr.status !== 200) {
return;
}
const corePlugins = JSON.parse(coreXhr.responseText);
if (!corePlugins.workspaces) {
return;
}
}
// Read workspaces.json to get the active field.
const xhr = new XMLHttpRequest();
xhr.open(
"GET",
"/api/fs/readFile" +
vaultParam +
sep +
"path=.obsidian/workspaces.json&encoding=utf-8",
false,
);
xhr.send();
if (xhr.status !== 200) {
if (!corePlugins || !corePlugins.workspaces) {
return;
}
}
const workspaces = JSON.parse(xhr.responseText);
const workspaces = readJsonIfPresent(WORKSPACES_PATH);
// Always store the original active value for the write transform.
if (workspaces.active) {
window.__originalActiveWorkspace = workspaces.active;
}
if (!workspaces) {
return;
}
// If no param was provided, seed from the active workspace.
if (!window.__workspaceName && workspaces.active) {
window.__workspaceName = workspaces.active;
setWorkspaceParam(workspaces.active);
console.log("[ignis] Workspace resolved from active:", workspaces.active);
}
} catch (e) {
console.warn("[ignis] Failed to resolve workspace name:", e);
// Keep the original active value so the write transform can restore it on disk.
if (workspaces.active) {
window.__originalActiveWorkspace = workspaces.active;
}
// With no URL param, seed from the active workspace.
if (!window.__workspaceName && workspaces.active) {
window.__workspaceName = workspaces.active;
setWorkspaceParam(workspaces.active);
console.log("[ignis] Workspace resolved from active:", workspaces.active);
}
}