mirror of
https://github.com/Nystik-gh/ignis.git
synced 2026-06-17 04:35:53 +00:00
improve workspaces handling
This commit is contained in:
@@ -1,4 +1,10 @@
|
||||
import {
|
||||
rewriteWorkspacePath,
|
||||
rewriteWorkspacesContent,
|
||||
} from "../workspace.js";
|
||||
|
||||
const API_BASE = "/api/fs";
|
||||
const WORKSPACES_PATH = ".obsidian/workspaces.json";
|
||||
|
||||
function normPath(p) {
|
||||
return (p || "").replace(/^\/+/, "");
|
||||
@@ -19,22 +25,6 @@ function vaultId() {
|
||||
return window.__currentVaultId || "";
|
||||
}
|
||||
|
||||
const WORKSPACE_PATH = ".obsidian/workspace.json";
|
||||
|
||||
function rewriteWorkspacePath(normalizedPath) {
|
||||
const name = window.__workspaceName;
|
||||
|
||||
if (!name) {
|
||||
return normalizedPath;
|
||||
}
|
||||
|
||||
if (normalizedPath === WORKSPACE_PATH) {
|
||||
return `.obsidian/workspace.${name}.json`;
|
||||
}
|
||||
|
||||
return normalizedPath;
|
||||
}
|
||||
|
||||
async function request(method, endpoint, params = {}) {
|
||||
const url = new URL(API_BASE + endpoint, window.location.origin);
|
||||
|
||||
@@ -156,10 +146,17 @@ export const transport = {
|
||||
},
|
||||
|
||||
async writeFile(path, content, encoding) {
|
||||
const isText = typeof content === "string";
|
||||
const norm = normPath(path);
|
||||
let data = content;
|
||||
|
||||
if (norm === WORKSPACES_PATH && typeof data === "string") {
|
||||
data = rewriteWorkspacesContent(data);
|
||||
}
|
||||
|
||||
const isText = typeof data === "string";
|
||||
return requestJson("POST", "/writeFile", {
|
||||
path: rewriteWorkspacePath(normPath(path)),
|
||||
content: isText ? content : uint8ToBase64(content),
|
||||
path: rewriteWorkspacePath(norm),
|
||||
content: isText ? data : uint8ToBase64(data),
|
||||
encoding: encoding || (isText ? "utf-8" : "binary"),
|
||||
base64: !isText,
|
||||
});
|
||||
@@ -261,10 +258,17 @@ export const transport = {
|
||||
},
|
||||
|
||||
writeFileSync(path, content, encoding) {
|
||||
const isText = typeof content === "string";
|
||||
const norm = normPath(path);
|
||||
let data = content;
|
||||
|
||||
if (norm === WORKSPACES_PATH && typeof data === "string") {
|
||||
data = rewriteWorkspacesContent(data);
|
||||
}
|
||||
|
||||
const isText = typeof data === "string";
|
||||
requestSync("POST", "/writeFile", {
|
||||
path: rewriteWorkspacePath(normPath(path)),
|
||||
content: isText ? content : uint8ToBase64(content),
|
||||
path: rewriteWorkspacePath(norm),
|
||||
content: isText ? data : uint8ToBase64(data),
|
||||
encoding: encoding || (isText ? "utf-8" : "binary"),
|
||||
base64: !isText,
|
||||
});
|
||||
|
||||
@@ -3,6 +3,7 @@ import { installRequestUrlShim } from "./request-url.js";
|
||||
import { vaultService } from "../services/vault-service.js";
|
||||
import { showPluginInstallDialog } from "../ui/bootstrap.js";
|
||||
import { registerReadTransform } from "./fs/read-transforms.js";
|
||||
import { resolveWorkspaceName, initWorkspacePatch } from "./workspace.js";
|
||||
|
||||
function resolveVaultId() {
|
||||
const urlParams = new URLSearchParams(window.location.search);
|
||||
@@ -171,9 +172,11 @@ function initCoreSyncGuard() {
|
||||
export function initialize() {
|
||||
resolveVaultId();
|
||||
initVaultConfig();
|
||||
resolveWorkspaceName();
|
||||
initVaultList();
|
||||
initMetadataCache();
|
||||
initCoreSyncGuard();
|
||||
installRequestUrlShim();
|
||||
initWorkspacePatch();
|
||||
initPluginPrompt();
|
||||
}
|
||||
|
||||
188
src/shims/workspace.js
Normal file
188
src/shims/workspace.js
Normal file
@@ -0,0 +1,188 @@
|
||||
import { fsShim } from "./fs/index.js";
|
||||
import { registerReadTransform } from "./fs/read-transforms.js";
|
||||
|
||||
const WORKSPACE_PATH = ".obsidian/workspace.json";
|
||||
const WORKSPACES_PATH = ".obsidian/workspaces.json";
|
||||
|
||||
export function rewriteWorkspacePath(normalizedPath) {
|
||||
const name = window.__workspaceName;
|
||||
|
||||
if (!name) {
|
||||
return normalizedPath;
|
||||
}
|
||||
|
||||
if (normalizedPath === WORKSPACE_PATH) {
|
||||
return `.obsidian/workspace.${name}.json`;
|
||||
}
|
||||
|
||||
return normalizedPath;
|
||||
}
|
||||
|
||||
export function rewriteWorkspacesContent(content) {
|
||||
const original = window.__originalActiveWorkspace;
|
||||
|
||||
if (!original || !window.__workspaceName) {
|
||||
return content;
|
||||
}
|
||||
|
||||
try {
|
||||
const parsed = JSON.parse(content);
|
||||
|
||||
if (parsed.active !== original) {
|
||||
parsed.active = original;
|
||||
return JSON.stringify(parsed);
|
||||
}
|
||||
} catch {}
|
||||
|
||||
return content;
|
||||
}
|
||||
|
||||
function setWorkspaceParam(name) {
|
||||
const url = new URL(window.location.href);
|
||||
|
||||
if (name) {
|
||||
url.searchParams.set("workspace", name);
|
||||
} else {
|
||||
url.searchParams.delete("workspace");
|
||||
}
|
||||
|
||||
history.replaceState(null, "", url.toString());
|
||||
}
|
||||
|
||||
export function resolveWorkspaceName() {
|
||||
try {
|
||||
const vaultParam = window.__currentVaultId
|
||||
? "?vault=" + encodeURIComponent(window.__currentVaultId)
|
||||
: "";
|
||||
|
||||
const sep = vaultParam ? "&" : "?";
|
||||
|
||||
// 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) {
|
||||
return;
|
||||
}
|
||||
|
||||
const workspaces = JSON.parse(xhr.responseText);
|
||||
|
||||
// Always store the original active value for the write transform.
|
||||
if (workspaces.active) {
|
||||
window.__originalActiveWorkspace = workspaces.active;
|
||||
}
|
||||
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
|
||||
export function initWorkspacePatch() {
|
||||
const observer = new MutationObserver(() => {
|
||||
if (!document.querySelector(".workspace")) {
|
||||
return;
|
||||
}
|
||||
|
||||
const plugin =
|
||||
window.app &&
|
||||
window.app.internalPlugins &&
|
||||
window.app.internalPlugins.plugins &&
|
||||
window.app.internalPlugins.plugins.workspaces;
|
||||
|
||||
if (!plugin || !plugin.enabled || !plugin.instance) {
|
||||
return;
|
||||
}
|
||||
|
||||
observer.disconnect();
|
||||
|
||||
const instance = plugin.instance;
|
||||
const origLoad = instance.loadWorkspace.bind(instance);
|
||||
const origSave = instance.saveWorkspace.bind(instance);
|
||||
|
||||
instance.loadWorkspace = function (name) {
|
||||
window.__workspaceName = name;
|
||||
setWorkspaceParam(name);
|
||||
fsShim._contentCache.invalidate(".obsidian/workspace.json");
|
||||
return origLoad(name);
|
||||
};
|
||||
|
||||
instance.saveWorkspace = function (name) {
|
||||
// Grab the current layout before switching the transport target.
|
||||
const currentLayout = fsShim._contentCache.get(".obsidian/workspace.json");
|
||||
|
||||
window.__workspaceName = name;
|
||||
setWorkspaceParam(name);
|
||||
fsShim._contentCache.invalidate(".obsidian/workspace.json");
|
||||
const result = origSave(name);
|
||||
|
||||
// Write the layout to the new workspace file so it exists on disk immediately.
|
||||
if (currentLayout) {
|
||||
fsShim.writeFileSync(".obsidian/workspace.json", currentLayout, "utf-8");
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
// Override the active field on reads so the menu matches this tab's workspace.
|
||||
registerReadTransform(".obsidian/workspaces.json", (data) => {
|
||||
if (!window.__workspaceName) {
|
||||
return data;
|
||||
}
|
||||
|
||||
let text =
|
||||
typeof data === "string" ? data : new TextDecoder().decode(data);
|
||||
|
||||
try {
|
||||
const parsed = JSON.parse(text);
|
||||
|
||||
if (parsed.active !== window.__workspaceName) {
|
||||
parsed.active = window.__workspaceName;
|
||||
return JSON.stringify(parsed);
|
||||
}
|
||||
} catch {}
|
||||
|
||||
return data;
|
||||
});
|
||||
|
||||
console.log("[ignis] Workspaces plugin patched, workspace:", window.__workspaceName || "(none)");
|
||||
});
|
||||
|
||||
observer.observe(document.documentElement, {
|
||||
childList: true,
|
||||
subtree: true,
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user