mirror of
				https://github.com/dragonwocky/obsidian-tray.git
				synced 2025-10-26 19:58:07 +11:00 
			
		
		
		
	feat: #10 add quick notes via tray or hotkey
This commit is contained in:
		
							parent
							
								
									d34a8edf42
								
							
						
					
					
						commit
						da54fc0937
					
				
							
								
								
									
										16
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								README.md
									
									
									
									
									
								
							| @ -1,11 +1,13 @@ | |||||||
| <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 an icon to the system tray that it | on system startup and run it in the background, adding global hotkeys and a tray menu that | ||||||
| can be minimised to and a global hotkey to toggle visibility of the app's windows. | toggle app window visibility and can create quick notes from anywhere in your operating system. | ||||||
| 
 | 
 | ||||||
| ## Configuration | ## Configuration | ||||||
| 
 | 
 | ||||||
|  | ### Window management | ||||||
|  | 
 | ||||||
| | Option                     | Description                                                                                                                                                                                                                        | Default             | | | Option                     | Description                                                                                                                                                                                                                        | Default             | | ||||||
| | -------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------- | | | -------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------- | | ||||||
| | Launch on startup          | Open Obsidian automatically whenever you log into your computer.                                                                                                                                                                   | Disabled            | | | Launch on startup          | Open Obsidian automatically whenever you log into your computer.                                                                                                                                                                   | Disabled            | | ||||||
| @ -13,7 +15,15 @@ can be minimised to and a global hotkey to toggle visibility of the app's window | |||||||
| | Run in background          | Hide the app and continue to run it in the background instead of quitting it when pressing the window close button or toggle focus hotkey.                                                                                         | Disabled            | | | Run in background          | Hide the app and continue to run it in the background instead of quitting it when pressing the window close button or toggle focus hotkey.                                                                                         | Disabled            | | ||||||
| | Hide taskbar icon          | Hides the window's icon from from the dock/taskbar. This may not work on all Linux-based OSes.                                                                                                                                     | Disabled            | | | Hide taskbar icon          | Hides the window's icon from from the dock/taskbar. This may not work on all Linux-based OSes.                                                                                                                                     | Disabled            | | ||||||
| | Create tray icon           | Add an icon to your system tray/menubar to bring hidden Obsidian windows back into focus on click or force a full quit/relaunch of the app through the right-click menu. _Changing this option requires a restart to take effect._ | Enabled             | | | Create tray icon           | Add an icon to your system tray/menubar to bring hidden Obsidian windows back into focus on click or force a full quit/relaunch of the app through the right-click menu. _Changing this option requires a restart to take effect._ | Enabled             | | ||||||
| | Toggle window focus hotkey | Format: [Electron accelerator](https://www.electronjs.org/docs/latest/api/accelerator)                                                                                                                                             | CmdOrCtrl+Shift+Tab | | | Toggle window focus hotkey | This hotkey is registered globally and will be detected even if Obsidian does not have keyboard focus. Format: [Electron accelerator](https://www.electronjs.org/docs/latest/api/accelerator)                                      | CmdOrCtrl+Shift+Tab | | ||||||
|  | 
 | ||||||
|  | ### Quick notes | ||||||
|  | 
 | ||||||
|  | | Option                 | Description                                                                                                                                                                                   | Default    | | ||||||
|  | | ---------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- | | ||||||
|  | | Quick note location    | New quick notes will be placed in this folder.                                                                                                                                                |            | | ||||||
|  | | Quick note date format | New quick notes will use a filename of this pattern. Format: [Moment.js format string](https://momentjs.com/docs/#/displaying/format/)                                                        | YYYY-MM-DD | | ||||||
|  | | Quick note hotkey      | This hotkey is registered globally and will be detected even if Obsidian does not have keyboard focus. Format: [Electron accelerator](https://www.electronjs.org/docs/latest/api/accelerator) | Disabled   | | ||||||
| 
 | 
 | ||||||
| ## Installation | ## Installation | ||||||
| 
 | 
 | ||||||
|  | |||||||
							
								
								
									
										157
									
								
								main.js
									
									
									
									
									
								
							
							
						
						
									
										157
									
								
								main.js
									
									
									
									
									
								
							| @ -3,6 +3,8 @@ | |||||||
| 
 | 
 | ||||||
| "use strict"; | "use strict"; | ||||||
| 
 | 
 | ||||||
|  | const DEFAULT_DATE_FORMAT = "YYYY-MM-DD"; | ||||||
|  | 
 | ||||||
| let tray; | let tray; | ||||||
| const obsidian = require("obsidian"), | const obsidian = require("obsidian"), | ||||||
|   { |   { | ||||||
| @ -61,7 +63,17 @@ const onWindowClose = (event) => { | |||||||
|     closeBtn.removeEventListener("click", onWindowClose, true); |     closeBtn.removeEventListener("click", onWindowClose, true); | ||||||
|   }; |   }; | ||||||
| 
 | 
 | ||||||
| const setHideTaskbarIcon = (plugin) => { | const addQuickNote = (plugin) => { | ||||||
|  |     const { quickNoteLocation, quickNoteDateFormat } = plugin.settings, | ||||||
|  |       format = quickNoteDateFormat || DEFAULT_DATE_FORMAT, | ||||||
|  |       date = obsidian.moment().format(format), | ||||||
|  |       name = obsidian | ||||||
|  |         .normalizePath(`${quickNoteLocation ?? ""}/${date}`) | ||||||
|  |         .replace(/\*|"|\\|<|>|:|\||\?/g, "-"); | ||||||
|  |     plugin.app.fileManager.createAndOpenMarkdownFile(name); | ||||||
|  |     showWindows(); | ||||||
|  |   }, | ||||||
|  |   setHideTaskbarIcon = (plugin) => { | ||||||
|     const win = getCurrentWindow(); |     const win = getCurrentWindow(); | ||||||
|     win.setSkipTaskbar(plugin.settings.hideTaskbarIcon); |     win.setSkipTaskbar(plugin.settings.hideTaskbarIcon); | ||||||
|   }, |   }, | ||||||
| @ -84,6 +96,12 @@ const createTrayIcon = (plugin) => { | |||||||
|       `data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAHZSURBVDhPlZKxTxRBFMa/XZcF7nIG7mjxjoRCwomJxgsFdhaASqzQxFDzB1AQKgstLGxIiBQGJBpiCCGx8h+wgYaGgAWNd0dyHofeEYVwt/PmOTMZV9aDIL/s5pvZvPfN9yaL/+HR3eXcypta0m4juFbP5GHuXc9IbunDFc9db/G81/ZzhDMN7g8td47mll4R5BfHwZN4LOaA+fHa259PbUmIYzWkt3e2NZNo3/V9v1vvU6kkstk+tLW3ItUVr/m+c3N8MlkwxYqmBFcbwUQQCNOcyVzDwEAWjuPi5DhAMV/tKOYPX5hCyz8Gz1zX5SmWjBvZfmTSaRBJkGAIoxJHv+pVW2yIGNxOJ8bUVNcFEWLxuG1ia6JercTbttwQTeDwPS0kCMXiXtgk/jQrFUw7ptYSMWApF40yo/ytjHq98fdk3ayVE+cn2CxMb6ruz9qAJKFUKoWza1VJSi/n0+ffgYHdWW2gHuxXymg0gjCB0sjpmiaDnkL3RzDyzLqBUKns2ztQqUR0fk2TwSrGSf1eczqF5vsPZRCQSSAFLk6gqctgQRkc6TWRQLV2YMYQki9OoNkqzFQ9r+WOGuW5CrJbOzyAlPKr6MSGLbkcDwbf35oY/jRkt6cAfgNwowruAMz9AgAAAABJRU5ErkJggg==` |       `data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAHZSURBVDhPlZKxTxRBFMa/XZcF7nIG7mjxjoRCwomJxgsFdhaASqzQxFDzB1AQKgstLGxIiBQGJBpiCCGx8h+wgYaGgAWNd0dyHofeEYVwt/PmOTMZV9aDIL/s5pvZvPfN9yaL/+HR3eXcypta0m4juFbP5GHuXc9IbunDFc9db/G81/ZzhDMN7g8td47mll4R5BfHwZN4LOaA+fHa259PbUmIYzWkt3e2NZNo3/V9v1vvU6kkstk+tLW3ItUVr/m+c3N8MlkwxYqmBFcbwUQQCNOcyVzDwEAWjuPi5DhAMV/tKOYPX5hCyz8Gz1zX5SmWjBvZfmTSaRBJkGAIoxJHv+pVW2yIGNxOJ8bUVNcFEWLxuG1ia6JercTbttwQTeDwPS0kCMXiXtgk/jQrFUw7ptYSMWApF40yo/ytjHq98fdk3ayVE+cn2CxMb6ruz9qAJKFUKoWza1VJSi/n0+ffgYHdWW2gHuxXymg0gjCB0sjpmiaDnkL3RzDyzLqBUKns2ztQqUR0fk2TwSrGSf1eczqF5vsPZRCQSSAFLk6gqctgQRkc6TWRQLV2YMYQki9OoNkqzFQ9r+WOGuW5CrJbOzyAlPKr6MSGLbkcDwbf35oY/jRkt6cAfgNwowruAMz9AgAAAABJRU5ErkJggg==` | ||||||
|     ), |     ), | ||||||
|     contextMenu = Menu.buildFromTemplate([ |     contextMenu = Menu.buildFromTemplate([ | ||||||
|  |       { | ||||||
|  |         type: "normal", | ||||||
|  |         label: "Add Quick Note", | ||||||
|  |         accelerator: plugin.settings.quickNoteHotkey, | ||||||
|  |         click: () => addQuickNote(plugin), | ||||||
|  |       }, | ||||||
|       { |       { | ||||||
|         type: "normal", |         type: "normal", | ||||||
|         label: "Open Obsidian", |         label: "Open Obsidian", | ||||||
| @ -112,25 +130,36 @@ const createTrayIcon = (plugin) => { | |||||||
|   tray.on("click", () => toggleWindows(plugin.settings.runInBackground, false)); |   tray.on("click", () => toggleWindows(plugin.settings.runInBackground, false)); | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| const registerHotkey = (plugin) => { | const registerHotkeys = (plugin) => { | ||||||
|     console.log("obsidian-tray: registering hotkey"); |     console.log("obsidian-tray: registering hotkey"); | ||||||
|     try { |     try { | ||||||
|       const accelerator = plugin.settings.toggleWindowFocusHotkey; |       const toggleAccelerator = plugin.settings.toggleWindowFocusHotkey, | ||||||
|       globalShortcut.register(accelerator, () => { |         quicknoteAccelerator = plugin.settings.quickNoteHotkey; | ||||||
|         const runInBackground = plugin.settings.runInBackground; |       if (toggleAccelerator) { | ||||||
|         toggleWindows(runInBackground); |         globalShortcut.register(toggleAccelerator, () => { | ||||||
|       }); |           const runInBackground = plugin.settings.runInBackground; | ||||||
|  |           toggleWindows(runInBackground); | ||||||
|  |         }); | ||||||
|  |       } | ||||||
|  |       if (quicknoteAccelerator) { | ||||||
|  |         globalShortcut.register(quicknoteAccelerator, () => { | ||||||
|  |           addQuickNote(plugin); | ||||||
|  |         }); | ||||||
|  |       } | ||||||
|     } catch {} |     } catch {} | ||||||
|   }, |   }, | ||||||
|   unregisterHotkey = (plugin) => { |   unregisterHotkeys = (plugin) => { | ||||||
|     console.log("obsidian-tray: unregistering hotkey"); |     console.log("obsidian-tray: unregistering hotkey"); | ||||||
|     try { |     try { | ||||||
|       const accelerator = plugin.settings.toggleWindowFocusHotkey; |       const toggle = plugin.settings.toggleWindowFocusHotkey, | ||||||
|       globalShortcut.unregister(accelerator); |         quicknote = plugin.settings.quickNoteHotkey; | ||||||
|  |       globalShortcut.unregister(toggle); | ||||||
|  |       globalShortcut.unregister(quicknote); | ||||||
|     } catch {} |     } catch {} | ||||||
|   }; |   }; | ||||||
| 
 | 
 | ||||||
| const OPTIONS = [ | const OPTIONS = [ | ||||||
|  |   "Window management", | ||||||
|   { |   { | ||||||
|     key: "launchOnStartup", |     key: "launchOnStartup", | ||||||
|     desc: "Open Obsidian automatically whenever you log into your computer.", |     desc: "Open Obsidian automatically whenever you log into your computer.", | ||||||
| @ -185,16 +214,26 @@ const OPTIONS = [ | |||||||
|   }, |   }, | ||||||
|   { |   { | ||||||
|     key: "toggleWindowFocusHotkey", |     key: "toggleWindowFocusHotkey", | ||||||
|     desc: ` |     type: "hotkey", | ||||||
|       Format: |  | ||||||
|       <a href="https://www.electronjs.org/docs/latest/api/accelerator"> |  | ||||||
|         Electron accelerator |  | ||||||
|       </a> |  | ||||||
|     `,
 |  | ||||||
|     type: "text", |  | ||||||
|     default: "CmdOrCtrl+Shift+Tab", |     default: "CmdOrCtrl+Shift+Tab", | ||||||
|     onBeforeChange: unregisterHotkey, |   }, | ||||||
|     onChange: registerHotkey, |   "Quick notes", | ||||||
|  |   { | ||||||
|  |     key: "quickNoteLocation", | ||||||
|  |     desc: "New quick notes will be placed in this folder.", | ||||||
|  |     type: "text", | ||||||
|  |     placeholder: "Example: notes/quick", | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     key: "quickNoteDateFormat", | ||||||
|  |     desc: "New quick notes will use a filename of this pattern.", | ||||||
|  |     type: "moment", | ||||||
|  |     default: DEFAULT_DATE_FORMAT, | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     key: "quickNoteHotkey", | ||||||
|  |     type: "hotkey", | ||||||
|  |     default: "CmdOrCtrl+Shift+Q", | ||||||
|   }, |   }, | ||||||
| ]; | ]; | ||||||
| 
 | 
 | ||||||
| @ -210,6 +249,18 @@ const keyToLabel = (key) => | |||||||
|       .createRange() |       .createRange() | ||||||
|       .createContextualFragment((html ?? "").replace(/\s+/g, " ")); |       .createContextualFragment((html ?? "").replace(/\s+/g, " ")); | ||||||
| 
 | 
 | ||||||
|  | const acceleratorFormat = ` | ||||||
|  |     This hotkey is registered globally and will be detected even if Obsidian does | ||||||
|  |     not have keyboard focus. Format: | ||||||
|  |     <a href="https://www.electronjs.org/docs/latest/api/accelerator" target="_blank" rel="noopener"> | ||||||
|  |     Electron accelerator</a> | ||||||
|  |   `,
 | ||||||
|  |   momentFormat = ` | ||||||
|  |     Format: | ||||||
|  |     <a href="https://momentjs.com/docs/#/displaying/format/" target="_blank" rel="noopener"> | ||||||
|  |     Moment.js format string</a> | ||||||
|  |     <br>Preview: | ||||||
|  |   `;
 | ||||||
| class SettingsTab extends obsidian.PluginSettingTab { | class SettingsTab extends obsidian.PluginSettingTab { | ||||||
|   constructor(app, plugin) { |   constructor(app, plugin) { | ||||||
|     super(app, plugin); |     super(app, plugin); | ||||||
| @ -218,32 +269,58 @@ class SettingsTab extends obsidian.PluginSettingTab { | |||||||
|   display() { |   display() { | ||||||
|     this.containerEl.empty(); |     this.containerEl.empty(); | ||||||
|     for (const opt of OPTIONS) { |     for (const opt of OPTIONS) { | ||||||
|       const name = keyToLabel(opt.key), |       const setting = new obsidian.Setting(this.containerEl); | ||||||
|         desc = htmlToFragment(opt.desc), |       if (typeof opt === "string") { | ||||||
|         onChange = async (value) => { |         setting.setName(opt); | ||||||
|  |         setting.setHeading(); | ||||||
|  |       } else { | ||||||
|  |         if (opt.default) { | ||||||
|  |           opt.placeholder ??= `Example: ${opt.default}`; | ||||||
|  |         } | ||||||
|  |         if (opt.type === "hotkey") { | ||||||
|  |           opt.desc ??= ""; | ||||||
|  |           opt.desc += acceleratorFormat; | ||||||
|  |           opt.onBeforeChange = unregisterHotkeys; | ||||||
|  |           opt.onChange = registerHotkeys; | ||||||
|  |         } | ||||||
|  |         if (opt.type === "moment") { | ||||||
|  |           opt.desc = `${opt.desc ? `${opt.desc}<br>` : ""}${momentFormat}`; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         setting.setName(keyToLabel(opt.key)); | ||||||
|  |         setting.setDesc(htmlToFragment(opt.desc)); | ||||||
|  |         const onChange = async (value) => { | ||||||
|           await opt.onBeforeChange?.(this.plugin); |           await opt.onBeforeChange?.(this.plugin); | ||||||
|           this.plugin.settings[opt.key] = value; |           this.plugin.settings[opt.key] = value; | ||||||
|           await this.plugin.saveSettings(); |           await this.plugin.saveSettings(); | ||||||
|           await opt.onChange?.(this.plugin); |           await opt.onChange?.(this.plugin); | ||||||
|         }; |         }; | ||||||
| 
 | 
 | ||||||
|       const setting = new obsidian.Setting(this.containerEl) |         if (opt.type === "toggle") { | ||||||
|         .setName(name) |           setting.addToggle((toggle) => { | ||||||
|         .setDesc(desc); |             toggle | ||||||
|       switch (opt.type) { |               .setValue(this.plugin.settings[opt.key] ?? opt.default) | ||||||
|         case "toggle": |               .onChange(onChange); | ||||||
|           setting.addToggle((toggle) => |           }); | ||||||
|             toggle.setValue(this.plugin.settings[opt.key]).onChange(onChange) |         } else if (opt.type === "moment") { | ||||||
|           ); |           setting.addMomentFormat((moment) => { | ||||||
|           break; |             const sampleEl = setting.descEl.createEl("b"); | ||||||
|         case "text": |             sampleEl.className = "u-pop"; | ||||||
|         default: |             moment | ||||||
|           setting.addText((text) => |               .setPlaceholder(opt.placeholder) | ||||||
|  |               .setDefaultFormat(opt.default ?? "") | ||||||
|  |               .setValue(this.plugin.settings[opt.key] ?? opt.default ?? "") | ||||||
|  |               .setSampleEl(sampleEl) | ||||||
|  |               .onChange(onChange); | ||||||
|  |           }); | ||||||
|  |         } else { | ||||||
|  |           setting.addText((text) => { | ||||||
|             text |             text | ||||||
|               .setPlaceholder(opt.default) |               .setPlaceholder(opt.placeholder) | ||||||
|               .setValue(this.plugin.settings[opt.key]) |               .setValue(this.plugin.settings[opt.key] ?? opt.default ?? "") | ||||||
|               .onChange(onChange) |               .onChange(onChange); | ||||||
|           ); |           }); | ||||||
|  |         } | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| @ -256,7 +333,7 @@ class TrayPlugin extends obsidian.Plugin { | |||||||
|     this.addSettingTab(new SettingsTab(this.app, this)); |     this.addSettingTab(new SettingsTab(this.app, this)); | ||||||
|     const { settings } = this; |     const { settings } = this; | ||||||
| 
 | 
 | ||||||
|     registerHotkey(this); |     registerHotkeys(this); | ||||||
|     setHideTaskbarIcon(this); |     setHideTaskbarIcon(this); | ||||||
|     setLaunchOnStartup(this); |     setLaunchOnStartup(this); | ||||||
|     if (settings.createTrayIcon) createTrayIcon(this); |     if (settings.createTrayIcon) createTrayIcon(this); | ||||||
| @ -273,7 +350,7 @@ class TrayPlugin extends obsidian.Plugin { | |||||||
|     } |     } | ||||||
|   } |   } | ||||||
|   onunload() { |   onunload() { | ||||||
|     unregisterHotkey(this); |     unregisterHotkeys(this); | ||||||
|     cleanupWindowClose(); |     cleanupWindowClose(); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user