mirror of
https://github.com/Nystik-gh/ignis.git
synced 2026-06-17 04:35:53 +00:00
minor refactor, cleanup
This commit is contained in:
@@ -1,6 +1,3 @@
|
||||
// Electron module shim
|
||||
// Returned when Obsidian calls: window.require('electron')
|
||||
|
||||
import { ipcRenderer } from "./ipc-renderer.js";
|
||||
import { webFrame } from "./web-frame.js";
|
||||
import { remoteShim } from "./remote/index.js";
|
||||
@@ -10,14 +7,12 @@ export const electronShim = {
|
||||
webFrame,
|
||||
remote: remoteShim,
|
||||
|
||||
// electron.webUtils - used for drag/drop file path extraction (desktop only)
|
||||
webUtils: {
|
||||
getPathForFile(file) {
|
||||
return "";
|
||||
},
|
||||
},
|
||||
|
||||
// electron.deprecate - used by Obsidian to mark deprecated APIs
|
||||
deprecate: {
|
||||
function(fn, name) {
|
||||
return fn;
|
||||
|
||||
@@ -1,28 +1,7 @@
|
||||
// Shim for electron.ipcRenderer
|
||||
// Obsidian uses: .send(), .sendSync(), .on(), .once()
|
||||
//
|
||||
// sendSync channels discovered in app.js:
|
||||
// vault → {id, path} - critical for startup
|
||||
// version → string - app version
|
||||
// is-dev → boolean - dev mode flag
|
||||
// file-url → string - base URL prefix for vault assets
|
||||
// disable-update → boolean - whether updates are disabled
|
||||
// update → string - update status
|
||||
// disable-gpu → boolean - GPU acceleration toggle
|
||||
// frame → void - window frame style
|
||||
// set-icon → void - custom vault icon
|
||||
// get-icon → null|object - get custom vault icon
|
||||
// relaunch → void - restart app
|
||||
// starter → void - open vault chooser
|
||||
// help → void - open help
|
||||
// sandbox → void - open sandbox vault
|
||||
// copy-asar → boolean - install update
|
||||
|
||||
import { showVaultManager } from "../ui/vault-manager.js";
|
||||
|
||||
const listeners = new Map();
|
||||
|
||||
// Sync channel handlers - must return values synchronously
|
||||
const syncHandlers = {
|
||||
vault: () => window.__vaultConfig || { id: "default-vault", path: "/" },
|
||||
version: () => "1.8.9",
|
||||
@@ -51,7 +30,6 @@ const syncHandlers = {
|
||||
"copy-asar": () => false,
|
||||
"check-update": () => null,
|
||||
"vault-list": () => {
|
||||
// Starter expects an object keyed by ID: {id: {path, ts, name}}
|
||||
const result = {};
|
||||
for (const v of window.__vaultList || []) {
|
||||
result[v.id] = {
|
||||
@@ -66,14 +44,12 @@ const syncHandlers = {
|
||||
const id = (vaultPath || "").replace(/^\/+/, "");
|
||||
const vault = (window.__vaultList || []).find((v) => v.id === id);
|
||||
if (!vault && id) {
|
||||
// New vault created by starter - create it on the server
|
||||
const xhr = new XMLHttpRequest();
|
||||
xhr.open("POST", "/api/vault/create", false);
|
||||
xhr.setRequestHeader("Content-Type", "application/json");
|
||||
xhr.send(JSON.stringify({ name: id }));
|
||||
if (xhr.status >= 400) return "Failed to create vault";
|
||||
}
|
||||
// Navigate - use parent if in iframe, otherwise current window
|
||||
const target = window.parent !== window ? window.parent : window;
|
||||
target.location.href = "/?vault=" + encodeURIComponent(id);
|
||||
return true;
|
||||
@@ -90,7 +66,6 @@ const syncHandlers = {
|
||||
return xhr.status < 400;
|
||||
},
|
||||
"vault-move": (oldPath, newPath) => {
|
||||
// Not supported in web context
|
||||
return "Moving vaults is not supported in the web version";
|
||||
},
|
||||
"vault-message": () => null,
|
||||
@@ -105,10 +80,6 @@ export const ipcRenderer = {
|
||||
send(channel, ...args) {
|
||||
console.log("[shim:ipcRenderer] send:", channel, args);
|
||||
|
||||
// context-menu: Obsidian sends this and waits (up to 1s) for a response.
|
||||
// In Electron, the main process returns spell-check info + edit flags.
|
||||
// We reply immediately with a response object so Obsidian proceeds to
|
||||
// build and show its HTML context menu without delay.
|
||||
if (channel === "context-menu") {
|
||||
queueMicrotask(() =>
|
||||
ipcRenderer._emit("context-menu", {
|
||||
@@ -163,7 +134,6 @@ export const ipcRenderer = {
|
||||
return ipcRenderer;
|
||||
},
|
||||
|
||||
// Internal: emit an event to registered listeners (used by ws bridge)
|
||||
_emit(channel, ...args) {
|
||||
const arr = listeners.get(channel);
|
||||
if (arr) {
|
||||
|
||||
@@ -1,36 +1,32 @@
|
||||
// Shim for remote.app
|
||||
// Obsidian uses: getPath, getVersion, getName, quit, isPackaged, getLocale
|
||||
|
||||
export const appShim = {
|
||||
getPath(name) {
|
||||
// Return web-friendly paths; config lives server-side in the vault's .obsidian/ dir
|
||||
const paths = {
|
||||
userData: '/.obsidian',
|
||||
home: '/',
|
||||
documents: '/documents',
|
||||
desktop: '/desktop',
|
||||
temp: '/tmp',
|
||||
appData: '/.obsidian',
|
||||
userData: "/.obsidian",
|
||||
home: "/",
|
||||
documents: "/documents",
|
||||
desktop: "/desktop",
|
||||
temp: "/tmp",
|
||||
appData: "/.obsidian",
|
||||
};
|
||||
return paths[name] || '/';
|
||||
return paths[name] || "/";
|
||||
},
|
||||
|
||||
getVersion() {
|
||||
return '1.8.9';
|
||||
return "1.8.9";
|
||||
},
|
||||
|
||||
getName() {
|
||||
return 'Obsidian';
|
||||
return "Obsidian";
|
||||
},
|
||||
|
||||
getLocale() {
|
||||
return navigator.language || 'en-US';
|
||||
return navigator.language || "en-US";
|
||||
},
|
||||
|
||||
isPackaged: true,
|
||||
|
||||
quit() {
|
||||
console.log('[shim:app] quit (stub)');
|
||||
console.log("[shim:app] quit (stub)");
|
||||
},
|
||||
|
||||
relaunch() {
|
||||
|
||||
@@ -1,35 +1,29 @@
|
||||
// Shim for remote.clipboard
|
||||
// Obsidian uses: readText, writeText, readImage, writeImage, readHTML, writeHTML
|
||||
|
||||
export const clipboardShim = {
|
||||
readText() {
|
||||
// navigator.clipboard.readText() is async; return empty for sync calls
|
||||
// TODO: maintain a local mirror updated via async reads
|
||||
return '';
|
||||
return "";
|
||||
},
|
||||
|
||||
writeText(text) {
|
||||
navigator.clipboard.writeText(text).catch((e) => {
|
||||
console.warn('[shim:clipboard] writeText failed:', e);
|
||||
console.warn("[shim:clipboard] writeText failed:", e);
|
||||
});
|
||||
},
|
||||
|
||||
readHTML() {
|
||||
return '';
|
||||
return "";
|
||||
},
|
||||
|
||||
writeHTML(html) {
|
||||
// TODO: use clipboard API with text/html mime type
|
||||
console.log('[shim:clipboard] writeHTML (stub)');
|
||||
console.log("[shim:clipboard] writeHTML (stub)");
|
||||
},
|
||||
|
||||
readImage() {
|
||||
// TODO: implement if needed
|
||||
return { isEmpty: () => true, toPNG: () => new Uint8Array(0) };
|
||||
},
|
||||
|
||||
writeImage(image) {
|
||||
console.log('[shim:clipboard] writeImage (stub)');
|
||||
console.log("[shim:clipboard] writeImage (stub)");
|
||||
},
|
||||
|
||||
has(format) {
|
||||
@@ -37,10 +31,10 @@ export const clipboardShim = {
|
||||
},
|
||||
|
||||
read(format) {
|
||||
return '';
|
||||
return "";
|
||||
},
|
||||
|
||||
clear() {
|
||||
navigator.clipboard.writeText('').catch(() => {});
|
||||
navigator.clipboard.writeText("").catch(() => {});
|
||||
},
|
||||
};
|
||||
|
||||
@@ -1,38 +1,40 @@
|
||||
// Shim for remote.dialog
|
||||
// Obsidian uses: showOpenDialog, showSaveDialog, showMessageBox, showErrorBox
|
||||
|
||||
export const dialogShim = {
|
||||
async showOpenDialog(browserWindow, options) {
|
||||
// TODO: implement custom modal UI with server-side file listing
|
||||
console.log('[shim:dialog] showOpenDialog (stub):', options);
|
||||
// TODO: implement custom modal with server-side file listing
|
||||
console.log("[shim:dialog] showOpenDialog (stub):", options);
|
||||
return { canceled: true, filePaths: [] };
|
||||
},
|
||||
|
||||
async showSaveDialog(browserWindow, options) {
|
||||
// TODO: implement custom modal UI
|
||||
console.log('[shim:dialog] showSaveDialog (stub):', options);
|
||||
// TODO: implement custom modal
|
||||
console.log("[shim:dialog] showSaveDialog (stub):", options);
|
||||
return { canceled: true, filePath: undefined };
|
||||
},
|
||||
|
||||
async showMessageBox(browserWindow, options) {
|
||||
// TODO: implement custom modal matching Electron's return format
|
||||
// For now, use browser confirm/alert as rough approximation
|
||||
if (typeof browserWindow === 'object' && !options) {
|
||||
if (typeof browserWindow === "object" && !options) {
|
||||
options = browserWindow;
|
||||
}
|
||||
console.log('[shim:dialog] showMessageBox:', options);
|
||||
console.log("[shim:dialog] showMessageBox:", options);
|
||||
|
||||
const message = options.message || '';
|
||||
const detail = options.detail || '';
|
||||
const buttons = options.buttons || ['OK'];
|
||||
const message = options.message || "";
|
||||
const detail = options.detail || "";
|
||||
const buttons = options.buttons || ["OK"];
|
||||
|
||||
// Simple fallback: use confirm for 2-button, alert for 1-button
|
||||
if (buttons.length <= 1) {
|
||||
alert(message + (detail ? '\n\n' + detail : ''));
|
||||
alert(message + (detail ? "\n\n" + detail : ""));
|
||||
return { response: 0, checkboxChecked: false };
|
||||
}
|
||||
|
||||
const result = confirm(message + (detail ? '\n\n' + detail : '') + '\n\n[OK] = "' + buttons[0] + '", [Cancel] = "' + buttons[1] + '"');
|
||||
const result = confirm(
|
||||
message +
|
||||
(detail ? "\n\n" + detail : "") +
|
||||
'\n\n[OK] = "' +
|
||||
buttons[0] +
|
||||
'", [Cancel] = "' +
|
||||
buttons[1] +
|
||||
'"',
|
||||
);
|
||||
return {
|
||||
response: result ? 0 : 1,
|
||||
checkboxChecked: false,
|
||||
@@ -40,7 +42,7 @@ export const dialogShim = {
|
||||
},
|
||||
|
||||
showErrorBox(title, content) {
|
||||
console.error('[shim:dialog] Error:', title, content);
|
||||
alert(title + '\n\n' + content);
|
||||
console.error("[shim:dialog] Error:", title, content);
|
||||
alert(title + "\n\n" + content);
|
||||
},
|
||||
};
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
// @electron/remote shim
|
||||
// Returned when Obsidian calls: window.require('@electron/remote')
|
||||
|
||||
import { clipboardShim } from "./clipboard.js";
|
||||
import { shellShim } from "./shell.js";
|
||||
import { dialogShim } from "./dialog.js";
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
// Shim for remote.Menu and remote.MenuItem
|
||||
// Obsidian uses: Menu.buildFromTemplate, Menu.popup, Menu.setApplicationMenu
|
||||
|
||||
export class menuShim {
|
||||
constructor() {
|
||||
this.items = [];
|
||||
@@ -8,13 +5,12 @@ export class menuShim {
|
||||
|
||||
static buildFromTemplate(template) {
|
||||
const menu = new menuShim();
|
||||
menu.items = (template || []).map(item => new menuItemShim(item));
|
||||
menu.items = (template || []).map((item) => new menuItemShim(item));
|
||||
return menu;
|
||||
}
|
||||
|
||||
static setApplicationMenu(menu) {
|
||||
// No native menu bar in browser - no-op
|
||||
console.log('[shim:Menu] setApplicationMenu (stub)');
|
||||
console.log("[shim:Menu] setApplicationMenu (stub)");
|
||||
}
|
||||
|
||||
static getApplicationMenu() {
|
||||
@@ -22,8 +18,8 @@ export class menuShim {
|
||||
}
|
||||
|
||||
popup(options) {
|
||||
// TODO: implement custom HTML context menu rendered at mouse position
|
||||
console.log('[shim:Menu] popup (stub)', options);
|
||||
// TODO: render custom HTML context menu at mouse position
|
||||
console.log("[shim:Menu] popup (stub)", options);
|
||||
}
|
||||
|
||||
append(menuItem) {
|
||||
@@ -41,19 +37,19 @@ export class menuShim {
|
||||
|
||||
export class menuItemShim {
|
||||
constructor(options = {}) {
|
||||
this.label = options.label || '';
|
||||
this.type = options.type || 'normal';
|
||||
this.label = options.label || "";
|
||||
this.type = options.type || "normal";
|
||||
this.click = options.click || null;
|
||||
this.role = options.role || null;
|
||||
this.accelerator = options.accelerator || '';
|
||||
this.accelerator = options.accelerator || "";
|
||||
this.enabled = options.enabled !== false;
|
||||
this.visible = options.visible !== false;
|
||||
this.checked = !!options.checked;
|
||||
this.submenu = options.submenu
|
||||
? menuShim.buildFromTemplate(
|
||||
Array.isArray(options.submenu) ? options.submenu : []
|
||||
Array.isArray(options.submenu) ? options.submenu : [],
|
||||
)
|
||||
: null;
|
||||
this.id = options.id || '';
|
||||
this.id = options.id || "";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
// Shim for remote.nativeImage
|
||||
// Minimal stub - Obsidian's renderer-side usage is limited
|
||||
|
||||
export const nativeImageShim = {
|
||||
createFromBuffer(buffer) {
|
||||
return {
|
||||
@@ -8,7 +5,7 @@ export const nativeImageShim = {
|
||||
getSize: () => ({ width: 0, height: 0 }),
|
||||
toPNG: () => buffer || new Uint8Array(0),
|
||||
toJPEG: (quality) => buffer || new Uint8Array(0),
|
||||
toDataURL: () => '',
|
||||
toDataURL: () => "",
|
||||
};
|
||||
},
|
||||
|
||||
|
||||
@@ -1,21 +1,24 @@
|
||||
// Shim for remote.Notification
|
||||
// Maps to browser Notification API
|
||||
|
||||
export class notificationShim {
|
||||
constructor(options = {}) {
|
||||
this.title = options.title || '';
|
||||
this.body = options.body || '';
|
||||
this.title = options.title || "";
|
||||
this.body = options.body || "";
|
||||
this.silent = options.silent || false;
|
||||
this._handlers = {};
|
||||
}
|
||||
|
||||
show() {
|
||||
if ('Notification' in window && Notification.permission === 'granted') {
|
||||
if ("Notification" in window && Notification.permission === "granted") {
|
||||
new Notification(this.title, { body: this.body, silent: this.silent });
|
||||
} else if ('Notification' in window && Notification.permission !== 'denied') {
|
||||
} else if (
|
||||
"Notification" in window &&
|
||||
Notification.permission !== "denied"
|
||||
) {
|
||||
Notification.requestPermission().then((perm) => {
|
||||
if (perm === 'granted') {
|
||||
new Notification(this.title, { body: this.body, silent: this.silent });
|
||||
if (perm === "granted") {
|
||||
new Notification(this.title, {
|
||||
body: this.body,
|
||||
silent: this.silent,
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -29,6 +32,6 @@ export class notificationShim {
|
||||
}
|
||||
|
||||
static isSupported() {
|
||||
return 'Notification' in window;
|
||||
return "Notification" in window;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +1,24 @@
|
||||
// Shim for remote.screen
|
||||
// Obsidian uses screen for display/monitor info
|
||||
|
||||
export const screenShim = {
|
||||
getPrimaryDisplay() {
|
||||
return {
|
||||
workAreaSize: { width: window.screen.availWidth, height: window.screen.availHeight },
|
||||
workAreaSize: {
|
||||
width: window.screen.availWidth,
|
||||
height: window.screen.availHeight,
|
||||
},
|
||||
size: { width: window.screen.width, height: window.screen.height },
|
||||
scaleFactor: window.devicePixelRatio || 1,
|
||||
bounds: { x: 0, y: 0, width: window.screen.width, height: window.screen.height },
|
||||
workArea: { x: 0, y: 0, width: window.screen.availWidth, height: window.screen.availHeight },
|
||||
bounds: {
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: window.screen.width,
|
||||
height: window.screen.height,
|
||||
},
|
||||
workArea: {
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: window.screen.availWidth,
|
||||
height: window.screen.availHeight,
|
||||
},
|
||||
};
|
||||
},
|
||||
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
// Shim for remote.session
|
||||
// Mostly no-op; Obsidian's use is minimal
|
||||
|
||||
export const sessionShim = {
|
||||
defaultSession: {
|
||||
clearCache() {
|
||||
@@ -12,7 +9,9 @@ export const sessionShim = {
|
||||
},
|
||||
|
||||
setSpellCheckerLanguages(langs) {},
|
||||
getSpellCheckerLanguages() { return []; },
|
||||
getSpellCheckerLanguages() {
|
||||
return [];
|
||||
},
|
||||
|
||||
on() {},
|
||||
once() {},
|
||||
|
||||
@@ -1,20 +1,15 @@
|
||||
// Shim for remote.shell
|
||||
// Obsidian uses: openExternal, openPath, showItemInFolder
|
||||
|
||||
export const shellShim = {
|
||||
openExternal(url) {
|
||||
window.open(url, '_blank');
|
||||
window.open(url, "_blank");
|
||||
return Promise.resolve();
|
||||
},
|
||||
|
||||
openPath(filePath) {
|
||||
// TODO: could trigger a server-side download or preview
|
||||
console.log('[shim:shell] openPath (stub):', filePath);
|
||||
return Promise.resolve('');
|
||||
console.log("[shim:shell] openPath (stub):", filePath);
|
||||
return Promise.resolve("");
|
||||
},
|
||||
|
||||
showItemInFolder(filePath) {
|
||||
// No OS file manager in browser context
|
||||
console.log('[shim:shell] showItemInFolder (stub):', filePath);
|
||||
console.log("[shim:shell] showItemInFolder (stub):", filePath);
|
||||
},
|
||||
};
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
// Shim for remote.systemPreferences
|
||||
// No-op with safe defaults
|
||||
|
||||
export const systemPreferencesShim = {
|
||||
getAccentColor() {
|
||||
return '0078d4'; // Default Windows accent blue
|
||||
return "0078d4"; // Default Windows accent blue
|
||||
},
|
||||
|
||||
isAeroGlassEnabled() {
|
||||
@@ -11,7 +8,7 @@ export const systemPreferencesShim = {
|
||||
},
|
||||
|
||||
getMediaAccessStatus(mediaType) {
|
||||
return 'granted';
|
||||
return "granted";
|
||||
},
|
||||
|
||||
askForMediaAccess(mediaType) {
|
||||
|
||||
@@ -1,14 +1,12 @@
|
||||
// Shim for remote.nativeTheme
|
||||
// Obsidian uses: shouldUseDarkColors, on('updated', cb)
|
||||
|
||||
const listeners = [];
|
||||
|
||||
const darkQuery = typeof window !== 'undefined'
|
||||
? window.matchMedia('(prefers-color-scheme: dark)')
|
||||
: null;
|
||||
const darkQuery =
|
||||
typeof window !== "undefined"
|
||||
? window.matchMedia("(prefers-color-scheme: dark)")
|
||||
: null;
|
||||
|
||||
if (darkQuery?.addEventListener) {
|
||||
darkQuery.addEventListener('change', () => {
|
||||
darkQuery.addEventListener("change", () => {
|
||||
for (const fn of listeners) {
|
||||
fn();
|
||||
}
|
||||
@@ -21,7 +19,7 @@ export const themeShim = {
|
||||
},
|
||||
|
||||
get themeSource() {
|
||||
return 'system';
|
||||
return "system";
|
||||
},
|
||||
|
||||
set themeSource(val) {
|
||||
@@ -29,14 +27,14 @@ export const themeShim = {
|
||||
},
|
||||
|
||||
on(event, callback) {
|
||||
if (event === 'updated') {
|
||||
if (event === "updated") {
|
||||
listeners.push(callback);
|
||||
}
|
||||
return themeShim;
|
||||
},
|
||||
|
||||
once(event, callback) {
|
||||
if (event === 'updated') {
|
||||
if (event === "updated") {
|
||||
const wrapped = () => {
|
||||
const idx = listeners.indexOf(wrapped);
|
||||
if (idx >= 0) listeners.splice(idx, 1);
|
||||
|
||||
@@ -1,8 +1,3 @@
|
||||
// Shim for remote.getCurrentWindow() / remote.BrowserWindow
|
||||
// Obsidian uses: isMaximized, isMinimized, isFullScreen, minimize, maximize,
|
||||
// unmaximize, close, setTitle, setAlwaysOnTop, isAlwaysOnTop,
|
||||
// getBounds, setBounds, show, focus, setFullScreen, etc.
|
||||
|
||||
const currentWindowState = {
|
||||
title: "Obsidian",
|
||||
isMaximized: false,
|
||||
@@ -80,7 +75,6 @@ const currentWindow = {
|
||||
},
|
||||
|
||||
setBounds(bounds) {
|
||||
// Cannot resize browser window from JS
|
||||
console.log("[shim:window] setBounds (stub):", bounds);
|
||||
},
|
||||
|
||||
@@ -113,7 +107,6 @@ const currentWindow = {
|
||||
},
|
||||
|
||||
on(event, handler) {
|
||||
// Map some Electron window events to browser equivalents
|
||||
if (event === "focus") window.addEventListener("focus", handler);
|
||||
else if (event === "blur") window.addEventListener("blur", handler);
|
||||
else if (event === "resize") window.addEventListener("resize", handler);
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
// Shim for electron.webFrame
|
||||
// Obsidian uses: getZoomLevel(), setZoomLevel()
|
||||
|
||||
let currentZoom = 0;
|
||||
|
||||
export const webFrame = {
|
||||
|
||||
Reference in New Issue
Block a user