diff --git a/DOCUMENTATION.md b/DOCUMENTATION.md index 38d04d4..9a55d14 100644 --- a/DOCUMENTATION.md +++ b/DOCUMENTATION.md @@ -41,12 +41,12 @@ module.exports = { desc: String of markdown, version: String of semver, author: String of github_username, - options?: { + options?: Array<{ key: String, label: String, type: String in ['toggle', 'select', 'input', 'file'], value: Boolean or Array or String or null - }, + }>, hacks?: { [k: 'insert-point' (e.g. 'main/createWindow.js')]: function (store) {} } @@ -87,7 +87,7 @@ each "hack" is a function taking 2 arguments. 1. the **`store`** argument, which allows access to the module settings/options defined in `mod.js` (those set in the menu, or used internally by the module). each module store is automatically saved to + loaded from `~/.notion-enhancer/id.json`. - it can be initialised with `const settings = store({ defaults })`, then used as if it were a normal object. + it can be initialised/accessed with `store({ defaults })`, then used as if it were a normal object. 2. the **`__exports`** argument, which is the `module.exports` of the file being modded. this can be used to call or replace functions from notion. @@ -109,8 +109,7 @@ e.g. module.exports = function (store, __exports) { document.addEventListener('readystatechange', (event) => { if (document.readyState !== 'complete') return false; - const settings = store({ name: 'dragonwocky' }); - console.log(settings.name); + console.log(store({ name: 'dragonwocky' }).name); }); }; // mod.js diff --git a/mods/core/buttons.js b/mods/core/buttons.js index c1c57d2..1dcf728 100644 --- a/mods/core/buttons.js +++ b/mods/core/buttons.js @@ -6,93 +6,96 @@ 'use strict'; -const __mod = require('./mod.js'), - store = require('../../pkg/store.js'), - settings = store(__mod.id, __mod.defaults), - path = require('path'), - fs = require('fs-extra'), - browser = require('electron').remote.getCurrentWindow(), - is_mac = process.platform === 'darwin', - buttons = { - element: document.createElement('div'), - insert: [ - 'alwaysontop', - ...(settings.frameless && !is_mac - ? ['minimize', 'maximize', 'close'] - : []), - ], - icons: { - raw: { - alwaysontop: { - on: fs.readFile( - path.resolve(`${__dirname}/icons/alwaysontop_on.svg`) - ), - off: fs.readFile( - path.resolve(`${__dirname}/icons/alwaysontop_off.svg`) +module.exports = (store) => { + const path = require('path'), + fs = require('fs-extra'), + browser = require('electron').remote.getCurrentWindow(), + is_mac = process.platform === 'darwin', + buttons = { + element: document.createElement('div'), + insert: [ + 'alwaysontop', + ...(store().frameless && !is_mac + ? ['minimize', 'maximize', 'close'] + : []), + ], + icons: { + raw: { + alwaysontop: { + on: fs.readFile( + path.resolve(`${__dirname}/icons/alwaysontop_on.svg`) + ), + off: fs.readFile( + path.resolve(`${__dirname}/icons/alwaysontop_off.svg`) + ), + }, + minimize: fs.readFile( + path.resolve(`${__dirname}/icons/minimize.svg`) ), + maximize: { + on: fs.readFile(path.resolve(`${__dirname}/icons/maximize_on.svg`)), + off: fs.readFile( + path.resolve(`${__dirname}/icons/maximize_off.svg`) + ), + }, + close: fs.readFile(path.resolve(`${__dirname}/icons/close.svg`)), }, - minimize: fs.readFile(path.resolve(`${__dirname}/icons/minimize.svg`)), - maximize: { - on: fs.readFile(path.resolve(`${__dirname}/icons/maximize_on.svg`)), - off: fs.readFile(path.resolve(`${__dirname}/icons/maximize_off.svg`)), + alwaysontop() { + return browser.isAlwaysOnTop() + ? buttons.icons.raw.alwaysontop.on + : buttons.icons.raw.alwaysontop.off; // '🠙' : '🠛' + }, + minimize() { + return buttons.icons.raw.minimize; // '⚊' + }, + maximize() { + return browser.isMaximized() + ? buttons.icons.raw.maximize.on + : buttons.icons.raw.maximize.off; // '🗗' : '🗖' + }, + close() { + return buttons.icons.raw.close; // '⨉' }, - close: fs.readFile(path.resolve(`${__dirname}/icons/close.svg`)), }, - alwaysontop() { - return browser.isAlwaysOnTop() - ? buttons.icons.raw.alwaysontop.on - : buttons.icons.raw.alwaysontop.off; // '🠙' : '🠛' + actions: { + async alwaysontop() { + browser.setAlwaysOnTop(!browser.isAlwaysOnTop()); + this.innerHTML = await buttons.icons.alwaysontop(); + }, + minimize() { + browser.minimize(); + }, + async maximize() { + browser.isMaximized() ? browser.unmaximize() : browser.maximize(); + this.innerHTML = await buttons.icons.maximize(); + }, + close() { + browser.close(); + }, }, - minimize() { - return buttons.icons.raw.minimize; // '⚊' - }, - maximize() { - return browser.isMaximized() - ? buttons.icons.raw.maximize.on - : buttons.icons.raw.maximize.off; // '🗗' : '🗖' - }, - close() { - return buttons.icons.raw.close; // '⨉' - }, - }, - actions: { - async alwaysontop() { - browser.setAlwaysOnTop(!browser.isAlwaysOnTop()); - this.innerHTML = await buttons.icons.alwaysontop(); - }, - minimize() { - browser.minimize(); - }, - async maximize() { - browser.isMaximized() ? browser.unmaximize() : browser.maximize(); - this.innerHTML = await buttons.icons.maximize(); - }, - close() { - browser.close(); - }, - }, - }; + }; -(async () => { - buttons.element.className = 'window-buttons-area'; - for (let btn of buttons.insert) { - buttons.element.innerHTML += ``; - setTimeout( - () => - (document.querySelector(`.window-button#btn-${btn}`).onclick = - buttons.actions[btn]), - 10 - ); - } - if (settings.frameless && !is_mac) { - setInterval(async () => { - const icon = (await buttons.icons.maximize()).toString(), - el = buttons.element.querySelector('#btn-maximize'); - if (el.innerHTML != icon) el.innerHTML = icon; - }, 100); - } -})(); + (async () => { + buttons.element.className = 'window-buttons-area'; + for (let btn of buttons.insert) { + buttons.element.innerHTML += ``; + setTimeout( + () => + (document.querySelector(`.window-button#btn-${btn}`).onclick = + buttons.actions[btn]), + 10 + ); + } + if (store().frameless && !is_mac) { + setInterval(async () => { + const icon = (await buttons.icons.maximize()).toString(), + el = buttons.element.querySelector('#btn-maximize'); + if (el.innerHTML != icon) el.innerHTML = icon; + }, 100); + } + })(); -module.exports = buttons; + return buttons; +}; diff --git a/mods/core/client.js b/mods/core/client.js index 1c535e9..85b3cfe 100644 --- a/mods/core/client.js +++ b/mods/core/client.js @@ -7,125 +7,123 @@ 'use strict'; -module.exports = (defaults) => - function (store, __exports) { - const electron = require('electron'), - settings = store(defaults), - helpers = require('../../pkg/helpers.js'), - __notion = helpers.getNotion(), - notionIpc = require(`${__notion.replace( - /\\/g, - '/' - )}/app/helpers/notionIpc.js`); +module.exports = (store, __exports) => { + const electron = require('electron'), + helpers = require('../../pkg/helpers.js'), + __notion = helpers.getNotion(), + notionIpc = require(`${__notion.replace( + /\\/g, + '/' + )}/app/helpers/notionIpc.js`); - // additional hotkeys - document.defaultView.addEventListener('keyup', (event) => { - if (event.code === 'F5') window.reload(); - if (event.key === 'e' && (event.ctrlKey || event.metaKey)) - electron.ipcRenderer.send('enhancer:open-extension-menu'); - }); + // additional hotkeys + document.defaultView.addEventListener('keyup', (event) => { + if (event.code === 'F5') window.reload(); + if (event.key === 'e' && (event.ctrlKey || event.metaKey)) + electron.ipcRenderer.send('enhancer:open-extension-menu'); + }); - const attempt_interval = setInterval(enhance, 500); - async function enhance() { - if (!document.querySelector('.notion-frame')) return; - clearInterval(attempt_interval); + const attempt_interval = setInterval(enhance, 500); + async function enhance() { + if (!document.querySelector('.notion-frame')) return; + clearInterval(attempt_interval); - // scrollbars - if (settings.smooth_scrollbars) { - document.body.classList.add('smooth-scrollbars'); - // interval_attempts.patchScrollbars = setInterval(patchScrollbars, 100); - // function patchScrollbars() { - // const sidebar = document.querySelector( - // '.notion-scroller.vertical[style*="overflow: hidden auto;"]' - // ); - // if (!sidebar) return; - // clearInterval(interval_attempts.patchScrollbars); - // sidebar.style.overflow = ''; - // setTimeout(() => { - // sidebar.style.overflow = 'hidden auto'; - // }, 10); - // } - } + // scrollbars + if (store().smooth_scrollbars) { + document.body.classList.add('smooth-scrollbars'); + // interval_attempts.patchScrollbars = setInterval(patchScrollbars, 100); + // function patchScrollbars() { + // const sidebar = document.querySelector( + // '.notion-scroller.vertical[style*="overflow: hidden auto;"]' + // ); + // if (!sidebar) return; + // clearInterval(interval_attempts.patchScrollbars); + // sidebar.style.overflow = ''; + // setTimeout(() => { + // sidebar.style.overflow = 'hidden auto'; + // }, 10); + // } + } - // frameless - if (settings.frameless) { - document.body.classList.add('frameless'); - // draggable area - const dragarea = document.createElement('div'); - dragarea.className = 'window-dragarea'; - document.querySelector('.notion-topbar').prepend(dragarea); - document.documentElement.style.setProperty( - '--configured-dragarea_height', - `${settings.dragarea_height + 2}px` - ); - } + // frameless + if (store().frameless) { + document.body.classList.add('frameless'); + // draggable area + const dragarea = document.createElement('div'); + dragarea.className = 'window-dragarea'; + document.querySelector('.notion-topbar').prepend(dragarea); + document.documentElement.style.setProperty( + '--configured-dragarea_height', + `${store().dragarea_height + 2}px` + ); + } - // window buttons - const buttons = require('./buttons.js'); - document - .querySelector('.notion-topbar > div[style*="display: flex"]') - .appendChild(buttons.element); - document - .querySelector('.notion-history-back-button') - .parentElement.nextElementSibling.classList.add( - 'notion-topbar-breadcrumb' - ); - document - .querySelector('.notion-topbar-share-menu') - .parentElement.classList.add('notion-topbar-actions'); + // window buttons + const buttons = require('./buttons.js')(store); + document + .querySelector('.notion-topbar > div[style*="display: flex"]') + .appendChild(buttons.element); + document + .querySelector('.notion-history-back-button') + .parentElement.nextElementSibling.classList.add( + 'notion-topbar-breadcrumb' + ); + document + .querySelector('.notion-topbar-share-menu') + .parentElement.classList.add('notion-topbar-actions'); - let sidebar_width; - function communicationLoop() { - const getStyle = (prop) => - getComputedStyle(document.body).getPropertyValue(prop), - mode = JSON.parse(localStorage.theme).mode; + let sidebar_width; + function communicationLoop() { + const getStyle = (prop) => + getComputedStyle(document.body).getPropertyValue(prop), + mode = JSON.parse(localStorage.theme).mode; - // ctrl+f theming - notionIpc.sendNotionToIndex('search:set-theme', { - 'mode': mode, - 'colors': { - 'white': getStyle(`--theme_${mode}--todo_ticked-fill`), - 'blue': getStyle(`--theme_${mode}--primary`), - }, - 'borderRadius': 3, - 'textColor': getStyle(`--theme_${mode}--text`), - 'popoverBackgroundColor': getStyle(`--theme_${mode}--card`), - 'popoverBoxShadow': `0 0 0 1px ${getStyle( - `--theme_${mode}--overlay` - )}, 0 3px 6px ${getStyle(`--theme_${mode}--overlay`)}`, - 'inputBoxShadow': `box-shadow: ${getStyle( - `--theme_${mode}--primary` - )} 0px 0px 0px 1px inset, ${getStyle( - `--theme_${mode}--primary_hover` - )} 0px 0px 0px 2px !important`, - 'inputBackgroundColor': getStyle(`--theme_${mode}--main`), - 'dividerColor': getStyle(`--theme_${mode}--table-border`), - 'shadowOpacity': 0.2, - }); + // ctrl+f theming + notionIpc.sendNotionToIndex('search:set-theme', { + 'mode': mode, + 'colors': { + 'white': getStyle(`--theme_${mode}--todo_ticked-fill`), + 'blue': getStyle(`--theme_${mode}--primary`), + }, + 'borderRadius': 3, + 'textColor': getStyle(`--theme_${mode}--text`), + 'popoverBackgroundColor': getStyle(`--theme_${mode}--card`), + 'popoverBoxShadow': `0 0 0 1px ${getStyle( + `--theme_${mode}--overlay` + )}, 0 3px 6px ${getStyle(`--theme_${mode}--overlay`)}`, + 'inputBoxShadow': `box-shadow: ${getStyle( + `--theme_${mode}--primary` + )} 0px 0px 0px 1px inset, ${getStyle( + `--theme_${mode}--primary_hover` + )} 0px 0px 0px 2px !important`, + 'inputBackgroundColor': getStyle(`--theme_${mode}--main`), + 'dividerColor': getStyle(`--theme_${mode}--table-border`), + 'shadowOpacity': 0.2, + }); - // enhancer menu - electron.ipcRenderer.send('enhancer:set-theme', { - mode, - rules: require('./css/variables.json').map((rule) => [ - rule, - getStyle(rule), - ]), - }); + // enhancer menu + electron.ipcRenderer.send('enhancer:set-theme', { + mode, + rules: require('./css/variables.json').map((rule) => [ + rule, + getStyle(rule), + ]), + }); - // draggable area resizing - const sidebar = document.querySelector('.notion-sidebar'); - if (settings.frameless && sidebar) { - let new_sidebar_width = - sidebar.style.height === 'auto' ? '0px' : sidebar.style.width; - if (sidebar_width !== new_sidebar_width) { - sidebar_width = new_sidebar_width; - electron.ipcRenderer.sendToHost( - 'enhancer:sidebar-width', - sidebar_width - ); - } + // draggable area resizing + const sidebar = document.querySelector('.notion-sidebar'); + if (store().frameless && sidebar) { + let new_sidebar_width = + sidebar.style.height === 'auto' ? '0px' : sidebar.style.width; + if (sidebar_width !== new_sidebar_width) { + sidebar_width = new_sidebar_width; + electron.ipcRenderer.sendToHost( + 'enhancer:sidebar-width', + sidebar_width + ); } } - setInterval(communicationLoop, 500); } - }; + setInterval(communicationLoop, 500); + } +}; diff --git a/mods/core/create.js b/mods/core/create.js index 4a2a1e9..1343670 100644 --- a/mods/core/create.js +++ b/mods/core/create.js @@ -7,84 +7,78 @@ 'use strict'; -module.exports = (defaults) => - function (store, __exports) { - const electron = require('electron'), - allWindows = () => - electron.BrowserWindow.getAllWindows().filter( - (win) => win.getTitle() !== 'notion-enhancer menu' - ), - // createWindow = __exports.createWindow, - path = require('path'), - settings = store(defaults), - helpers = require('../../pkg/helpers.js'), - __notion = helpers.getNotion(); +module.exports = (store, __exports) => { + const electron = require('electron'), + allWindows = () => + electron.BrowserWindow.getAllWindows().filter( + (win) => win.getTitle() !== 'notion-enhancer menu' + ), + // createWindow = __exports.createWindow, + path = require('path'), + helpers = require('../../pkg/helpers.js'), + __notion = helpers.getNotion(); - __exports.createWindow = function (relativeUrl) { - if (!relativeUrl) relativeUrl = ''; - const window_state = require(`${__notion.replace( - /\\/g, - '/' - )}/app/node_modules/electron-window-state/index.js`)({ - defaultWidth: 1320, - defaultHeight: 860, - }), - rect = { - x: window_state.x, - y: window_state.y, - width: window_state.width, - height: window_state.height, - }, - focused_window = electron.BrowserWindow.getFocusedWindow(); - if (focused_window && !focused_window.isMaximized()) { - rect.x = focused_window.getPosition()[0] + 20; - rect.y = focused_window.getPosition()[1] + 20; - rect.width = focused_window.getSize()[0]; - rect.height = focused_window.getSize()[1]; + __exports.createWindow = function (relativeUrl) { + if (!relativeUrl) relativeUrl = ''; + const window_state = require(`${__notion.replace( + /\\/g, + '/' + )}/app/node_modules/electron-window-state/index.js`)({ + defaultWidth: 1320, + defaultHeight: 860, + }), + rect = { + x: window_state.x, + y: window_state.y, + width: window_state.width, + height: window_state.height, + }, + focused_window = electron.BrowserWindow.getFocusedWindow(); + if (focused_window && !focused_window.isMaximized()) { + rect.x = focused_window.getPosition()[0] + 20; + rect.y = focused_window.getPosition()[1] + 20; + rect.width = focused_window.getSize()[0]; + rect.height = focused_window.getSize()[1]; + } + const window = new electron.BrowserWindow({ + show: false, + backgroundColor: '#ffffff', + titleBarStyle: 'hiddenInset', + frame: !store().frameless, + webPreferences: { + preload: path.resolve(`${__notion}/app/renderer/index.js`), + webviewTag: true, + session: electron.session.fromPartition('persist:notion'), + }, + ...rect, + }); + window.once('ready-to-show', function () { + if ( + !store().openhidden || + allWindows().some((win) => win.isVisible() && win.id != window.id) + ) { + window.show(); + window.focus(); + if (store().maximized) window.maximize(); + if ( + (focused_window && focused_window.isFullScreen()) || + window_state.isFullScreen + ) + window.setFullScreen(true); } - const window = new electron.BrowserWindow({ - show: false, - backgroundColor: '#ffffff', - titleBarStyle: 'hiddenInset', - frame: !settings.frameless, - webPreferences: { - preload: path.resolve(`${__notion}/app/renderer/index.js`), - webviewTag: true, - session: electron.session.fromPartition('persist:notion'), - }, - ...rect, - }); - window.once('ready-to-show', function () { - if ( - !settings.openhidden || - allWindows().some((win) => win.isVisible() && win.id != window.id) - ) { - window.show(); - window.focus(); - if (settings.maximized) window.maximize(); - if ( - (focused_window && focused_window.isFullScreen()) || - window_state.isFullScreen - ) - window.setFullScreen(true); - } - }); - let intended_quit = false; - window.on('close', (e) => { - if ( - intended_quit || - !settings.close_to_tray || - allWindows().length > 1 - ) { - window_state.saveState(window); - window = null; - } else { - e.preventDefault(); - window.hide(); - } - }); - electron.app.on('before-quit', () => (intended_quit = true)); - window.loadURL(__exports.getIndexUrl(relativeUrl)); - return window; - }; + }); + let intended_quit = false; + window.on('close', (e) => { + if (intended_quit || !store().close_to_tray || allWindows().length > 1) { + window_state.saveState(window); + window = null; + } else { + e.preventDefault(); + window.hide(); + } + }); + electron.app.on('before-quit', () => (intended_quit = true)); + window.loadURL(__exports.getIndexUrl(relativeUrl)); + return window; }; +}; diff --git a/mods/core/css/menu.css b/mods/core/css/menu.css index 019b43d..58ee971 100644 --- a/mods/core/css/menu.css +++ b/mods/core/css/menu.css @@ -60,7 +60,6 @@ main { } main section { border-radius: 2px; - padding: 0.75em; margin-bottom: 0.75em; } @@ -118,6 +117,7 @@ s { #alerts [role='alert'] { display: flex; + padding: 0.75em; } #alerts [role='alert']::before { content: '!'; @@ -180,6 +180,12 @@ s { background: var(--theme_local--sidebar); border: 1px solid var(--theme_local--table-border); } +#modules section > div { + padding: 0.75em; +} +.notion-light-theme #modules section { + background: var(--theme_local--main); +} #modules section h3, #modules section p { @@ -187,6 +193,13 @@ s { font-size: 1rem; } +/* #modules section .meta .toggle input + label .switch:before { + background: linear-gradient( + 90deg, + var(--theme_local--text_green), + var(--theme_local--bg_green) + ); +} */ #modules section .desc { margin: 0.3em 0 0.4em 0; font-size: 0.9em; @@ -236,19 +249,51 @@ s { /* module options */ +#modules .disabled .options { + display: none; +} +#modules section .options { + border-top: 1px solid var(--theme_local--table-border); + background: var(--theme_local--card); +} +#modules section .options p { + font-size: 0.9em; +} +#modules section .options p:not(:last-child) { + padding-bottom: 0.5em; + border-bottom: 0.5px solid var(--theme_local--table-border); + margin-bottom: 0.5em; +} + +select { + width: 100%; + margin: 0.25em 0; + font-size: 0.9rem; + padding: 0.4rem 0.2rem; + border: none; + color: var(--theme_local--text); + background: var(--theme_local--main); +} + .toggle * { cursor: pointer; } .toggle input { display: none; } +.toggle input + label { + display: flex; +} +.toggle input + label .name { + flex-basis: calc(100% - 2.25em); +} .toggle input + label .switch { position: relative; margin-top: 0.5em; float: right; height: 0.65em; width: 2em; - background: var(--theme_local--card); + background: var(--theme_local--main); border-radius: 5px; } .toggle input + label .switch:before { diff --git a/mods/core/menu.js b/mods/core/menu.js index 4ad2b65..f5cea1f 100644 --- a/mods/core/menu.js +++ b/mods/core/menu.js @@ -6,14 +6,13 @@ 'use strict'; -const __mod = require('./mod.js'), - store = require('../../pkg/store.js'), +const store = require('../../pkg/store.js'), helpers = require('../../pkg/helpers.js'), electron = require('electron'), browser = electron.remote.getCurrentWindow(); window['__start'] = async () => { - const buttons = require('./buttons.js'); + const buttons = require('./buttons.js')(() => ({ frameless: true })); document.querySelector('#menu-titlebar').appendChild(buttons.element); document.defaultView.addEventListener('keyup', (event) => { @@ -61,10 +60,11 @@ window['__start'] = async () => { ) .then((res) => res.json()) .then((res) => { - const version = { - local: __mod.version.split(/[~-]/g)[0], - repo: res.tag_name.slice(1), - }; + const raw_v = require('./mod.js').version, + version = { + local: raw_v.split(/[~-]/g)[0], + repo: res.tag_name.slice(1), + }; if (version.local == version.repo) return; // compare func from https://github.com/substack/semver-compare version.sorted = [version.local, version.repo].sort((a, b) => { @@ -87,7 +87,7 @@ window['__start'] = async () => { run npm i -g notion-enhancer
(or yarn global add notion-enhancer),
and notion-enhancer apply.` - : `local build v${__mod.version} is unstable.` + : `local build v${raw_v} is unstable.` ).prepend(); }); @@ -108,13 +108,12 @@ window['__start'] = async () => { ).append(); } - // mod options + // mod info + options function markdown(string) { const parsed = string .split('\n') .map((line) => line - // todo: stop e.g. whole chunk of ~~thin~~g~~ being selected .trim() .replace(/\s+/g, ' ') // > quote @@ -148,56 +147,121 @@ window['__start'] = async () => { .join(''); return parsed; } + + let modified_notice; + function modified() { + if (modified_notice) return; + modified_notice = createAlert( + 'info', + `changes may not apply until app restart.` + ); + modified_notice.append(); + } + const $modules = document.querySelector('#modules'); - for (let mod of modules.loaded.sort((a, b) => { - return a.tags.includes('core') || - store('mods', { [a.id]: { pinned: false } }).pinned + for (let mod of modules.loaded.sort((a, b) => + a.tags.includes('core') || + store('mods', { [a.id]: { pinned: false } }).pinned ? -1 : b.tags.includes('core') || store('mods', { [b.id]: { pinned: false } }).pinned ? 1 - : a.name.localeCompare(b.name); - })) { + : a.name.localeCompare(b.name) + )) { const menuStore = store('mods', { [mod.id]: { enabled: false } }); - mod.store = store(mod.id); mod.elem = createElement(` `); const $enable = mod.elem.querySelector(`#enable_${mod.id}`); if ($enable) $enable.addEventListener('click', (event) => { menuStore[mod.id].enabled = $enable.checked; + mod.elem.className = menuStore[mod.id].enabled ? 'enabled' : 'disabled'; }); + const $options = mod.elem.querySelector('.options'); + if ($options) + for (const opt of mod.options) { + let $opt; + switch (opt.type) { + case 'toggle': + $opt = createElement(` +

+ + +

+ `); + const $opt_checkbox = $opt.querySelector( + `#toggle_${mod.id}--${opt.key}` + ); + $opt_checkbox.addEventListener('change', (event) => { + store(mod.id)[opt.key] = $opt_checkbox.checked; + modified(); + }); + $options.appendChild($opt); + break; + case 'select': + $opt = createElement(` +

+ + +

+ `); + const $opt_select = $opt.querySelector( + `#select_${mod.id}--${opt.key}` + ); + $opt_select.value = store(mod.id)[opt.key]; + $opt_select.addEventListener('change', (event) => { + store(mod.id)[opt.key] = $opt_select.value; + modified(); + }); + $options.appendChild($opt); + break; + case 'input': + break; + case 'file': + break; + } + } $modules.append(mod.elem); } }; diff --git a/mods/core/mod.js b/mods/core/mod.js index 574d4d4..6d02054 100644 --- a/mods/core/mod.js +++ b/mods/core/mod.js @@ -6,16 +6,6 @@ 'use strict'; -const defaults = { - openhidden: false, - maximized: false, - close_to_tray: true, - frameless: true, - dragarea_height: 15, - smooth_scrollbars: true, - hotkey: 'CmdOrCtrl+Shift+A', -}; - module.exports = { id: '0f0bf8b6-eae6-4273-b307-8fc43f2ee082', tags: ['core', 'extension'], @@ -24,12 +14,54 @@ module.exports = { ![](https://preview.redd.it/vtiw9ulqlt951.png?width=1368&format=png&auto=webp&s=733d8b27ec62151c7858b4eca463f809ead6395a)`, version: require('../../package.json').version, author: 'dragonwocky', - options: [], + options: [ + { + key: 'openhidden', + label: 'hide app on open', + type: 'toggle', + value: false, + }, + { + key: 'maximized', + label: 'auto-maximise windows', + type: 'toggle', + value: false, + }, + { + key: 'close_to_tray', + label: 'close window to the tray', + type: 'toggle', + value: true, + }, + { + key: 'frameless', + label: 'integrate titlebar into notion', + type: 'toggle', + value: true, + }, + { + key: 'dragarea_height', + label: 'height of frameless dragarea', + type: 'input', + value: 15, + }, + { + key: 'smooth_scrollbars', + label: 'integrate scrollbars into notion', + type: 'toggle', + value: true, + }, + { + key: 'hotkey', + label: 'window display hotkey', + type: 'input', + value: 'CmdOrCtrl+Shift+A', + }, + ], hacks: { - 'main/main.js': require('./tray.js')(defaults), - 'main/createWindow.js': require('./create.js')(defaults), - 'renderer/index.js': require('./render.js')(defaults), - 'renderer/preload.js': require('./client.js')(defaults), + 'main/main.js': require('./tray.js'), + 'main/createWindow.js': require('./create.js'), + 'renderer/index.js': require('./render.js'), + 'renderer/preload.js': require('./client.js'), }, - defaults, }; diff --git a/mods/core/render.js b/mods/core/render.js index d77e17a..f9eb7f8 100644 --- a/mods/core/render.js +++ b/mods/core/render.js @@ -6,28 +6,28 @@ 'use strict'; -module.exports = (defaults) => - function (store, __exports) { - const __start = window['__start'], - settings = store(defaults); +module.exports = (store, __exports) => { + const __start = window['__start']; - window['__start'] = function () { - __start(); - const dragarea = document.querySelector( - '#root [style*="-webkit-app-region: drag"]' - ), - default_styles = dragarea.getAttribute('style'); + window['__start'] = function () { + __start(); + const dragarea = document.querySelector( + '#root [style*="-webkit-app-region: drag"]' + ), + default_styles = dragarea.getAttribute('style'); - // document.body.innerText = document.body.innerHTML; + // document.body.innerText = document.body.innerHTML; - document - .getElementById('notion') - .addEventListener('ipc-message', (event) => { - if (event.channel !== 'enhancer:sidebar-width') return; - dragarea.setAttribute( - 'style', - `${default_styles} top: 2px; height: ${settings.dragarea_height}px; left: ${event.args[0]};` - ); - }); - }; + document + .getElementById('notion') + .addEventListener('ipc-message', (event) => { + if (event.channel !== 'enhancer:sidebar-width') return; + dragarea.setAttribute( + 'style', + `${default_styles} top: 2px; height: ${ + store().dragarea_height + }px; left: ${event.args[0]};` + ); + }); }; +}; diff --git a/mods/core/tray.js b/mods/core/tray.js index 91c8a48..cc7ddcf 100644 --- a/mods/core/tray.js +++ b/mods/core/tray.js @@ -9,176 +9,174 @@ let tray, enhancer_menu; -module.exports = (defaults) => - function (store, __exports) { - const electron = require('electron'), - path = require('path'), - is_mac = process.platform === 'darwin', - is_win = process.platform === 'win32', - settings = store(defaults), - helpers = require('../../pkg/helpers.js'), - __notion = helpers.getNotion(); +module.exports = (store, __exports) => { + const electron = require('electron'), + path = require('path'), + is_mac = process.platform === 'darwin', + is_win = process.platform === 'win32', + helpers = require('../../pkg/helpers.js'), + __notion = helpers.getNotion(); - electron.app.on('ready', () => { - tray = new electron.Tray( - is_win - ? path.resolve(`${__dirname}/icons/windows.ico`) - : new electron.nativeImage.createFromPath( - path.resolve(`${__dirname}/icons/mac+linux.png`) - ).resize({ - width: 16, - height: 16, - }) - ); + electron.app.on('ready', () => { + tray = new electron.Tray( + is_win + ? path.resolve(`${__dirname}/icons/windows.ico`) + : new electron.nativeImage.createFromPath( + path.resolve(`${__dirname}/icons/mac+linux.png`) + ).resize({ + width: 16, + height: 16, + }) + ); - electron.ipcMain.on('enhancer:set-theme', (event, arg) => { - if (!enhancer_menu) return; - enhancer_menu.webContents.send('enhancer:set-theme', arg); + electron.ipcMain.on('enhancer:set-theme', (event, arg) => { + if (!enhancer_menu) return; + enhancer_menu.webContents.send('enhancer:set-theme', arg); + }); + electron.ipcMain.on('enhancer:open-extension-menu', openExtensionMenu); + + function calculateWindowPos(width, height) { + const screen = electron.screen.getDisplayNearestPoint({ + x: tray.getBounds().x, + y: tray.getBounds().y, }); - electron.ipcMain.on('enhancer:open-extension-menu', openExtensionMenu); - - function calculateWindowPos(width, height) { - const screen = electron.screen.getDisplayNearestPoint({ - x: tray.getBounds().x, - y: tray.getBounds().y, - }); - // left - if (screen.workArea.x > 0) - return { - x: screen.workArea.x, - y: screen.workArea.height - height, - }; - // top - if (screen.workArea.y > 0) - return { - x: Math.round( - tray.getBounds().x + tray.getBounds().width / 2 - width / 2 - ), - y: screen.workArea.y, - }; - // right - if (screen.workArea.width < screen.bounds.width) - return { - x: screen.workArea.width - width, - y: screen.bounds.height - height, - }; - // bottom + // left + if (screen.workArea.x > 0) + return { + x: screen.workArea.x, + y: screen.workArea.height - height, + }; + // top + if (screen.workArea.y > 0) return { x: Math.round( tray.getBounds().x + tray.getBounds().width / 2 - width / 2 ), - y: screen.workArea.height - height, + y: screen.workArea.y, }; - } + // right + if (screen.workArea.width < screen.bounds.width) + return { + x: screen.workArea.width - width, + y: screen.bounds.height - height, + }; + // bottom + return { + x: Math.round( + tray.getBounds().x + tray.getBounds().width / 2 - width / 2 + ), + y: screen.workArea.height - height, + }; + } - function openExtensionMenu() { - if (enhancer_menu) return enhancer_menu.show(); - const window_state = require(`${__notion.replace( - /\\/g, - '/' - )}/app/node_modules/electron-window-state/index.js`)({ - file: 'menu-windowstate.json', - path: helpers.data_folder, - defaultWidth: 275, - defaultHeight: 600, - }); - electron.shell.openExternal(JSON.stringify(window_state)); - enhancer_menu = new electron.BrowserWindow({ - show: true, - frame: false, - titleBarStyle: 'hiddenInset', - x: - window_state.x || - calculateWindowPos(window_state.width, window_state.height).x, - y: - window_state.y || - calculateWindowPos(window_state.width, window_state.height).y, - width: window_state.width, - height: window_state.height, - webPreferences: { - preload: path.resolve(`${__dirname}/menu.js`), - nodeIntegration: true, - session: electron.session.fromPartition('persist:notion'), - }, - }); - enhancer_menu.loadURL('enhancement://core/menu.html'); - enhancer_menu.on('close', (e) => { - window_state.saveState(enhancer_menu); - enhancer_menu = null; - }); - } - - const contextMenu = electron.Menu.buildFromTemplate([ - { - type: 'normal', - label: 'Bug Report', - click: () => { - electron.shell.openExternal( - 'https://github.com/dragonwocky/notion-enhancer/issues/new?labels=bug&template=bug-report.md' - ); - }, - }, - { - type: 'normal', - label: 'Feature Request', - click: () => { - electron.shell.openExternal( - 'https://github.com/dragonwocky/notion-enhancer/issues/new?labels=enhancement&template=feature-request.md' - ); - }, - }, - { - type: 'separator', - }, - { - type: 'normal', - label: 'Docs', - click: () => { - electron.shell.openExternal( - 'https://github.com/dragonwocky/notion-enhancer/tree/js' - ); - }, - }, - { - type: 'normal', - label: 'Enhancements', - accelerator: 'CommandOrControl+E', - click: openExtensionMenu, - }, - { - type: 'separator', - }, - { - label: 'Quit', - role: 'quit', - }, - ]); - tray.setContextMenu(contextMenu); - tray.setToolTip('Notion'); - - function showWindows() { - const windows = electron.BrowserWindow.getAllWindows(); - if (is_mac) electron.app.show(); - if (settings.maximized) windows.forEach((win) => [win.maximize()]); - else windows.forEach((win) => win.show()); - electron.app.focus({ steal: true }); - } - function hideWindows() { - const windows = electron.BrowserWindow.getAllWindows(); - windows.forEach((win) => [win.isFocused() && win.blur(), win.hide()]); - if (is_mac) electron.app.hide(); - } - - tray.on('click', () => { - const windows = electron.BrowserWindow.getAllWindows(); - if (windows.some((win) => win.isVisible())) hideWindows(); - else showWindows(); + function openExtensionMenu() { + if (enhancer_menu) return enhancer_menu.show(); + const window_state = require(`${__notion.replace( + /\\/g, + '/' + )}/app/node_modules/electron-window-state/index.js`)({ + file: 'menu-windowstate.json', + path: helpers.data_folder, + defaultWidth: 275, + defaultHeight: 600, }); - electron.globalShortcut.register(settings.hotkey, () => { - const windows = electron.BrowserWindow.getAllWindows(); - if (windows.some((win) => win.isFocused() && win.isVisible())) - hideWindows(); - else showWindows(); + electron.shell.openExternal(JSON.stringify(window_state)); + enhancer_menu = new electron.BrowserWindow({ + show: true, + frame: false, + titleBarStyle: 'hiddenInset', + x: + window_state.x || + calculateWindowPos(window_state.width, window_state.height).x, + y: + window_state.y || + calculateWindowPos(window_state.width, window_state.height).y, + width: window_state.width, + height: window_state.height, + webPreferences: { + preload: path.resolve(`${__dirname}/menu.js`), + nodeIntegration: true, + session: electron.session.fromPartition('persist:notion'), + }, }); + enhancer_menu.loadURL('enhancement://core/menu.html'); + enhancer_menu.on('close', (e) => { + window_state.saveState(enhancer_menu); + enhancer_menu = null; + }); + } + + const contextMenu = electron.Menu.buildFromTemplate([ + { + type: 'normal', + label: 'Bug Report', + click: () => { + electron.shell.openExternal( + 'https://github.com/dragonwocky/notion-enhancer/issues/new?labels=bug&template=bug-report.md' + ); + }, + }, + { + type: 'normal', + label: 'Feature Request', + click: () => { + electron.shell.openExternal( + 'https://github.com/dragonwocky/notion-enhancer/issues/new?labels=enhancement&template=feature-request.md' + ); + }, + }, + { + type: 'separator', + }, + { + type: 'normal', + label: 'Docs', + click: () => { + electron.shell.openExternal( + 'https://github.com/dragonwocky/notion-enhancer/tree/js' + ); + }, + }, + { + type: 'normal', + label: 'Enhancements', + accelerator: 'CommandOrControl+E', + click: openExtensionMenu, + }, + { + type: 'separator', + }, + { + label: 'Quit', + role: 'quit', + }, + ]); + tray.setContextMenu(contextMenu); + tray.setToolTip('Notion'); + + function showWindows() { + const windows = electron.BrowserWindow.getAllWindows(); + if (is_mac) electron.app.show(); + if (store().maximized) windows.forEach((win) => [win.maximize()]); + else windows.forEach((win) => win.show()); + electron.app.focus({ steal: true }); + } + function hideWindows() { + const windows = electron.BrowserWindow.getAllWindows(); + windows.forEach((win) => [win.isFocused() && win.blur(), win.hide()]); + if (is_mac) electron.app.hide(); + } + + tray.on('click', () => { + const windows = electron.BrowserWindow.getAllWindows(); + if (windows.some((win) => win.isVisible())) hideWindows(); + else showWindows(); }); - }; + electron.globalShortcut.register(store().hotkey, () => { + const windows = electron.BrowserWindow.getAllWindows(); + if (windows.some((win) => win.isFocused() && win.isVisible())) + hideWindows(); + else showWindows(); + }); + }); +}; diff --git a/pkg/helpers.js b/pkg/helpers.js index 8040baa..fefbef5 100644 --- a/pkg/helpers.js +++ b/pkg/helpers.js @@ -127,7 +127,11 @@ function getEnhancements() { modules.IDs.includes(mod.id) || !mod.name || !mod.version || - !mod.author + !mod.author || + (mod.options && + !mod.options.every((opt) => + ['toggle', 'select', 'input', 'file'].includes(opt.type) + )) ) throw Error; modules.loaded.push({ diff --git a/pkg/loader.js b/pkg/loader.js index d5213af..f1acbcc 100644 --- a/pkg/loader.js +++ b/pkg/loader.js @@ -52,14 +52,22 @@ module.exports = function (__file, __exports) { document.querySelector('head').appendChild(style); }); } - if (mod.hacks && mod.hacks[__file]) + if (mod.hacks && mod.hacks[__file]) { + mod.defaults = {}; + for (let opt of mod.options || []) + mod.defaults[opt.key] = Array.isArray(opt.value) + ? opt.value[0] + : opt.value; mod.hacks[__file]( (...args) => - args.length === 1 - ? store(mod.id, args[0]) - : store(args[0], args[1]), + !args.length + ? store(mod.id, mod.defaults) + : args.length === 1 + ? store(mod.id, { ...mod.defaults, ...args[0] }) + : store(args[0], { ...mod.defaults, ...args[1] }), __exports ); + } } } };