experiments in a post-browser web
10
fork

Configure Feed

Select the types of activity you want to include in your feed.

move peeks and slides to extensions

+726 -12
+1 -1
app/cmd/config.js
··· 33 33 34 34 const defaults = { 35 35 prefs: { 36 - shortcutKey: 'Control+Space' 36 + shortcutKey: 'Option+Space' 37 37 }, 38 38 }; 39 39
+4 -2
app/config.js
··· 138 138 { id: 'ef3bd271-d408-421f-9338-47b615571e43', 139 139 name: 'Peeks', 140 140 description: 'Peek at pages in a transient popup using keyboard shortcuts', 141 - start_url: 'peek://app/peeks/background.html', 141 + start_url: 'peek://ext/peeks/background.js', // Extension 142 142 enabled: false, 143 143 settings_url: 'peek://app/peeks/settings.html', 144 + extension: true, // Mark as extension-based feature 144 145 }, 145 146 { id: '30c25027-d367-4595-b37f-9db3de853c37', 146 147 name: 'Scripts', ··· 152 153 { id: '434108f3-18a6-437a-b507-2f998f693bb2', 153 154 name: 'Slides', 154 155 description: 'Open web pages as side/top/bottom bars', 155 - start_url: 'peek://app/slides/background.html', 156 + start_url: 'peek://ext/slides/background.js', // Extension 156 157 enabled: false, 157 158 settings_url: 'peek://app/slides/settings.html', 159 + extension: true, // Mark as extension-based feature 158 160 } 159 161 ] 160 162 };
+10 -2
app/extensions/loader.js
··· 20 20 id: 'groups', 21 21 path: 'peek://ext/groups', 22 22 backgroundScript: 'background.js' 23 + }, 24 + { 25 + id: 'peeks', 26 + path: 'peek://ext/peeks', 27 + backgroundScript: 'background.js' 28 + }, 29 + { 30 + id: 'slides', 31 + path: 'peek://ext/slides', 32 + backgroundScript: 'background.js' 23 33 } 24 - // Future: { id: 'peeks', path: 'peek://ext/peeks', backgroundScript: 'background.js' } 25 - // Future: { id: 'slides', path: 'peek://ext/slides', backgroundScript: 'background.js' } 26 34 ]; 27 35 28 36 /**
+129
extensions/peeks/background.js
··· 1 + /** 2 + * Peeks Extension Background Script 3 + * 4 + * Quick access modal windows for web pages via keyboard shortcuts (Option+0-9) 5 + */ 6 + 7 + import { id, labels, schemas, storageKeys, defaults } from './config.js'; 8 + import { openStore } from 'peek://app/utils.js'; 9 + import windows from 'peek://app/windows.js'; 10 + 11 + const api = window.app; 12 + const debug = api.debug; 13 + 14 + console.log('[ext:peeks] background', labels.name); 15 + 16 + const clear = false; 17 + const store = openStore(id, defaults, clear /* clear storage */); 18 + 19 + // Track registered shortcuts for cleanup 20 + let registeredShortcuts = []; 21 + 22 + const executeItem = (item) => { 23 + console.log('[ext:peeks] executeItem', item); 24 + const height = item.height || 600; 25 + const width = item.width || 800; 26 + 27 + const params = { 28 + // browserwindow 29 + height, 30 + width, 31 + 32 + // peek 33 + feature: labels.name, 34 + keepLive: item.keepLive || false, 35 + persistState: item.persistState || false, 36 + 37 + // Create a unique key for this peek using its address 38 + key: `peek:${item.address}`, 39 + 40 + // tracking (handled automatically by windows API) 41 + trackingSource: 'peek', 42 + trackingSourceId: item.keyNum ? `peek_${item.keyNum}` : 'peek', 43 + title: item.title || '' 44 + }; 45 + 46 + windows.openModalWindow(item.address, params) 47 + .then(result => { 48 + console.log('[ext:peeks] Peek window opened:', result); 49 + }) 50 + .catch(error => { 51 + console.error('[ext:peeks] Failed to open peek window:', error); 52 + }); 53 + }; 54 + 55 + const initItems = (prefs, items) => { 56 + const cmdPrefix = prefs.shortcutKeyPrefix; 57 + 58 + items.forEach(item => { 59 + if (item.enabled == true && item.address.length > 0) { 60 + const shortcut = `${cmdPrefix}${item.keyNum}`; 61 + 62 + api.shortcuts.register(shortcut, () => { 63 + executeItem(item); 64 + }, { global: true }); 65 + 66 + registeredShortcuts.push(shortcut); 67 + } 68 + }); 69 + }; 70 + 71 + /** 72 + * Unregister all shortcuts and clean up 73 + */ 74 + const uninit = () => { 75 + console.log('[ext:peeks] uninit - unregistering', registeredShortcuts.length, 'shortcuts'); 76 + 77 + registeredShortcuts.forEach(shortcut => { 78 + api.shortcuts.unregister(shortcut, { global: true }); 79 + }); 80 + 81 + registeredShortcuts = []; 82 + }; 83 + 84 + /** 85 + * Reinitialize peeks (called when settings change) 86 + * 87 + * TODO: This is inefficient - reinitializes all peeks when any single 88 + * property changes. A better approach would be to diff the old and new 89 + * settings and only update the shortcuts that actually changed. 90 + */ 91 + const reinit = () => { 92 + console.log('[ext:peeks] reinit'); 93 + uninit(); 94 + 95 + const prefs = store.get(storageKeys.PREFS); 96 + const items = store.get(storageKeys.ITEMS); 97 + 98 + if (items && items.length > 0) { 99 + initItems(prefs, items); 100 + } 101 + }; 102 + 103 + const init = () => { 104 + console.log('[ext:peeks] init'); 105 + 106 + const prefs = () => store.get(storageKeys.PREFS); 107 + const items = () => store.get(storageKeys.ITEMS); 108 + 109 + // Initialize peeks 110 + if (items().length > 0) { 111 + initItems(prefs(), items()); 112 + } 113 + 114 + // Listen for settings changes to hot-reload 115 + api.subscribe('peeks:settings-changed', () => { 116 + console.log('[ext:peeks] settings changed, reinitializing'); 117 + reinit(); 118 + }); 119 + }; 120 + 121 + export default { 122 + defaults, 123 + id, 124 + init, 125 + uninit, 126 + labels, 127 + schemas, 128 + storageKeys 129 + };
+131
extensions/peeks/config.js
··· 1 + const id = 'ef3bd271-d408-421f-9338-47b615571e43'; 2 + 3 + const labels = { 4 + name: 'Peeks', 5 + prefs: { 6 + keyPrefix: 'Peek shortcut prefix', 7 + } 8 + }; 9 + 10 + const prefsSchema = { 11 + "$schema": "https://json-schema.org/draft/2020-12/schema", 12 + "$id": "peek.peeks.prefs.schema.json", 13 + "title": "Peeks preferences", 14 + "description": "Peeks user preferences", 15 + "type": "object", 16 + "properties": { 17 + "shortcutKeyPrefix": { 18 + "description": "Global OS hotkey prefix to trigger peeks - will be followed by 0-9", 19 + "type": "string", 20 + "default": "Option+" 21 + }, 22 + }, 23 + "required": [ "shortcutKeyPrefix"] 24 + }; 25 + 26 + const itemSchema = { 27 + "$schema": "https://json-schema.org/draft/2020-12/schema", 28 + "$id": "peek.peeks.peek.schema.json", 29 + "title": "Peek - page peek", 30 + "description": "Peek page peek", 31 + "type": "object", 32 + "properties": { 33 + "keyNum": { 34 + "description": "Number on keyboard to open this peek, 0-9", 35 + "type": "integer", 36 + "minimum": 0, 37 + "maximum": 9, 38 + "default": 0 39 + }, 40 + "title": { 41 + "description": "Name of the peek - user defined label", 42 + "type": "string", 43 + "default": "New Peek" 44 + }, 45 + "address": { 46 + "description": "URL to load", 47 + "type": "string", 48 + "default": "https://example.com" 49 + }, 50 + "persistState": { 51 + "description": "Whether to persist local state or load page into empty container - defaults to false", 52 + "type": "boolean", 53 + "default": false 54 + }, 55 + "keepLive": { 56 + "description": "Whether to keep page alive in background or load fresh when triggered - defaults to false", 57 + "type": "boolean", 58 + "default": false 59 + }, 60 + "allowSound": { 61 + "description": "Whether to allow the page to emit sound or not (eg for background music player peeks - defaults to false", 62 + "type": "boolean", 63 + "default": false 64 + }, 65 + "height": { 66 + "description": "User-defined height of peek page", 67 + "type": "integer", 68 + "default": 600 69 + }, 70 + "width": { 71 + "description": "User-defined width of peek page", 72 + "type": "integer", 73 + "default": 800 74 + }, 75 + "enabled": { 76 + "description": "Whether this peek is enabled or not.", 77 + "type": "boolean", 78 + "default": false 79 + }, 80 + }, 81 + "required": [ "keyNum", "title", "address", "persistState", "keepLive", "allowSound", 82 + "height", "width", "enabled" ] 83 + }; 84 + 85 + const listSchema = { 86 + type: 'array', 87 + items: { "$ref": "#/$defs/peek" } 88 + }; 89 + 90 + // TODO: schemaize 0-9 constraints for peeks 91 + const schemas = { 92 + prefs: prefsSchema, 93 + item: itemSchema, 94 + items: listSchema 95 + }; 96 + 97 + const storageKeys = { 98 + PREFS: 'prefs', 99 + ITEMS: 'items', 100 + }; 101 + 102 + const defaults = { 103 + prefs: { 104 + shortcutKeyPrefix: 'Option+' 105 + }, 106 + items: Array.from(Array(10)), 107 + }; 108 + 109 + for (var i = 0; i != 10; i++) { 110 + const address = i == 0 ? 'https://example.com/' : ''; 111 + const enabled = i == 0 ? true : false; 112 + defaults.items[i] = { 113 + keyNum: i, 114 + title: `Peek key ${i}`, 115 + address: address, 116 + persistState: false, 117 + keepLive: false, 118 + allowSound: false, 119 + height: 600, 120 + width: 800, 121 + enabled: enabled, 122 + }; 123 + } 124 + 125 + export { 126 + id, 127 + labels, 128 + schemas, 129 + storageKeys, 130 + defaults 131 + };
+8
extensions/peeks/manifest.json
··· 1 + { 2 + "id": "peeks", 3 + "name": "Peeks", 4 + "description": "Quick access modal windows for web pages via keyboard shortcuts", 5 + "version": "1.0.0", 6 + "background": "background.js", 7 + "builtin": true 8 + }
+266
extensions/slides/background.js
··· 1 + /** 2 + * Slides Extension Background Script 3 + * 4 + * Edge-anchored slide-in panels triggered by keyboard shortcuts (Option+Arrow) 5 + */ 6 + 7 + import { id, labels, schemas, storageKeys, defaults } from './config.js'; 8 + import { openStore } from 'peek://app/utils.js'; 9 + import windows from 'peek://app/windows.js'; 10 + 11 + const api = window.app; 12 + const debug = api.debug; 13 + 14 + console.log('[ext:slides] background', labels.name); 15 + 16 + const clear = false; 17 + const store = openStore(id, defaults, clear /* clear storage */); 18 + 19 + // Map to track opened slides - key is slide key, value is window ID 20 + const slideWindows = new Map(); 21 + 22 + // Track registered shortcuts for cleanup 23 + let registeredShortcuts = []; 24 + 25 + const executeItem = (item) => { 26 + const height = item.height || 600; 27 + const width = item.width || 800; 28 + 29 + const screen = { 30 + height: window.screen.height, 31 + width: window.screen.width 32 + }; 33 + 34 + let x, y, center = null; 35 + 36 + switch(item.screenEdge) { 37 + case 'Up': 38 + // horizontally center 39 + x = (screen.width - width) / 2; 40 + 41 + // y starts at screen top and stays there 42 + y = 0; 43 + 44 + //width = item.width; 45 + //height = 1; 46 + break; 47 + case 'Down': 48 + // horizonally center 49 + x = (screen.width - item.width) / 2; 50 + 51 + // y ends up at window height from bottom 52 + // 53 + // eg: y = screen.height - item.height; 54 + // 55 + // but starts at screen bottom 56 + y = screen.height; 57 + 58 + //width = item.width; 59 + //height = 1; 60 + break; 61 + case 'Left': 62 + // x starts and ends at at left screen edge 63 + // at left edge 64 + x = 0; 65 + 66 + // vertically center 67 + y = (screen.height - item.height) / 2; 68 + 69 + //width = 1; 70 + //height = item.height; 71 + break; 72 + case 'Right': 73 + // x ends at at right screen edge - window size 74 + // 75 + // eg: x = screen.width - item.width; 76 + // 77 + // but starts at screen right edge, will animate in 78 + x = screen.width; 79 + 80 + // vertically center 81 + y = (screen.height - item.height) / 2; 82 + 83 + //width = 1; 84 + //height = item.height; 85 + break; 86 + default: 87 + center = true; 88 + console.log('[ext:slides] unknown screen edge'); 89 + } 90 + 91 + console.log('[ext:slides] execute slide', item.screenEdge, x, y); 92 + 93 + const key = `${item.address}:${item.screenEdge}`; 94 + 95 + // Check if this slide is already open 96 + if (slideWindows.has(key)) { 97 + // Get the window ID for the existing slide 98 + const windowId = slideWindows.get(key); 99 + console.log('[ext:slides] Slide already open, verifying window exists with ID:', windowId); 100 + 101 + // First check if window exists 102 + api.window.exists({ id: windowId }).then(existsResult => { 103 + if (existsResult.exists) { 104 + // Window exists, try to show it 105 + api.window.show({ id: windowId }).then(result => { 106 + if (result.success) { 107 + console.log('[ext:slides] Successfully showed existing slide:', key); 108 + } else { 109 + console.error('[ext:slides] Failed to show existing slide:', result.error); 110 + slideWindows.delete(key); 111 + openNewSlide(); 112 + } 113 + }).catch(err => { 114 + console.error('[ext:slides] Error showing window:', err); 115 + slideWindows.delete(key); 116 + openNewSlide(); 117 + }); 118 + } else { 119 + console.log('[ext:slides] Window no longer exists, creating new one'); 120 + slideWindows.delete(key); 121 + openNewSlide(); 122 + } 123 + }).catch(err => { 124 + console.error('[ext:slides] Error checking if window exists:', err); 125 + slideWindows.delete(key); 126 + openNewSlide(); 127 + }); 128 + } else { 129 + openNewSlide(); 130 + } 131 + 132 + function openNewSlide() { 133 + const params = { 134 + address: item.address, 135 + height, 136 + width, 137 + key, 138 + 139 + feature: labels.name, 140 + keepLive: item.keepLive || false, 141 + persistState: item.persistState || false, 142 + 143 + x, 144 + y, 145 + 146 + // tracking (handled automatically by windows API) 147 + trackingSource: 'slide', 148 + trackingSourceId: item.screenEdge ? `slide_${item.screenEdge}` : 'slide', 149 + title: item.title || '' 150 + }; 151 + 152 + // Open the window 153 + windows.openModalWindow(item.address, params).then(result => { 154 + if (result.success) { 155 + console.log('[ext:slides] Successfully opened slide with ID:', result.id); 156 + // Store the window ID for future reference 157 + slideWindows.set(key, result.id); 158 + } else { 159 + console.error('[ext:slides] Failed to open slide:', result.error); 160 + } 161 + }); 162 + } 163 + 164 + }; 165 + 166 + const initItems = (prefs, items) => { 167 + const cmdPrefix = prefs.shortcutKeyPrefix; 168 + 169 + items.forEach(item => { 170 + if (item.enabled == true && item.address.length > 0) { 171 + const shortcut = `${cmdPrefix}${item.screenEdge}`; 172 + 173 + api.shortcuts.register(shortcut, () => { 174 + executeItem(item); 175 + }, { global: true }); 176 + 177 + registeredShortcuts.push(shortcut); 178 + } 179 + }); 180 + }; 181 + 182 + /** 183 + * Unregister all shortcuts and clean up windows 184 + */ 185 + const uninit = () => { 186 + console.log('[ext:slides] uninit - unregistering', registeredShortcuts.length, 'shortcuts'); 187 + 188 + // Unregister all shortcuts 189 + registeredShortcuts.forEach(shortcut => { 190 + api.shortcuts.unregister(shortcut, { global: true }); 191 + }); 192 + registeredShortcuts = []; 193 + 194 + // Close or hide all slide windows 195 + for (const [key, windowId] of slideWindows.entries()) { 196 + console.log('[ext:slides] Closing slide window:', key); 197 + api.window.hide({ id: windowId }).catch(err => { 198 + console.error('[ext:slides] Error hiding slide window:', err); 199 + api.window.close({ id: windowId }).catch(err => { 200 + console.error('[ext:slides] Error closing slide window:', err); 201 + }); 202 + }); 203 + } 204 + slideWindows.clear(); 205 + }; 206 + 207 + /** 208 + * Reinitialize slides (called when settings change) 209 + * 210 + * TODO: This is inefficient - reinitializes all slides when any single 211 + * property changes. A better approach would be to diff the old and new 212 + * settings and only update the shortcuts that actually changed. 213 + */ 214 + const reinit = () => { 215 + console.log('[ext:slides] reinit'); 216 + uninit(); 217 + 218 + const prefs = store.get(storageKeys.PREFS); 219 + const items = store.get(storageKeys.ITEMS); 220 + 221 + if (items && items.length > 0) { 222 + initItems(prefs, items); 223 + } 224 + }; 225 + 226 + const init = () => { 227 + console.log('[ext:slides] init'); 228 + 229 + const prefs = () => store.get(storageKeys.PREFS); 230 + const items = () => store.get(storageKeys.ITEMS); 231 + 232 + // Add global window closed handler 233 + api.subscribe('window:closed', (data) => { 234 + // Check all slide windows to see if any match the closed window ID 235 + for (const [key, windowId] of slideWindows.entries()) { 236 + if (data.id === windowId) { 237 + console.log('[ext:slides] Slide window was closed externally:', key); 238 + slideWindows.delete(key); 239 + } 240 + } 241 + }); 242 + 243 + // Initialize slides 244 + if (items().length > 0) { 245 + initItems(prefs(), items()); 246 + } 247 + 248 + // Listen for settings changes to hot-reload 249 + api.subscribe('slides:settings-changed', () => { 250 + console.log('[ext:slides] settings changed, reinitializing'); 251 + reinit(); 252 + }); 253 + 254 + // Set up listener for app shutdown to clean up windows 255 + api.subscribe('app:shutdown', uninit); 256 + }; 257 + 258 + export default { 259 + defaults, 260 + id, 261 + init, 262 + uninit, 263 + labels, 264 + schemas, 265 + storageKeys 266 + };
+163
extensions/slides/config.js
··· 1 + const id = '434108f3-18a6-437a-b507-2f998f693bb2'; 2 + 3 + const labels = { 4 + name: 'Slides', 5 + prefs: { 6 + keyPrefix: 'Slide shortcut prefix', 7 + } 8 + }; 9 + 10 + const prefsSchema = { 11 + "$schema": "https://json-schema.org/draft/2020-12/schema", 12 + "$id": "peek.slides.prefs.schema.json", 13 + "title": "Slides prefs", 14 + "description": "Peek app Slides user preferences", 15 + "type": "object", 16 + "properties": { 17 + "shortcutKeyPrefix": { 18 + "description": "Global OS hotkey prefix to trigger slides - will be followed by up/down/left/right arrows", 19 + "type": "string", 20 + "default": "Option+" 21 + }, 22 + }, 23 + "required": [ "shortcutKeyPrefix"] 24 + }; 25 + 26 + const itemSchema = { 27 + "$schema": "https://json-schema.org/draft/2020-12/schema", 28 + "$id": "peek.slides.slide.schema.json", 29 + "title": "Peek - page slide", 30 + "description": "Peek page slide", 31 + "type": "object", 32 + "properties": { 33 + "screenEdge": { 34 + "description": "Edge of screen or arrow key to open this slide, up/down/left/right", 35 + "type": "string", 36 + "oneOf": [ 37 + { "format": "Up" }, 38 + { "format": "Down" }, 39 + { "format": "Left" }, 40 + { "format": "Right" } 41 + ], 42 + "default": "Right" 43 + }, 44 + "title": { 45 + "description": "Name of the slide - user defined label", 46 + "type": "string", 47 + "default": "New Slide" 48 + }, 49 + "address": { 50 + "description": "URL to load", 51 + "type": "string", 52 + "default": "https://example.com" 53 + }, 54 + "persistState": { 55 + "description": "Whether to persist local state or load page into empty container - defaults to false", 56 + "type": "boolean", 57 + "default": false 58 + }, 59 + "keepLive": { 60 + "description": "Whether to keep page alive in background or load fresh when triggered - defaults to false", 61 + "type": "boolean", 62 + "default": false 63 + }, 64 + "allowSound": { 65 + "description": "Whether to allow the page to emit sound or not (eg for background music player slides - defaults to false", 66 + "type": "boolean", 67 + "default": false 68 + }, 69 + "height": { 70 + "description": "User-defined height of slide page", 71 + "type": "integer", 72 + "default": 600 73 + }, 74 + "width": { 75 + "description": "User-defined width of slide page", 76 + "type": "integer", 77 + "default": 800 78 + }, 79 + "enabled": { 80 + "description": "Whether this slide is enabled or not.", 81 + "type": "boolean", 82 + "default": false 83 + }, 84 + }, 85 + "required": [ "screenEdge", "title", "address", "persistState", "keepLive", "allowSound", 86 + "height", "width", "enabled" ] 87 + }; 88 + 89 + const listSchema = { 90 + type: 'array', 91 + items: { "$ref": "#/$defs/slide" } 92 + }; 93 + 94 + const schemas = { 95 + prefs: prefsSchema, 96 + item: itemSchema, 97 + items: listSchema 98 + }; 99 + 100 + const storageKeys = { 101 + PREFS: 'prefs', 102 + ITEMS: 'items', 103 + }; 104 + 105 + const defaults = { 106 + prefs: { 107 + shortcutKeyPrefix: 'Option+' 108 + }, 109 + items: [ 110 + { 111 + screenEdge: 'Up', 112 + title: 'Slide from top', 113 + address: 'http://localhost/', 114 + persistState: false, 115 + keepLive: false, 116 + allowSound: false, 117 + height: 600, 118 + width: 800, 119 + enabled: true, 120 + }, 121 + { 122 + screenEdge: 'Down', 123 + title: 'Slide from bottom', 124 + address: '', 125 + persistState: false, 126 + keepLive: false, 127 + allowSound: false, 128 + height: 600, 129 + width: 800, 130 + enabled: false, 131 + }, 132 + { 133 + screenEdge: 'Left', 134 + title: 'Slide from left', 135 + address: '', 136 + persistState: false, 137 + keepLive: false, 138 + allowSound: false, 139 + height: 600, 140 + width: 800, 141 + enabled: false, 142 + }, 143 + { 144 + screenEdge: 'Right', 145 + title: 'Slide from right', 146 + address: '', 147 + persistState: false, 148 + keepLive: false, 149 + allowSound: false, 150 + height: 600, 151 + width: 800, 152 + enabled: false, 153 + }, 154 + ] 155 + }; 156 + 157 + export { 158 + id, 159 + labels, 160 + schemas, 161 + storageKeys, 162 + defaults 163 + };
+8
extensions/slides/manifest.json
··· 1 + { 2 + "id": "slides", 3 + "name": "Slides", 4 + "description": "Edge-anchored slide-in panels triggered by keyboard shortcuts", 5 + "version": "1.0.0", 6 + "background": "background.js", 7 + "builtin": true 8 + }
+6 -7
index.js
··· 587 587 // Register built-in extensions 588 588 // Built-in extensions live in ./extensions/ at the project root 589 589 registerExtensionPath('groups', path.join(__dirname, 'extensions', 'groups')); 590 - // Future: registerExtensionPath('peeks', path.join(__dirname, 'extensions', 'peeks')); 591 - // Future: registerExtensionPath('slides', path.join(__dirname, 'extensions', 'slides')); 590 + registerExtensionPath('peeks', path.join(__dirname, 'extensions', 'peeks')); 591 + registerExtensionPath('slides', path.join(__dirname, 'extensions', 'slides')); 592 592 593 593 // Register as default handler for http/https URLs (if not already and user hasn't declined) 594 594 const defaultBrowserPrefFile = path.join(profileDataPath, 'default-browser-pref.json'); ··· 1876 1876 // ***** Helpers ***** 1877 1877 1878 1878 const registerShortcut = (shortcut, callback) => { 1879 - console.log('registerShortcut', shortcut) 1879 + console.log('registerShortcut', shortcut); 1880 1880 1881 1881 if (globalShortcut.isRegistered(shortcut)) { 1882 1882 console.error(strings.shortcuts.errorAlreadyRegistered, shortcut); 1883 1883 globalShortcut.unregister(shortcut); 1884 - return new Error(strings.shortcuts.errorAlreadyRegisterd); 1885 1884 } 1886 1885 1887 1886 const ret = globalShortcut.register(shortcut, () => { ··· 1889 1888 callback(); 1890 1889 }); 1891 1890 1892 - if (ret != true) { 1893 - console.error('Unable to register shortcut', shortcut); 1891 + if (ret !== true) { 1892 + console.error('registerShortcut FAILED:', shortcut); 1894 1893 return new Error(strings.shortcuts.errorRegistrationFailed); 1895 1894 } 1896 1895 }; ··· 1900 1899 1901 1900 if (!globalShortcut.isRegistered(shortcut)) { 1902 1901 console.error('Unable to unregister shortcut because not registered or it is not us', shortcut); 1903 - return new Error("Failed in some way", { cause: err }); 1902 + return new Error("Shortcut not registered: " + shortcut); 1904 1903 } 1905 1904 1906 1905 globalShortcut.unregister(shortcut, () => {