From 21facae40ce0573cd5afd6ac1d3fa0e6f731e7e9 Mon Sep 17 00:00:00 2001 From: dragonwocky Date: Sun, 19 Jul 2020 16:24:34 +1000 Subject: [PATCH] taken control of createWindow --- CONTRIBUTING.md | 11 ++-- DOCUMENTATION.md | 18 +++--- README.md | 2 +- mods/core/icons/alwaysontop_off.svg | 1 + mods/core/icons/alwaysontop_on.svg | 1 + mods/core/icons/close.svg | 1 + mods/core/{ => icons}/mac+linux.png | Bin mods/core/icons/maximise_off.svg | 1 + mods/core/icons/maximise_on.svg | 1 + mods/core/icons/minimise.svg | 1 + mods/core/{ => icons}/windows.ico | Bin mods/core/mod.js | 14 +++-- mods/core/tray.js | 22 ++++++- mods/core/window.js | 85 ++++++++++++++++++++++++++++ pkg/apply.js | 23 +++----- pkg/check.js | 4 +- pkg/helpers.js | 10 ++-- pkg/loader.js | 18 +++--- pkg/remove.js | 10 ++-- pkg/store.js | 4 +- 20 files changed, 170 insertions(+), 57 deletions(-) create mode 100644 mods/core/icons/alwaysontop_off.svg create mode 100644 mods/core/icons/alwaysontop_on.svg create mode 100644 mods/core/icons/close.svg rename mods/core/{ => icons}/mac+linux.png (100%) create mode 100644 mods/core/icons/maximise_off.svg create mode 100644 mods/core/icons/maximise_on.svg create mode 100644 mods/core/icons/minimise.svg rename mods/core/{ => icons}/windows.ico (100%) create mode 100644 mods/core/window.js diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 2274cd7..8a45259 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -6,20 +6,19 @@ these guidelines are designed for smooth communication, management and developme following them shows respect to the developer/s spending their free time on it, and makes it easiest for them to improve the tool. **found a bug / something isn't working as expected?** create a -[bug report](https://github.com/dragonwocky/notion-enhancer/issues/new?assignees=&labels=bug&template=bug-report.md&title=). +[bug report](https://github.com/dragonwocky/notion-enhancer/issues/new?labels=bug&template=bug-report.md). > SECURITY ISSUE? (e.g. PERSONAL/NOTION DATA BEING INTERFERED WITH) > EMAIL ME INSTEAD: [thedragonring.bod@gmail.com](mailto:thedragonring.bod@gmail.com) **have a cool new feature idea / there's something you just wish you could do?** submit a -[feature request](https://github.com/dragonwocky/notion-enhancer/issues/new?assignees=&labels=enhancement&template=feature-request.md&title=). +[feature request](https://github.com/dragonwocky/notion-enhancer/issues/new?labels=enhancement&template=feature-request.md). -> enhancements are applied only locally. -> features should be designed only to improve the user experience - -> affecting the way notion internals work is against their ToS. +> enhancements are applied only locally - +> features should be designed only to improve the user experience. **using a not-yet-supported operating system or notion installation?** ask for -[platform support](https://github.com/dragonwocky/notion-enhancer/issues/new?assignees=&labels=enhancement&template=platform-support.md&title=). +[platform support](https://github.com/dragonwocky/notion-enhancer/issues/new?labels=enhancement&template=platform-support.md). > mobile clients cannot currently be modded. diff --git a/DOCUMENTATION.md b/DOCUMENTATION.md index 2ef1d8d..1d4b772 100644 --- a/DOCUMENTATION.md +++ b/DOCUMENTATION.md @@ -84,10 +84,14 @@ module.exports = { #### hacks -each "hack" is a function taking a single **`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 saved to + automatically syncs with `~/.notion-enhancer/id.json`. -it can be initialised with `const data = store({ defaults })`, then used as if it were a normal object. +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 saved to + automatically syncs with `~/.notion-enhancer/id.json`. + it can be initialised with `const settings = 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. this hack is applied to whichever file (`.js`-only) is set as the function key. these can be found within the `app` folder. @@ -104,11 +108,11 @@ e.g. ```js // sayhi.js -module.exports = function (store) { +module.exports = function (store, __exports) { document.addEventListener('readystatechange', (event) => { if (document.readyState !== 'complete') return false; - const data = store({ name: 'dragonwocky' }); - console.log(data.name); + const settings = store({ name: 'dragonwocky' }); + console.log(settings.name); }); }; // mod.js diff --git a/README.md b/README.md index ca5921a..e10df9d 100644 --- a/README.md +++ b/README.md @@ -48,7 +48,7 @@ want to contribute? check the the [contribution guidelines](CONTRIBUTING.md). (it can also be run from the wsl to apply enhancements to the windows app.) **using a not-yet-supported operating system or notion installation?** ask for -[platform support](https://github.com/dragonwocky/notion-enhancer/issues/new?assignees=&labels=enhancement&template=platform-support.md&title=). +[platform support](https://github.com/dragonwocky/notion-enhancer/issues/new?labels=enhancement&template=platform-support.md). mobile clients are not supported and due to system limitations/restrictions cannot be. diff --git a/mods/core/icons/alwaysontop_off.svg b/mods/core/icons/alwaysontop_off.svg new file mode 100644 index 0000000..e731f9b --- /dev/null +++ b/mods/core/icons/alwaysontop_off.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/mods/core/icons/alwaysontop_on.svg b/mods/core/icons/alwaysontop_on.svg new file mode 100644 index 0000000..b9befcd --- /dev/null +++ b/mods/core/icons/alwaysontop_on.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/mods/core/icons/close.svg b/mods/core/icons/close.svg new file mode 100644 index 0000000..7268fb0 --- /dev/null +++ b/mods/core/icons/close.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/mods/core/mac+linux.png b/mods/core/icons/mac+linux.png similarity index 100% rename from mods/core/mac+linux.png rename to mods/core/icons/mac+linux.png diff --git a/mods/core/icons/maximise_off.svg b/mods/core/icons/maximise_off.svg new file mode 100644 index 0000000..e79979f --- /dev/null +++ b/mods/core/icons/maximise_off.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/mods/core/icons/maximise_on.svg b/mods/core/icons/maximise_on.svg new file mode 100644 index 0000000..038b21e --- /dev/null +++ b/mods/core/icons/maximise_on.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/mods/core/icons/minimise.svg b/mods/core/icons/minimise.svg new file mode 100644 index 0000000..e40cd84 --- /dev/null +++ b/mods/core/icons/minimise.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/mods/core/windows.ico b/mods/core/icons/windows.ico similarity index 100% rename from mods/core/windows.ico rename to mods/core/icons/windows.ico diff --git a/mods/core/mod.js b/mods/core/mod.js index 295e0d7..d8e90e5 100644 --- a/mods/core/mod.js +++ b/mods/core/mod.js @@ -7,7 +7,8 @@ const defaults = { openhidden: false, maximized: false, - tray: false, + close_to_tray: false, + frameless: true, hotkey: 'CmdOrCtrl+Shift+A', }; @@ -24,10 +25,13 @@ module.exports = { options: [], hacks: { 'main/main.js': require('./tray.js')(defaults), - 'renderer/preload.js': function (store) { - const data = store({ name: 'dragonwocky' }); - console.log(data.name); - data.name = 'tom'; + 'main/createWindow.js': require('./window.js')(defaults), + 'renderer/preload.js': function (store, __exports) { + const window = require('electron').remote.getCurrentWindow(); + document.defaultView.addEventListener('keyup', (event) => { + if (event.code === 'F5') window.reload(); + // if (event.code === 'F4' && event.altKey) window.close(); + }); }, }, }; diff --git a/mods/core/tray.js b/mods/core/tray.js index 0423260..0a9175d 100644 --- a/mods/core/tray.js +++ b/mods/core/tray.js @@ -8,7 +8,7 @@ let tray; module.exports = (defaults) => - function (store) { + function (store, __exports) { const electron = require('electron'), path = require('path'), is_mac = process.platform === 'darwin', @@ -18,9 +18,9 @@ module.exports = (defaults) => electron.app.on('ready', () => { tray = new electron.Tray( is_win - ? path.normalize(`${__dirname}/windows.ico`) + ? path.resolve(`${__dirname}/icons/windows.ico`) : new electron.nativeImage.createFromPath( - path.normalize(`${__dirname}/mac+linux.png`) + path.resolve(`${__dirname}/icons/mac+linux.png`) ).resize({ width: 16, height: 16, @@ -31,10 +31,20 @@ module.exports = (defaults) => { 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', @@ -42,6 +52,11 @@ module.exports = (defaults) => { type: 'normal', label: 'Docs', + click: () => { + electron.shell.openExternal( + 'https://github.com/dragonwocky/notion-enhancer/tree/js' + ); + }, }, { type: 'normal', @@ -70,6 +85,7 @@ module.exports = (defaults) => 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(); diff --git a/mods/core/window.js b/mods/core/window.js new file mode 100644 index 0000000..82ddc49 --- /dev/null +++ b/mods/core/window.js @@ -0,0 +1,85 @@ +/* + * notion-enhancer + * (c) 2020 dragonwocky + * (c) 2020 TarasokUA + * (https://dragonwocky.me/) under the MIT license + */ + +module.exports = (defaults) => + function (store, __exports) { + const electron = require('electron'), + allWindows = electron.BrowserWindow.getAllWindows, + createWindow = __exports.createWindow, + path = require('path'), + is_mac = process.platform === 'darwin', + settings = store(defaults), + 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]; + } + 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(); + 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; + }; + }; diff --git a/pkg/apply.js b/pkg/apply.js index f5e39e9..44a8628 100644 --- a/pkg/apply.js +++ b/pkg/apply.js @@ -56,16 +56,14 @@ module.exports = async function ({ overwrite_version } = {}) { }); } console.info(' ...unpacking app.asar'); - const asar_app = path.normalize(`${__notion}/app.asar`), - asar_exec = path.normalize( - `${__dirname}/../node_modules/asar/bin/asar.js` - ); + const asar_app = path.resolve(`${__notion}/app.asar`), + asar_exec = path.resolve(`${__dirname}/../node_modules/asar/bin/asar.js`); await promisify(exec)( - `"${asar_exec}" extract "${asar_app}" "${path.normalize( + `"${asar_exec}" extract "${asar_app}" "${path.resolve( `${__notion}/app` )}"` ); - fs.move(asar_app, path.normalize(`${__notion}/app.asar.bak`)); + fs.move(asar_app, path.resolve(`${__notion}/app.asar.bak`)); // patching launch script target of custom wrappers if ( @@ -94,31 +92,28 @@ module.exports = async function ({ overwrite_version } = {}) { } for await (let insertion_target of readdirIterator( - path.normalize(`${__notion}/app`), + path.resolve(`${__notion}/app`), { deep: (stats) => stats.path.indexOf('node_modules') === -1, filter: (stats) => stats.isFile() && stats.path.endsWith('.js'), } )) { - insertion_target = path.normalize(`${__notion}/app/${insertion_target}`); + insertion_target = path.resolve(`${__notion}/app/${insertion_target}`); fs.appendFile( insertion_target, `\n\n//notion-enhancer\nrequire('${helpers.realpath( __dirname - )}/loader.js')(__filename);` + )}/loader.js')(__filename, exports);` ); } // not resolved, nothing depends on it so it's just a "let it do its thing" console.info(' ...recording enhancement version.'); fs.outputFile( - path.normalize(`${__notion}/app/ENHANCER_VERSION.txt`), - version - ); - fs.outputFile( - path.normalize(`${helpers.data_folder}/version.txt`), + path.resolve(`${__notion}/app/ENHANCER_VERSION.txt`), version ); + fs.outputFile(path.resolve(`${helpers.data_folder}/version.txt`), version); console.info(' ~~ success.'); return true; diff --git a/pkg/check.js b/pkg/check.js index 8e1337d..65e62c5 100644 --- a/pkg/check.js +++ b/pkg/check.js @@ -14,11 +14,11 @@ const fs = require('fs-extra'), let __notion = helpers.getNotion(); module.exports = async function () { - const version_path = path.normalize(`${__notion}/app/ENHANCER_VERSION.txt`), + const version_path = path.resolve(`${__notion}/app/ENHANCER_VERSION.txt`), installed_version = (await fs.pathExists(version_path)) ? await fs.readFile(version_path, 'utf8') : '?.?.?'; - if (await fs.pathExists(path.normalize(`${__notion}/app.asar`))) { + if (await fs.pathExists(path.resolve(`${__notion}/app.asar`))) { return { msg: `notion-enhancer has not been applied.`, code: 0, diff --git a/pkg/helpers.js b/pkg/helpers.js index 49caa74..f09b93f 100644 --- a/pkg/helpers.js +++ b/pkg/helpers.js @@ -25,7 +25,7 @@ const is_wsl = process.platform === 'linux' && os.release().toLowerCase().includes('microsoft'), // ~/.notion-enhancer absolute path. - data_folder = path.normalize( + data_folder = path.resolve( `${ is_wsl ? (() => { @@ -86,19 +86,19 @@ function getNotion() { if (!folder) throw new EnhancerError( 'platform not supported: open a request in the github repo:\n' + - 'https://github.com/dragonwocky/notion-enhancer/issues/new?assignees=&labels=enhancement&template=platform-support.md' + 'https://github.com/dragonwocky/notion-enhancer/issues/new?labels=enhancement&template=platform-support.md' ); // check if actual app files are present. // if app/app.asar are missing but app.asar.bak present it will be moved to app.asar - const app_asar = path.normalize(`${folder}/app.asar`); + const app_asar = path.resolve(`${folder}/app.asar`); if ( !( fs.pathExistsSync(folder) && (fs.pathExistsSync(app_asar) || - fs.pathExistsSync(path.normalize(`${folder}/app`))) + fs.pathExistsSync(path.resolve(`${folder}/app`))) ) ) { - const asar_bak = path.normalize(`${__notion}/app.asar.bak`); + const asar_bak = path.resolve(`${__notion}/app.asar.bak`); if (fs.pathExistsSync(asar_bak)) { fs.moveSync(asar_bak, app_asar); } else diff --git a/pkg/loader.js b/pkg/loader.js index fd6d8f8..90683cc 100644 --- a/pkg/loader.js +++ b/pkg/loader.js @@ -11,13 +11,13 @@ const fs = require('fs-extra'), store = require('./store.js'); let __notion = helpers.getNotion(); -module.exports = function (__file) { +module.exports = function (__file, __exports) { __file = __file - .slice(path.normalize(`${__notion}/app`).length + 1) + .slice(path.resolve(`${__notion}/app`).length + 1) .replace(/\\/g, '/'); const modules = { - source: fs.readdirSync(path.normalize(`${__dirname}/../mods`)), + source: fs.readdirSync(path.resolve(`${__dirname}/../mods`)), invalid: [], loaded: [], }; @@ -34,13 +34,17 @@ module.exports = function (__file) { throw Error; if (mod.type === 'core' || store('mods', { [mod.id]: false })[mod.id]) { if (mod.hacks && mod.hacks[__file]) - mod.hacks[__file]((...args) => - args.length === 1 ? store(mod.id, args[0]) : store(args[0], args[1]) + mod.hacks[__file]( + (...args) => + args.length === 1 + ? store(mod.id, args[0]) + : store(args[0], args[1]), + __exports ); if ( __file === 'renderer/preload.js' && fs.pathExistsSync( - path.normalize(`${__dirname}/../mods/${dir}/styles.css`) + path.resolve(`${__dirname}/../mods/${dir}/styles.css`) ) ) { document.addEventListener('readystatechange', (event) => { @@ -63,7 +67,7 @@ module.exports = function (__file) { .session.fromPartition('persist:notion') .protocol.registerFileProtocol('enhancement', (req, callback) => { callback({ - path: path.normalize( + path: path.resolve( `${__dirname}/../mods/${req.url.slice('enhancement://'.length)}` ), }); diff --git a/pkg/remove.js b/pkg/remove.js index 7b146b6..ae10c97 100644 --- a/pkg/remove.js +++ b/pkg/remove.js @@ -23,18 +23,18 @@ module.exports = async function ({ overwrite_asar, delete_data } = {}) { const file_operations = []; // extracted asar: modded - const app_folder = path.normalize(`${__notion}/app`); + const app_folder = path.resolve(`${__notion}/app`); if (await fs.pathExists(app_folder)) { console.info(` ...removing folder ${app_folder}`); file_operations.push(fs.remove(app_folder)); } else console.warn(` * ${app_folder} not found: step skipped.`); // restoring original asar - const asar_bak = path.normalize(`${__notion}/app.asar.bak`); + const asar_bak = path.resolve(`${__notion}/app.asar.bak`); if (await fs.pathExists(asar_bak)) { console.info(' ...moving asar.app.bak to app.asar'); - if (await fs.pathExists(path.normalize(`${__notion}/app.asar`))) { + if (await fs.pathExists(path.resolve(`${__notion}/app.asar`))) { console.warn(' * app.asar already exists!'); if (overwrite_asar === undefined) { do { @@ -56,7 +56,7 @@ module.exports = async function ({ overwrite_asar, delete_data } = {}) { file_operations.push( overwrite_asar || overwrite_asar === undefined - ? fs.move(asar_bak, path.normalize(`${__notion}/app.asar`), { + ? fs.move(asar_bak, path.resolve(`${__notion}/app.asar`), { overwrite: true, }) : fs.remove(asar_bak) @@ -83,7 +83,7 @@ module.exports = async function ({ overwrite_asar, delete_data } = {}) { ); if (delete_data) { file_operations.push(fs.remove(helpers.data_folder)); - } else fs.remove(path.normalize(`${helpers.data_folder}/version.txt`)); + } else fs.remove(path.resolve(`${helpers.data_folder}/version.txt`)); } else console.warn(` * ${helpers.data_folder} not found: step skipped.`); await Promise.all(file_operations); diff --git a/pkg/store.js b/pkg/store.js index 06a1bc8..9de230b 100644 --- a/pkg/store.js +++ b/pkg/store.js @@ -11,11 +11,11 @@ const path = require('path'), // a wrapper for accessing data stored in a JSON file. module.exports = (namespace, defaults = {}) => { - namespace = path.normalize(`${data_folder}/${namespace}.json`); + namespace = path.resolve(`${data_folder}/${namespace}.json`); fs.ensureDirSync(data_folder); const getData = () => ({ ...defaults, ...getJSON(namespace) }); - fs.writeJsonSync(namespace, getData()); + // fs.writeJsonSync(namespace, getData()); return new Proxy(defaults, { get(obj, prop) {