diff --git a/CHANGELOG.md b/CHANGELOG.md index 94a8738..6cc9bf1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,8 @@ a flexibility update. - new: in-page columns disabled/wrapped and wider pages when the window is narrower than 600px for improved responsiveness. - new: relaunch button in tray menu. +- new: a core mod option for a default page id/url (all new windows will load it instead of the + normal "most recent" page). - improved: a core mod option to make transitions snappy/0s. - improved: menu will now respect integrated titlebar setting. - improved: use keyup listeners instead of a globalShortcut for the enhancements menu toggle. @@ -32,6 +34,7 @@ a flexibility update. - bugfix: remove focus mode footer from neutral theme. - bugfix: improvements to the colour theming, particularly to make real- and fake-light/dark modes (as applied by the night shift extension) look consistent. +- bugfix: font sizing applied to overlays/previews. - tweak: sticky table/list rows. - theme: "material ocean" = an oceanic colour palette. - theme: "dracula" = a theme based on the popular dracula color palette diff --git a/mods/core/buttons.js b/mods/core/buttons.js index e50de06..bae94cd 100644 --- a/mods/core/buttons.js +++ b/mods/core/buttons.js @@ -15,7 +15,7 @@ module.exports = (store) => { buttons = { element: helpers.createElement('
'), insert: [ - ...((store('mods', {})['72886371-dada-49a7-9afc-9f275ecf29d3'] || {}) + ...((store('mods')['72886371-dada-49a7-9afc-9f275ecf29d3'] || {}) .enabled ? ['alwaysontop'] : []), diff --git a/mods/core/client.js b/mods/core/client.js index 4d683ca..3315093 100644 --- a/mods/core/client.js +++ b/mods/core/client.js @@ -19,12 +19,16 @@ module.exports = (store, __exports) => { // additional hotkeys document.defaultView.addEventListener('keyup', (event) => { if (event.code === 'F5') location.reload(); - // open menu on hotkey toggle - const hotkey = toKeyEvent(store().menu_toggle); - let triggered = true; - for (let prop in hotkey) - if (hotkey[prop] !== event[prop]) triggered = false; - if (triggered) electron.ipcRenderer.send('enhancer:open-menu'); + if ( + !(store('mods')['e1692c29-475e-437b-b7ff-3eee872e1a42'] || {}).enabled + ) { + // open menu on hotkey toggle + const hotkey = toKeyEvent(store().menu_toggle); + let triggered = true; + for (let prop in hotkey) + if (hotkey[prop] !== event[prop]) triggered = false; + if (triggered) electron.ipcRenderer.send('enhancer:open-menu'); + } }); const attempt_interval = setInterval(enhance, 500); @@ -43,7 +47,11 @@ module.exports = (store, __exports) => { document.body.classList.add('snappy-transitions'); // frameless - if (store().frameless && !store().tiling_mode && !store().tabs) { + if ( + store().frameless && + !store().tiling_mode && + !(store('mods')['e1692c29-475e-437b-b7ff-3eee872e1a42'] || {}).enabled + ) { document.body.classList.add('frameless'); // draggable area document @@ -56,7 +64,9 @@ module.exports = (store, __exports) => { } // window buttons - if (!store().tabs) { + if ( + !(store('mods')['e1692c29-475e-437b-b7ff-3eee872e1a42'] || {}).enabled + ) { const buttons = require('./buttons.js')(store); document .querySelector('.notion-topbar > div[style*="display: flex"]') @@ -153,7 +163,9 @@ module.exports = (store, __exports) => { '--theme--code_inline-background', ].map((rule) => [rule, getStyle(rule)]) ); - if (store().tabs) { + if ( + (store('mods')['e1692c29-475e-437b-b7ff-3eee872e1a42'] || {}).enabled + ) { electron.ipcRenderer.sendToHost( 'enhancer:set-tab-theme', [ @@ -179,7 +191,7 @@ module.exports = (store, __exports) => { ); electron.ipcRenderer.on('enhancer:get-menu-theme', setThemeVars); - if (store().tabs) { + if ((store('mods')['e1692c29-475e-437b-b7ff-3eee872e1a42'] || {}).enabled) { let tab_title = ''; __electronApi.setWindowTitle = (title) => { if (tab_title !== title) { diff --git a/mods/core/css/theme.css b/mods/core/css/theme.css index 735fad2..faeac8f 100644 --- a/mods/core/css/theme.css +++ b/mods/core/css/theme.css @@ -152,7 +152,8 @@ [style*='SFMono-Regular'] { font-family: var(--theme--font_code) !important; } -.notion-frame .notion-page-block div[placeholder='Untitled'] { +.notion-frame .notion-page-block div[placeholder='Untitled'], +.notion-overlay-container .notion-page-block div[placeholder='Untitled']{ font-size: calc( var(--theme--font_body-size) * (var(--theme--font_heading1-size) / 1em) ) !important; @@ -172,15 +173,16 @@ var(--theme--font_body-size) * (var(--theme--font_heading3-size) / 1em) ) !important; } -.notion-frame .notion-scroller.vertical.horizontal [style*='font-size: 14px'] { +.notion-frame .notion-scroller.vertical.horizontal [style*='font-size: 14px'], +.notion-overlay-container .notion-scroller.vertical [style*='font-size: 14px']{ font-size: var(--theme--font_label-size) !important; } -.notion-frame .notion-scroller.vertical.horizontal .notion-page-content { +.notion-frame .notion-scroller.vertical.horizontal .notion-page-content, +.notion-overlay-container .notion-scroller.vertical .notion-page-content { font-size: var(--theme--font_body-size) !important; } -.notion-frame - .notion-scroller.vertical.horizontal - .notion-page-content[style*='font-size: 14px'] { +.notion-frame .notion-scroller.vertical.horizontal .notion-page-content[style*='font-size: 14px'], +.notion-overlay-container .notion-scroller.vertical .notion-page-content[style*='font-size: 14px'] { font-size: var(--theme--font_body-size_small) !important; } .notion-code-block [placeholder=' '] { diff --git a/mods/core/menu.js b/mods/core/menu.js index 5925e28..60a0d20 100644 --- a/mods/core/menu.js +++ b/mods/core/menu.js @@ -14,47 +14,43 @@ const store = require('../../pkg/store.js'), { toKeyEvent } = require('keyboardevent-from-electron-accelerator'); window['__start'] = async () => { + // mod loader + const modules = helpers.getEnhancements(); + if (modules.loaded.length) + console.info( + ` enhancements loaded: ${modules.loaded + .map((mod) => mod.name) + .join(', ')}.` + ); + if (modules.invalid.length) { + createAlert( + 'error', + `invalid mods found: ${modules.invalid + .map((mod) => `${mod}`) + .join(', ')}.` + ).append(); + } + const coreStore = (...args) => { + const mod = modules.loaded.find( + (m) => m.id === '0f0bf8b6-eae6-4273-b307-8fc43f2ee082' + ); + return !args.length + ? store(mod.id, mod.defaults) + : args.length === 1 && typeof args[0] === 'object' + ? store(mod.id, { ...mod.defaults, ...args[0] }) + : store(args[0], { ...mod.defaults, ...args[1] }); + }; + const buttons = require('./buttons.js')(() => ({ '72886371-dada-49a7-9afc-9f275ecf29d3': { enabled: (store('mods')['72886371-dada-49a7-9afc-9f275ecf29d3'] || {}) .enabled, }, - tiling_mode: store('0f0bf8b6-eae6-4273-b307-8fc43f2ee082').tiling_mode, - frameless: store('0f0bf8b6-eae6-4273-b307-8fc43f2ee082').frameless, + tiling_mode: coreStore().tiling_mode, + frameless: coreStore().frameless, })); document.querySelector('#titlebar').appendChild(buttons.element); - document.defaultView.addEventListener('keyup', (event) => { - if (event.code === 'F5') location.reload(); - const meta = - !(event.ctrlKey || event.metaKey) && !event.altKey && !event.shiftKey; - if ( - meta && - document.activeElement.parentElement.id === 'tags' && - event.key === 'Enter' - ) - document.activeElement.click(); - if (document.activeElement.tagName.toLowerCase() === 'input') { - if (document.activeElement.type === 'checkbox' && event.key === 'Enter') - document.activeElement.checked = !document.activeElement.checked; - if ( - ['Escape', 'Enter'].includes(event.key) && - document.activeElement.type !== 'checkbox' && - (document.activeElement.parentElement.id !== 'search' || - event.key === 'Escape') - ) - document.activeElement.blur(); - } else if (meta && event.key === '/') - document.querySelector('#search > input').focus(); - if ( - (event.ctrlKey || event.metaKey) && - event.key === 'f' && - !event.altKey && - !event.shiftKey - ) - document.querySelector('#search > input').focus(); - }); - electron.ipcRenderer.send('enhancer:get-menu-theme'); electron.ipcRenderer.on('enhancer:set-menu-theme', (event, theme) => { for (const style of theme) @@ -120,26 +116,10 @@ window['__start'] = async () => { ).prepend(); }); - // mod loader - const modules = helpers.getEnhancements(); - if (modules.loaded.length) - console.info( - ` enhancements loaded: ${modules.loaded - .map((mod) => mod.name) - .join(', ')}.` - ); - if (modules.invalid.length) { - createAlert( - 'error', - `invalid mods found: ${modules.invalid - .map((mod) => `${mod}`) - .join(', ')}.` - ).append(); - } - - // further-configuration popup const $popup = document.querySelector('#popup'); document.addEventListener('keyup', (event) => { + if (event.code === 'F5') location.reload(); + // further-configuration popup if ( $popup.classList.contains('visible') && ['Enter', 'Escape'].includes(event.key) @@ -147,18 +127,41 @@ window['__start'] = async () => { $popup.classList.remove('visible'); // close window on hotkey toggle console.log(); - const hotkey = toKeyEvent( - store('0f0bf8b6-eae6-4273-b307-8fc43f2ee082', { - menu_toggle: modules.loaded - .find((m) => m.id === '0f0bf8b6-eae6-4273-b307-8fc43f2ee082') - .options.find((o) => o.key === 'menu_toggle').value, - }).menu_toggle - ); + const hotkey = toKeyEvent(coreStore().menu_toggle); let triggered = true; for (let prop in hotkey) if (hotkey[prop] !== event[prop]) triggered = false; if (triggered) electron.remote.getCurrentWindow().close(); + // focus search + const meta = + !(event.ctrlKey || event.metaKey) && !event.altKey && !event.shiftKey; + if ( + meta && + document.activeElement.parentElement.id === 'tags' && + event.key === 'Enter' + ) + document.activeElement.click(); + if (document.activeElement.tagName.toLowerCase() === 'input') { + if (document.activeElement.type === 'checkbox' && event.key === 'Enter') + document.activeElement.checked = !document.activeElement.checked; + if ( + ['Escape', 'Enter'].includes(event.key) && + document.activeElement.type !== 'checkbox' && + (document.activeElement.parentElement.id !== 'search' || + event.key === 'Escape') + ) + document.activeElement.blur(); + } else if (meta && event.key === '/') + document.querySelector('#search > input').focus(); + if ( + (event.ctrlKey || event.metaKey) && + event.key === 'f' && + !event.altKey && + !event.shiftKey + ) + document.querySelector('#search > input').focus(); }); + let colorpicker_target = null; const $colorpicker = colorjoe .rgb('colorpicker') @@ -171,7 +174,6 @@ window['__start'] = async () => { store(colorpicker_target.id)[colorpicker_target.key] = color.css(); }) .update(); - document .querySelector('#colorpicker') .appendChild( @@ -424,11 +426,13 @@ window['__start'] = async () => { }; mod.elem = helpers.createElement(`

${mod.name}` : `class="toggle"> + `notion://www.notion.so/${ + url.parse(id).pathname.split('/').reverse()[0] || '' + }/${url.parse(id).search || ''}`; module.exports = (store, __exports) => { - if (store().tabs) { + if ((store('mods')['e1692c29-475e-437b-b7ff-3eee872e1a42'] || {}).enabled) { class Index extends React.PureComponent { constructor() { super(...arguments); @@ -157,22 +161,39 @@ module.exports = (store, __exports) => { const list = new Map(this.state.tabs); while (this.state.tabs.get(id)) id++; list.delete(id); - if (this.views.html[id]) { - this.views.html[id].style.opacity = '0'; - let unhide; - unhide = () => { - this.views.html[id].style.opacity = ''; - this.views.html[id].removeEventListener('did-stop-loading', unhide); - }; - this.views.html[id].addEventListener('did-stop-loading', unhide); - this.views.html[id].loadURL(this.views.current.$el().src); - } - this.openTab(id, list); + this.openTab(id, list, true); } - openTab(id, state = new Map(this.state.tabs)) { + openTab(id, state = new Map(this.state.tabs), load) { if (!id && id !== 0) return; this.views.current.id = id; - this.setState({ tabs: state.set(id, true) }, this.focusTab.bind(this)); + this.setState({ tabs: state.set(id, true) }, async () => { + this.focusTab(); + if (load) { + await new Promise((res, rej) => { + let attempt; + attempt = setInterval(() => { + if (!document.body.contains(this.views.html[id])) return; + clearInterval(attempt); + res(); + }, 50); + }); + this.views.html[id].style.opacity = '0'; + let unhide; + unhide = () => { + this.views.html[id].style.opacity = ''; + this.views.html[id].removeEventListener( + 'did-stop-loading', + unhide + ); + }; + this.views.html[id].addEventListener('did-stop-loading', unhide); + this.views.html[id].loadURL( + store().default_page + ? idToNotionURL(store().default_page) + : this.views.current.$el().src + ); + } + }); } closeTab(id) { if ((!id && id !== 0) || !this.state.tabs.get(id)) return; @@ -219,11 +240,12 @@ module.exports = (store, __exports) => { ) { this.views.tabs[event.target.id].children[0].innerText = event.args[0]; + const electronWindow = electron.remote.getCurrentWindow(); if ( event.target.id == this.views.current.id && - browserWindow.getTitle() !== event.args[0] + electronWindow.getTitle() !== event.args[0] ) - browserWindow.setTitle(event.args[0]); + electronWindow.setTitle(event.args[0]); } } startSearch(isPeekView) { @@ -426,25 +448,41 @@ module.exports = (store, __exports) => { this.setState({ zoomFactor }); } ); + let electronWindow; + try { + electronWindow = electron.remote.getCurrentWindow(); + } catch (error) { + notionIpc.sendToMain('notion:log-error', { + level: 'error', + from: 'index', + type: 'GetCurrentWindowError', + error: error.message, + }); + } + if (!electronWindow) { + this.setState({ error: true }); + this.handleReload(); + return; + } const sendFullScreenChangeEvent = () => { notionIpc.sendIndexToNotion( $notion, 'notion:full-screen-changed' ); }; - browserWindow.addListener( + electronWindow.addListener( 'enter-full-screen', sendFullScreenChangeEvent ); - browserWindow.addListener( + electronWindow.addListener( 'leave-full-screen', sendFullScreenChangeEvent ); - browserWindow.addListener( + electronWindow.addListener( 'enter-html-full-screen', sendFullScreenChangeEvent ); - browserWindow.addListener( + electronWindow.addListener( 'leave-html-full-screen', sendFullScreenChangeEvent ); @@ -717,13 +755,24 @@ module.exports = (store, __exports) => { window['__start'] = () => { document.head.innerHTML += ``; + // open menu on hotkey toggle + document.addEventListener('keyup', (event) => { + const hotkey = toKeyEvent(store().menu_toggle); + let triggered = true; + for (let prop in hotkey) + if (hotkey[prop] !== event[prop]) triggered = false; + if (triggered) electron.ipcRenderer.send('enhancer:open-menu'); + }); + const parsed = url.parse(window.location.href, true), notionUrl = parsed.query.path || - schemeHelpers.getSchemeUrl({ - httpUrl: config.default.baseURL, - protocol: config.default.protocol, - }); + (store().default_page + ? idToNotionURL(store().default_page) + : schemeHelpers.getSchemeUrl({ + httpUrl: config.default.baseURL, + protocol: config.default.protocol, + })); delete parsed.search; delete parsed.query; const plainUrl = url.format(parsed); @@ -753,6 +802,31 @@ module.exports = (store, __exports) => { const __start = window['__start']; window['__start'] = () => { __start(); + + if (store().default_page) { + new Promise((res, rej) => { + let attempt; + attempt = setInterval(() => { + if ( + !document.getElementById('notion') || + !document.getElementById('notion').loadURL + ) + return; + clearInterval(attempt); + res(); + }, 50); + }).then(() => { + if ( + document.getElementById('notion').getAttribute('src') === + 'notion://www.notion.so' + ) { + document + .getElementById('notion') + .loadURL(idToNotionURL(store().default_page)); + } + }); + } + const dragarea = document.querySelector( '#root [style*="-webkit-app-region: drag"]' ), diff --git a/mods/tabs/mod.js b/mods/tabs/mod.js new file mode 100644 index 0000000..1585c43 --- /dev/null +++ b/mods/tabs/mod.js @@ -0,0 +1,19 @@ +/* + * tabs + * (c) 2020 dragonwocky (https://dragonwocky.me/) + * under the MIT license + */ + +'use strict'; + +// this is just a pseudo mod to "separate" the options +// from the core module - the core still handles actually +// making it work. +module.exports = { + id: 'e1692c29-475e-437b-b7ff-3eee872e1a42', + tags: ['core', 'extension'], + name: 'tabs', + desc: 'have multiple notion pages open in a single window.', + version: '0.1.0', + author: 'dragonwocky', +}; diff --git a/pkg/helpers.js b/pkg/helpers.js index 325433f..d64c628 100644 --- a/pkg/helpers.js +++ b/pkg/helpers.js @@ -130,6 +130,11 @@ function getEnhancements() { )) ) throw Error; + mod.defaults = {}; + for (let opt of mod.options || []) + mod.defaults[opt.key] = Array.isArray(opt.value) + ? opt.value[0] + : opt.value; modules.IDs.push(mod.id); modules.loaded.push({ ...mod, diff --git a/pkg/loader.js b/pkg/loader.js index 00c7d27..93a92ef 100644 --- a/pkg/loader.js +++ b/pkg/loader.js @@ -60,7 +60,7 @@ module.exports = function (__file, __exports) { ...modules.loaded.filter((m) => !m.tags.includes('core')).reverse(), ]) { if ( - (mod.tags || []).includes('core') || + mod.id === '0f0bf8b6-eae6-4273-b307-8fc43f2ee082' || store('mods', { [mod.id]: { enabled: false } })[mod.id].enabled ) { if ( @@ -84,20 +84,16 @@ module.exports = function (__file, __exports) { }); } 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 - ? store(mod.id, mod.defaults) - : args.length === 1 && typeof args[0] === 'object' - ? store(mod.id, { ...mod.defaults, ...args[0] }) - : store(args[0], { ...mod.defaults, ...args[1] }), - __exports - ); + mod.hacks[__file]((...args) => { + if (!args.length) return store(mod.id, mod.defaults); + if (args.length === 1 && typeof args[0] === 'object') + return store(mod.id, { ...mod.defaults, ...args[0] }); + const other_mod = modules.loaded.find((m) => m.id === args[0]); + return store(args[0], { + ...(other_mod ? other_mod.defaults : {}), + ...args[1], + }); + }, __exports); } } }