mirror of
https://github.com/dragonwocky/obsidian-tray.git
synced 2025-04-11 14:59:02 +00:00
Compare commits
19 Commits
Author | SHA1 | Date | |
---|---|---|---|
f4e827253d | |||
|
62fcf88fe6 | ||
|
09fe3c2d03 | ||
cc0baa3226 | |||
6a76f575ed | |||
b60e453b68 | |||
999213801f | |||
77ce4bd54a | |||
096bb34d54 | |||
fb15c25171 | |||
b62d8862ab | |||
4c0c3da898 | |||
b8326526ef | |||
5cef2b0ed7 | |||
78e819cc45 | |||
|
71ba850a15 | ||
a5abaf32e7 | |||
d49c49fe83 | |||
6f81acb0ad |
@ -1,8 +1,8 @@
|
|||||||
<img alt="" src="tray.png" align="right" height="128px">
|
<img alt="" src="tray.png" align="right" height="128px">
|
||||||
|
|
||||||
**Tray** is an [Obsidian](https://obsidian.md/) plugin that can be used to launch the app
|
**Tray** is an [Obsidian](https://obsidian.md/) plugin that can be used to launch the app
|
||||||
on system startup and run it in the background, adding global hotkeys and a tray menu that
|
on system startup and run it in the background, adding global hotkeys and a tray menu to
|
||||||
toggle app window visibility and can create quick notes from anywhere in your operating system.
|
toggle window visibility and create quick notes from anywhere in your operating system.
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
|
||||||
@ -33,7 +33,7 @@ Hotkeys can be assigned to the commands via Obsidian's built-in hotkey manager.
|
|||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
### Obsidian Marketplace (Coming Soon)
|
### Obsidian Marketplace
|
||||||
|
|
||||||
1. In Obsidian, navigate to **Settings** → **Community plugins**.
|
1. In Obsidian, navigate to **Settings** → **Community plugins**.
|
||||||
2. Press the **Browse** button beside the **Community plugins** option.
|
2. Press the **Browse** button beside the **Community plugins** option.
|
||||||
|
129
main.js
129
main.js
@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* obsidian-tray v0.3.2
|
* obsidian-tray v0.3.5
|
||||||
* (c) 2023 dragonwocky <thedragonring.bod@gmail.com> (https://dragonwocky.me/)
|
* (c) 2023 dragonwocky <thedragonring.bod@gmail.com> (https://dragonwocky.me/)
|
||||||
* (https://github.com/dragonwocky/obsidian-tray/) under the MIT license
|
* (https://github.com/dragonwocky/obsidian-tray/) under the MIT license
|
||||||
*/
|
*/
|
||||||
@ -38,31 +38,59 @@ const LOG_PREFIX = "obsidian-tray",
|
|||||||
|
|
||||||
let tray, plugin;
|
let tray, plugin;
|
||||||
const obsidian = require("obsidian"),
|
const obsidian = require("obsidian"),
|
||||||
{ app, Tray, Menu, nativeImage } = require("electron").remote,
|
{ app, Tray, Menu } = require("electron").remote,
|
||||||
|
{ nativeImage, BrowserWindow } = require("electron").remote,
|
||||||
{ getCurrentWindow, globalShortcut } = require("electron").remote;
|
{ getCurrentWindow, globalShortcut } = require("electron").remote;
|
||||||
|
|
||||||
const childWindows = new Set(),
|
const vaultWindows = new Set(),
|
||||||
observeChildWindows = () => {
|
maximizedWindows = new Set(),
|
||||||
getCurrentWindow().webContents.on("did-create-window", (win) => {
|
getWindows = () => [...vaultWindows],
|
||||||
childWindows.add(win);
|
observeWindows = () => {
|
||||||
win.on("close", () => childWindows.delete(win));
|
const onWindowCreation = (win) => {
|
||||||
|
vaultWindows.add(win);
|
||||||
win.setSkipTaskbar(plugin.settings.hideTaskbarIcon);
|
win.setSkipTaskbar(plugin.settings.hideTaskbarIcon);
|
||||||
});
|
win.on("close", () => {
|
||||||
|
if (win !== getCurrentWindow()) vaultWindows.delete(win);
|
||||||
|
});
|
||||||
|
// preserve maximised windows after minimisation
|
||||||
|
if (win.isMaximized()) maximizedWindows.add(win);
|
||||||
|
win.on("maximize", () => maximizedWindows.add(win));
|
||||||
|
win.on("unmaximize", () => maximizedWindows.delete(win));
|
||||||
|
};
|
||||||
|
onWindowCreation(getCurrentWindow());
|
||||||
|
getCurrentWindow().webContents.on("did-create-window", onWindowCreation);
|
||||||
|
if (process.platform === "darwin") {
|
||||||
|
// on macos, the "hide taskbar icon" option is implemented
|
||||||
|
// via app.dock.hide(): thus, the app as a whole will be
|
||||||
|
// hidden from the dock, including windows from other vaults.
|
||||||
|
// when a vault is closed via the "close vault" button,
|
||||||
|
// the cleanup process will call app.dock.show() to restore
|
||||||
|
// access to any other open vaults w/out the tray enabled
|
||||||
|
// => thus, this listener is required to re-hide the dock
|
||||||
|
// if switching to another vault with the option enabled
|
||||||
|
getCurrentWindow().on("focus", () => {
|
||||||
|
if (plugin.settings.hideTaskbarIcon) hideTaskbarIcons();
|
||||||
|
});
|
||||||
|
}
|
||||||
},
|
},
|
||||||
getAllWindows = () => [...childWindows, getCurrentWindow()],
|
|
||||||
showWindows = () => {
|
showWindows = () => {
|
||||||
log(LOG_SHOWING_WINDOWS);
|
log(LOG_SHOWING_WINDOWS);
|
||||||
getAllWindows().forEach((win) => win.show());
|
getWindows().forEach((win) => {
|
||||||
|
if (maximizedWindows.has(win)) {
|
||||||
|
win.maximize();
|
||||||
|
win.focus();
|
||||||
|
} else win.show();
|
||||||
|
});
|
||||||
},
|
},
|
||||||
hideWindows = () => {
|
hideWindows = () => {
|
||||||
log(LOG_HIDING_WINDOWS);
|
log(LOG_HIDING_WINDOWS);
|
||||||
getAllWindows().forEach((win) => [
|
getWindows().forEach((win) => [
|
||||||
win.isFocused() && win.blur(),
|
win.isFocused() && win.blur(),
|
||||||
plugin.settings.runInBackground ? win.hide() : win.minimize(),
|
plugin.settings.runInBackground ? win.hide() : win.minimize(),
|
||||||
]);
|
]);
|
||||||
},
|
},
|
||||||
toggleWindows = (checkForFocus = true) => {
|
toggleWindows = (checkForFocus = true) => {
|
||||||
const openWindows = getAllWindows().some((win) => {
|
const openWindows = getWindows().some((win) => {
|
||||||
return (!checkForFocus || win.isFocused()) && win.isVisible();
|
return (!checkForFocus || win.isFocused()) && win.isVisible();
|
||||||
});
|
});
|
||||||
if (openWindows) hideWindows();
|
if (openWindows) hideWindows();
|
||||||
@ -91,10 +119,13 @@ const onWindowClose = (event) => event.preventDefault(),
|
|||||||
window.removeEventListener("beforeunload", onWindowUnload, true);
|
window.removeEventListener("beforeunload", onWindowUnload, true);
|
||||||
};
|
};
|
||||||
|
|
||||||
const setHideTaskbarIcon = () => {
|
const hideTaskbarIcons = () => {
|
||||||
getAllWindows().forEach((win) => {
|
getWindows().forEach((win) => win.setSkipTaskbar(true));
|
||||||
win.setSkipTaskbar(plugin.settings.hideTaskbarIcon);
|
if (process.platform === "darwin") app.dock.hide();
|
||||||
});
|
},
|
||||||
|
showTaskbarIcons = () => {
|
||||||
|
getWindows().forEach((win) => win.setSkipTaskbar(false));
|
||||||
|
if (process.platform === "darwin") app.dock.show();
|
||||||
},
|
},
|
||||||
setLaunchOnStartup = () => {
|
setLaunchOnStartup = () => {
|
||||||
const { launchOnStartup, runInBackground, hideOnLaunch } = plugin.settings;
|
const { launchOnStartup, runInBackground, hideOnLaunch } = plugin.settings;
|
||||||
@ -102,6 +133,14 @@ const setHideTaskbarIcon = () => {
|
|||||||
openAtLogin: launchOnStartup,
|
openAtLogin: launchOnStartup,
|
||||||
openAsHidden: runInBackground && hideOnLaunch,
|
openAsHidden: runInBackground && hideOnLaunch,
|
||||||
});
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const cleanup = () => {
|
||||||
|
log(LOG_CLEANUP);
|
||||||
|
unregisterHotkeys();
|
||||||
|
showTaskbarIcons();
|
||||||
|
allowWindowClose();
|
||||||
|
destroyTray();
|
||||||
},
|
},
|
||||||
relaunchApp = () => {
|
relaunchApp = () => {
|
||||||
app.relaunch();
|
app.relaunch();
|
||||||
@ -109,10 +148,14 @@ const setHideTaskbarIcon = () => {
|
|||||||
},
|
},
|
||||||
closeVault = () => {
|
closeVault = () => {
|
||||||
log(LOG_CLEANUP);
|
log(LOG_CLEANUP);
|
||||||
unregisterHotkeys();
|
cleanup();
|
||||||
allowWindowClose();
|
const vaultWindows = getWindows(),
|
||||||
destroyTray();
|
obsidianWindows = BrowserWindow.getAllWindows();
|
||||||
getAllWindows().forEach((win) => win.destroy());
|
if (obsidianWindows.length === vaultWindows.length) {
|
||||||
|
// quit app directly if only remaining windows are in the
|
||||||
|
// current vault - necessary for successful quit on macos
|
||||||
|
app.quit();
|
||||||
|
} else vaultWindows.forEach((win) => win.destroy());
|
||||||
};
|
};
|
||||||
|
|
||||||
const addQuickNote = () => {
|
const addQuickNote = () => {
|
||||||
@ -121,8 +164,18 @@ const addQuickNote = () => {
|
|||||||
date = obsidian.moment().format(pattern),
|
date = obsidian.moment().format(pattern),
|
||||||
name = obsidian
|
name = obsidian
|
||||||
.normalizePath(`${quickNoteLocation ?? ""}/${date}`)
|
.normalizePath(`${quickNoteLocation ?? ""}/${date}`)
|
||||||
.replace(/\*|"|\\|<|>|:|\||\?/g, "-");
|
.replace(/\*|"|\\|<|>|:|\||\?/g, "-"),
|
||||||
plugin.app.fileManager.createAndOpenMarkdownFile(name);
|
// manually create and open file instead of depending
|
||||||
|
// on createAndOpenMarkdownFile to force file creation
|
||||||
|
// relative to the root instead of the active file
|
||||||
|
// (in case user has default location for new notes
|
||||||
|
// set to "same folder as current file")
|
||||||
|
leaf = plugin.app.workspace.getLeaf(),
|
||||||
|
root = plugin.app.fileManager.getNewFileParent(""),
|
||||||
|
openMode = { active: true, state: { mode: "source" } };
|
||||||
|
plugin.app.fileManager
|
||||||
|
.createNewMarkdownFile(root, name)
|
||||||
|
.then((file) => leaf.openFile(file, openMode));
|
||||||
showWindows();
|
showWindows();
|
||||||
},
|
},
|
||||||
replaceVaultName = (str) => {
|
replaceVaultName = (str) => {
|
||||||
@ -165,7 +218,13 @@ const addQuickNote = () => {
|
|||||||
tray = new Tray(obsidianIcon);
|
tray = new Tray(obsidianIcon);
|
||||||
tray.setContextMenu(contextMenu);
|
tray.setContextMenu(contextMenu);
|
||||||
tray.setToolTip(replaceVaultName(plugin.settings.trayIconTooltip));
|
tray.setToolTip(replaceVaultName(plugin.settings.trayIconTooltip));
|
||||||
tray.on("click", () => toggleWindows(false));
|
tray.on("click", () => {
|
||||||
|
if (process.platform === "darwin") {
|
||||||
|
// macos does not register separate left/right click actions
|
||||||
|
// for menu items, icon should open menu w/out causing toggle
|
||||||
|
tray.popUpContextMenu();
|
||||||
|
} else toggleWindows(false);
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const registerHotkeys = () => {
|
const registerHotkeys = () => {
|
||||||
@ -217,8 +276,8 @@ const OPTIONS = [
|
|||||||
default: false,
|
default: false,
|
||||||
onChange() {
|
onChange() {
|
||||||
setLaunchOnStartup();
|
setLaunchOnStartup();
|
||||||
const runInBackground = plugin.settings.runInBackground;
|
if (plugin.settings.runInBackground) interceptWindowClose();
|
||||||
if (!runInBackground) showWindows();
|
else [allowWindowClose(), showWindows()];
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -229,7 +288,10 @@ const OPTIONS = [
|
|||||||
`,
|
`,
|
||||||
type: "toggle",
|
type: "toggle",
|
||||||
default: false,
|
default: false,
|
||||||
onChange: setHideTaskbarIcon,
|
onChange() {
|
||||||
|
if (plugin.settings.hideTaskbarIcon) hideTaskbarIcons();
|
||||||
|
else showTaskbarIcons();
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: "createTrayIcon",
|
key: "createTrayIcon",
|
||||||
@ -391,10 +453,10 @@ class TrayPlugin extends obsidian.Plugin {
|
|||||||
plugin = this;
|
plugin = this;
|
||||||
createTrayIcon();
|
createTrayIcon();
|
||||||
registerHotkeys();
|
registerHotkeys();
|
||||||
setHideTaskbarIcon();
|
|
||||||
setLaunchOnStartup();
|
setLaunchOnStartup();
|
||||||
observeChildWindows();
|
observeWindows();
|
||||||
if (settings.runInBackground) interceptWindowClose();
|
if (settings.runInBackground) interceptWindowClose();
|
||||||
|
if (settings.hideTaskbarIcon) hideTaskbarIcons();
|
||||||
if (settings.hideOnLaunch) {
|
if (settings.hideOnLaunch) {
|
||||||
this.registerEvent(this.app.workspace.onLayoutReady(hideWindows));
|
this.registerEvent(this.app.workspace.onLayoutReady(hideWindows));
|
||||||
}
|
}
|
||||||
@ -413,12 +475,15 @@ class TrayPlugin extends obsidian.Plugin {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
onunload() {
|
onunload() {
|
||||||
log(LOG_CLEANUP);
|
cleanup();
|
||||||
unregisterHotkeys();
|
|
||||||
allowWindowClose();
|
|
||||||
destroyTray();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getCurrentWindow = getCurrentWindow
|
||||||
|
getWindows = getWindows;
|
||||||
|
showWindows = showWindows;
|
||||||
|
hideWindows = hideWindows;
|
||||||
|
toggleWindows = toggleWindows;
|
||||||
|
|
||||||
async loadSettings() {
|
async loadSettings() {
|
||||||
const DEFAULT_SETTINGS = OPTIONS.map((opt) => ({ [opt.key]: opt.default }));
|
const DEFAULT_SETTINGS = OPTIONS.map((opt) => ({ [opt.key]: opt.default }));
|
||||||
this.settings = Object.assign(...DEFAULT_SETTINGS, await this.loadData());
|
this.settings = Object.assign(...DEFAULT_SETTINGS, await this.loadData());
|
||||||
|
@ -3,8 +3,8 @@
|
|||||||
"name": "Tray",
|
"name": "Tray",
|
||||||
"author": "dragonwocky",
|
"author": "dragonwocky",
|
||||||
"authorUrl": "https://dragonwocky.me/",
|
"authorUrl": "https://dragonwocky.me/",
|
||||||
"description": "Launch Obsidian on startup and run it in the background from the system tray.",
|
"description": "Run Obsidian from the system tray for customisable window management & global quick notes",
|
||||||
"version": "0.3.2",
|
"version": "0.3.5",
|
||||||
"isDesktopOnly": true,
|
"isDesktopOnly": true,
|
||||||
"minAppVersion": "1.0.0"
|
"minAppVersion": "1.0.0"
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user