diff --git a/CHANGELOG.md b/CHANGELOG.md
index 49a8d6d..72b963d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,11 +2,61 @@
**potential future features (not confirmed)**
-- [groupy-like tabbing](https://www.npmjs.com/package/electron-tabs)
-- [improved responsiveness](https://chrome.google.com/webstore/detail/notion%20%20-responsiveness-f/leadcilhbmibbkgbnjgmmnfgnnhmeddk)
- [highlight/mark viewer](https://chrome.google.com/webstore/detail/notion%2B-mark-manager/hipgmnlpnimedfepbfbfiaobohhffcfc)
- [advanced math editor](https://github.com/Manueloccorso/NotionMathEditor_BrowserExtension)
-- re-orderable extensions
+
+### v0.10.0 (wip)
+
+a flexibility update.
+
+- new: mods can be reordered in the menu to control what order styling/scripts are added/executed in.
+ higher up on the list = higher priority of application = loaded last in order to override others.
+ (excluding the core, which though pinned to the top of the list is always loaded first so theming
+ variables can be modified.)
+- new: in-page columns are disabled/wrapped and pages are wider when
+ the window is narrower than 600px for improved responsiveness.
+- new: relaunch button in tray menu.
+- new: a core mod option to make transitions snappy/0s.
+- new: a core mod option for a default page id/url (all new windows will load it instead of the
+ normal "most recent" page).
+- new: css variables for increasing line spacing/paragraph margins.
+- new: patch the notion:// url scheme/protocol to work on linux.
+- improved: menu will now respect integrated titlebar setting.
+- improved: use keyup listeners instead of a globalShortcut for the enhancements menu toggle.
+- bugfix: removed messenger emoji set as the provider no longer supports it.
+- bugfix: remove shadow around light mode board headers
+ \+ minor text colour fixes for night shift theming.
+- bugfix: properly detect/respond to `EACCES`/`EBUSY` errors.
+- bugfix: night shift checks every interaction,
+ will respond to system changes without any manual changes.
+- bugfix: toc blocks can have text colours.
+- bugfix: bypass preview extension works with the back/forward keyboard shortcuts.
+- bugfix: (maybe) fix csp issues under proxy.
+- 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.
+ relevant variables (assuming all are prefixed by `--theme_[dark|light]--`):
+ `box-shadow`, `box-shadow_strong`, `select_input`, and `ui-border`
+- bugfix: font sizing applied to overlays/previews.
+- bugfix: removed typo in variable name for brown text.
+- bugfix: primary-colour text (mainly in "add a \_" popups) is now properly themed.
+- bugfix: right-to-left extension applies to text in columns.
+- tweak: sticky table/list rows.
+- theme: "material ocean" = an oceanic colour palette.
+- theme: "dracula" = a theme based on the popular dracula color palette
+ originally by zeno rocha and friends.
+- extension: "tabs" = have multiple notion pages open in a single window.
+
+a fork of notion-deb-builder that does generate an app.asar has been created and is once again supported.
+
+// todo
+
+- new: menu shows theme conflicts.
+- improved: default option for showing/hiding page properties.
+- bugfix: night shift working on macOS.
+- bugfix: windows are properly hidden/shown on macOS.
+- extension: "tweaks" = common layout changes.
+- update themes to new variables.
### v0.9.1 (2020-09-26)
diff --git a/DOCUMENTATION.md b/DOCUMENTATION.md
index 95f0667..ed22a83 100644
--- a/DOCUMENTATION.md
+++ b/DOCUMENTATION.md
@@ -20,7 +20,7 @@ _for examples of the stuff described below in action._
_at the moment, for ease of development and use (and security assurance), there's no way for users_
_to install their own modules. this means that testing modules requires_
-_[running a dev build of the enhancer](DOCUMENTATION.md#testing). a better system is in the works._
+_[running a dev build of the enhancer](https://github.com/dragonwocky/notion-enhancer/blob/master/CONTRIBUTING.md#testing). a better system is in the works._
_once your mod is working, open a pull request to add it to the enhancer!_
diff --git a/README.md b/README.md
index 8a749d2..1f1f702 100644
--- a/README.md
+++ b/README.md
@@ -17,6 +17,8 @@ for support, join the [discord server](https://discord.gg/sFWPXtA).
- the [official windows/mac releases](https://notion.so/desktop).
- the arch linux AUR [notion-app](https://aur.archlinux.org/packages/notion-app/) package.
- the linux [notion-app](https://github.com/jaredallard/notion-app) installer.
+- [@haydn-jones](https://github.com/haydn-jones/)'s fork of the
+ linux [notion-deb-builder](https://github.com/haydn-jones/notion-deb-builder).
(it can also be run from the wsl to apply enhancements to the windows app.)
@@ -31,10 +33,23 @@ a chrome extension may be coming soon for web client support.
during installation/removal, make sure no notion processes are running! (check your task manager.)
-**win10, macOS**
+**win10**
-1. [install node.js](https://nodejs.org/en/download/) (_a computer restart may be required here._)
-2. execute `npm i -g notion-enhancer` in the terminal/command prompt.
+[install node.js](https://nodejs.org/en/download/) (_a computer restart may be required here_),
+then execute `npm i -g notion-enhancer` in the command prompt.
+
+**macOS**
+
+[install node.js](https://nodejs.org/en/download/) (_a computer restart may be required here_),
+then execute the following lines in the terminal:
+
+```
+sudo chmod -R a+wr /usr/local/lib/node_modules
+sudo chmod -R a+wr /usr/local/bin
+sudo chmod -R a+wr /Applications/Notion/Contents/Resources
+sudo chmod -R a+wr /Applications/Notion.app/Contents/Resources
+npm i -g notion-enhancer
+```
**debian/ubuntu, chromeOS, WSL (to modify the win10 app)**
@@ -43,7 +58,7 @@ execute the following lines in the terminal:
```
bash curl -sL https://deb.nodesource.com setup_current.x | sudo -E bash -
sudo apt-get install -y nodejs
-sudo npm i -g notion-enhancer
+npm i -g notion-enhancer
```
**arch linux, manjaro**
@@ -81,6 +96,14 @@ Options:
-v, --version : display version number
```
+### faq
+
+**the themes aren't working?**
+
+if you pick a dark theme it will only be applied if notion is in dark mode,
+and if you pick a light theme it will only work if notion is in light mode.
+do `CMD/CTRL+SHIFT+L` to toggle between them.
+
**is this against notion's terms of service? can i get in trouble for using it?**
definitely not! i contacted their support team to check, and the response was awesome:
@@ -91,8 +114,16 @@ team to take to heart for future improvements."
## features
-once applied, modules can be configured via the graphical menu, which is opened from
-the tray/menubar icon or with `ALT+E`.
+most of the enhancer's functionality is split into configurable enhancement modules,
+but some basic improvements are built in by default:
+
+- the notion:// url scheme/protocol is patched to work on linux.
+- in-page columns are disabled/wrapped and pages are wider when
+ the window is narrower than 600px for improved responsiveness.
+- a tray/menubar icon: links relevant to the enhancer + buttons to manage notion windows.
+
+once applied, modules can be configured via the graphical menu,
+which is opened from the tray/menubar icon or with `OPTION/ALT+E`.

@@ -164,7 +195,8 @@ on top of other windows even if it's not focused.
**tags:** #extension
-**description:** link files for small client-side tweaks.
+**description:** link files for small client-side tweaks. (not sure how to do something? check out the
+[tweaks](https://github.com/dragonwocky/notion-enhancer/blob/master/TWEAKS.md) collection.)
**author**: [dragonwocky](https://github.com/dragonwocky/)
@@ -343,8 +375,9 @@ the font you would like to use, or leave it blank to not change anything.
a couple months after I ([@dragonwocky](https://github.com/dragonwocky/)) picked the project up, at first extending
upon the original base and later moving to the javascript module system.
-since then, various community members have helped out heaps - some listed as
+the enhancer wouldn't be anything near to what it is now though without
+interested community members testing, coding and ideating features - some are listed as
[contributors](https://github.com/dragonwocky/notion-enhancer/graphs/contributors) here on github,
-but many helping with code, feedback and testing on discord and in emails.
+but many more have been helping out on discord and in emails.
individual modules have their original authors attributed.
diff --git a/TWEAKS.md b/TWEAKS.md
index a15d9ed..aba6147 100644
--- a/TWEAKS.md
+++ b/TWEAKS.md
@@ -70,10 +70,34 @@ then use the 3 dots up in the top-right corner to remove them.
+### sticky table/list row
+
+note: this will make the first row stick to the top of the screen when scrolling down.
+to stick a specific row replace `:nth-child(2)` with `[data-block-id="ROW_BLOCK_ID_HERE"]`.
+
+does not apply to inline databases.
+
+```css
+.notion-collection_view_page-block
+ .notion-page-block.notion-collection-item:nth-child(2) {
+ background: var(--theme--main);
+ z-index: 10;
+ position: sticky;
+ top: 0;
+}
+.notion-table-view
+ .notion-collection_view_page-block
+ .notion-page-block.notion-collection-item:nth-child(2) {
+ top: 32px;
+}
+```
+
+
+
### table columns below 100px
**not recommended!** this may cause buggy viewing.
-as it is a per-table-column style, unlike all others here, it must be prepended with the block ID and repeated for each column.
+as it is a per-table-column style, unlike most others here, it must be prepended with the block ID and repeated for each column.
to see how to do this, watch [this video](https://www.youtube.com/watch?v=6V7eqShm_4w).
diff --git a/bin.js b/bin.js
old mode 100644
new mode 100755
diff --git a/mods/bypass-preview/mod.js b/mods/bypass-preview/mod.js
index 0a12995..2fe9f02 100644
--- a/mods/bypass-preview/mod.js
+++ b/mods/bypass-preview/mod.js
@@ -11,57 +11,43 @@ module.exports = {
tags: ['extension'],
name: 'bypass preview',
desc: 'go straight to the normal full view when opening a page.',
- version: '0.1.0',
+ version: '0.1.2',
author: 'dragonwocky',
hacks: {
'renderer/preload.js'(store, __exports) {
document.addEventListener('readystatechange', (event) => {
if (document.readyState !== 'complete') return false;
- const attempt_interval = setInterval(enhance, 500);
- function enhance() {
- const notion_elem = document.querySelector('.notion-app-inner');
- if (!notion_elem) return;
- clearInterval(attempt_interval);
- const observer = new MutationObserver(handle);
- observer.observe(notion_elem, {
- childList: true,
- subtree: true,
- });
+ let queue = [];
+ const observer = new MutationObserver((list, observer) => {
+ if (!queue.length) requestIdleCallback(() => handle(queue));
+ queue.push(...list);
+ });
+ observer.observe(document.body, {
+ childList: true,
+ subtree: true,
+ attributes: true,
+ });
- let pageHistory = [];
- handle();
- function handle(list, observer) {
- const pageID = (location.search
- .slice(1)
- .split('&')
- .map((opt) => opt.split('='))
- .find((opt) => opt[0] === 'p') || [
- '',
- ...location.pathname.split(/(-|\/)/g).reverse(),
- ])[1],
- preview = document.querySelector(
- '.notion-peek-renderer [style*="height: 45px;"] a'
- );
- if (
- pageID &&
- (!pageHistory[0] ||
- pageHistory[0][0] !== pageID ||
- pageHistory[0][1] !== !!preview)
- ) {
- if (preview) {
- if (
- pageHistory[1] &&
- pageHistory[0][0] === pageID &&
- pageHistory[1][0] === pageID &&
- pageHistory[1][1]
- ) {
- document.querySelector('.notion-history-back-button').click();
- } else preview.click();
- }
- // most recent is at start for easier access
- pageHistory.unshift([pageID, !!preview]);
- }
- }
+ let lastPageID;
+ function handle(list) {
+ queue = [];
+ const pageID = (location.search
+ .slice(1)
+ .split('&')
+ .map((opt) => opt.split('='))
+ .find((opt) => opt[0] === 'p') || [
+ '',
+ ...location.pathname.split(/(-|\/)/g).reverse(),
+ ])[1],
+ preview = document.querySelector(
+ '.notion-peek-renderer [style*="height: 45px;"] a'
+ );
+ if (!pageID) return;
+ if (preview) {
+ if (pageID === lastPageID) {
+ history.back();
+ } else preview.click();
+ } else lastPageID = pageID;
}
});
},
diff --git a/mods/bypass-preview/styles.css b/mods/bypass-preview/styles.css
index 95f2308..176a1b9 100644
--- a/mods/bypass-preview/styles.css
+++ b/mods/bypass-preview/styles.css
@@ -5,5 +5,5 @@
*/
.notion-peek-renderer {
- opacity: 0;
+ display: none;
}
diff --git a/mods/cherrycola/mod.js b/mods/cherrycola/mod.js
new file mode 100644
index 0000000..33e4c34
--- /dev/null
+++ b/mods/cherrycola/mod.js
@@ -0,0 +1,16 @@
+/*
+ * cherry cola
+ * (c) 2020 Alexa Baldon (https://github.com/runargs)
+ * under the MIT license
+ */
+
+'use strict';
+
+module.exports = {
+ id: 'ec5c4640-68d4-4d25-aefd-62c7e9737cfb',
+ tags: ['theme', 'dark'],
+ name: 'cherry cola',
+ desc: 'a delightfully plummy, cherry cola flavored theme.',
+ version: '0.1.0',
+ author: 'runargs',
+};
diff --git a/mods/cherrycola/styles.css b/mods/cherrycola/styles.css
new file mode 100644
index 0000000..893e96a
--- /dev/null
+++ b/mods/cherrycola/styles.css
@@ -0,0 +1,150 @@
+/*
+ * cherry cola
+ * (c) 2020 Alexa Baldon (https://github.com/runargs)
+ * (c) 2020 dragonwocky (https://dragonwocky.me/)
+ * under the MIT license
+ */
+
+:root {
+ --cola-main: #180915;
+ --cola-sec: #1d0919;
+ --cola-tet: #492341;
+ --cola-info: #9b6890;
+ --cola-accent: #bf799b;
+ --cola-gray: #8a8a8a;
+ --cola-brown: #755241;
+ --cola-orange: #e6846b;
+ --cola-yellow: #d7b56e;
+ --cola-green: #8f9b4f;
+ --cola-blue: #6ebdb7;
+ --cola-purple: #813d63;
+ --cola-pink: #d86f71;
+ --cola-red: #a33232;
+
+ /* Main */
+ --theme_dark--main: var(--cola-main);
+ --theme_dark--sidebar: var(--cola-sec);
+ --theme_dark--overlay: var(--cola-sec);
+ --theme_dark--dragarea: #210a1c;
+ --theme_dark--box-shadow: rgba(20, 0, 16, 0.2) 0px 0px 0px 1px,
+ rgba(20, 0, 16, 0.2) 0px 2px 4px;
+ --theme_dark--box-shadow_strong: rgba(20, 0, 16, 0.1) 0px 0px 0px 1px,
+ rgba(20, 0, 16, 0.2) 0px 3px 6px, rgba(20, 0, 16, 0.4) 0px 9px 24px;
+
+ /* Scrollbar */
+ --theme_dark--scrollbar: var(--cola-sec);
+ --theme_dark--scrollbar_hover: var(--cola-accent);
+
+ /* Database */
+ --theme_dark--card: var(--cola-sec);
+ --theme_dark--gallery: var(--cola-sec);
+ --theme_dark--select_input: var(--cola-tet);
+ --theme_dark--table-border: var(--cola-tet);
+ --theme_dark--ui-border: rgba(73, 35, 65, 0.7);
+ --theme_dark--interactive_hover: var(--cola-tet);
+ --theme_dark--button_close: var(--cola-accent);
+
+ /* Select/hover/click */
+ --theme_dark--selected: rgba(78, 32, 69, 0.5);
+ --theme_dark--primary: var(--cola-accent);
+ --theme_dark--primary_hover: var(--cola-accent);
+ --theme_dark--primary_click: var(--cola-sec);
+ --theme_dark--primary_indicator: var(--cola-accent);
+
+ --theme_dark--option_active-background: var(--theme_dark--primary);
+ --theme_dark--option_hover-background: var(--theme_dark--primary_hover);
+
+ /* Danger */
+ --theme_dark--danger_text: #eb5757;
+ --theme_dark--danger_border: rgba(235, 87, 87, 0.5);
+
+ /* Default text colors */
+ --theme_dark--text: #ffffff;
+ --theme_dark--text_ui: var(--cola-info);
+ --theme_dark--text_ui_info: var(--cola-info);
+
+ /* Text color options */
+ --theme_dark--text_gray: var(--cola-gray);
+ --theme_dark--text_brown: var(--cola-brown);
+ --theme_dark--text_orange: var(--cola-orange);
+ --theme_dark--text_yellow: var(--cola-yellow);
+ --theme_dark--text_green: var(--cola-green);
+ --theme_dark--text_blue: var(--cola-blue);
+ --theme_dark--text_purple: var(--cola-purple);
+ --theme_dark--text_pink: var(--cola-pink);
+ --theme_dark--text_red: var(--cola-red);
+
+ --theme_dark--select-text: var(--cola-main);
+ --theme_dark--select_gray: var(--cola-gray);
+ --theme_dark--select_brown: var(--cola-brown);
+ --theme_dark--select_brown-text: #ffffff;
+ --theme_dark--select_orange: var(--cola-orange);
+ --theme_dark--select_yellow: var(--cola-yellow);
+ --theme_dark--select_green: var(--cola-green);
+ --theme_dark--select_blue: var(--cola-blue);
+ --theme_dark--select_purple: var(--cola-purple);
+ --theme_dark--select_purple-text: #ffffff;
+ --theme_dark--select_pink: var(--cola-pink);
+ --theme_dark--select_red: var(--cola-red);
+ --theme_dark--select_red-text: #ffffff;
+
+ --theme_dark--line-text: var(--cola-main);
+ --theme_dark--line_gray: var(--cola-gray);
+ --theme_dark--line_brown: var(--cola-brown);
+ --theme_dark--line_orange: var(--cola-orange);
+ --theme_dark--line_yellow: var(--cola-yellow);
+ --theme_dark--line_green: var(--cola-green);
+ --theme_dark--line_blue: var(--cola-blue);
+ --theme_dark--line_purple: var(--cola-purple);
+ --theme_dark--line_pink: var(--cola-pink);
+ --theme_dark--line_red: var(--cola-red);
+
+ --theme_dark--bg-text: var(--theme_dark--select-text);
+ --theme_dark--bg_gray: var(--theme_dark--select_gray);
+ --theme_dark--bg_brown: var(--theme_dark--select_brown);
+ --theme_dark--bg_orange: var(--theme_dark--select_orange);
+ --theme_dark--bg_yellow: var(--theme_dark--select_yellow);
+ --theme_dark--bg_green: var(--theme_dark--select_green);
+ --theme_dark--bg_blue: var(--theme_dark--select_blue);
+ --theme_dark--bg_purple: var(--theme_dark--select_purple);
+ --theme_dark--bg_pink: var(--theme_dark--select_pink);
+ --theme_dark--bg_red: var(--theme_dark--select_red);
+
+ /* Callout blocks */
+ --theme_dark--callout-text: var(--theme_dark--line-text);
+ --theme_dark--callout_gray: var(--theme_dark--line_gray);
+ --theme_dark--callout_brown: var(--theme_dark--line_brown);
+ --theme_dark--callout_orange: var(--theme_dark--line_orange);
+ --theme_dark--callout_yellow: var(--theme_dark--line_yellow);
+ --theme_dark--callout_green: var(--theme_dark--line_green);
+ --theme_dark--callout_blue: var(--theme_dark--line_blue);
+ --theme_dark--callout_purple: var(--theme_dark--line_purple);
+ --theme_dark--callout_pink: var(--theme_dark--line_pink);
+ --theme_dark--callout_red: var(--theme_dark--line_red);
+
+ /* Incline/code text */
+ --theme_dark--code_inline-text: var(--cola-accent);
+ --theme_dark--code_inline-background: var(--cola-main);
+ --theme_dark--code-text: var(--theme_dark--text);
+ --theme_dark--code-background: var(--cola-sec);
+ --theme_dark--code_function: var(--theme_dark--text_blue);
+ --theme_dark--code_keyword: var(--theme_dark--text_pink);
+ --theme_dark--code_tag: var(--theme_dark--text_pink);
+ --theme_dark--code_operator: var(--theme_dark--text_yellow);
+ --theme_dark--code_important: var(--theme_dark--text_yellow);
+ --theme_dark--code_property: var(--theme_dark--text_pink);
+ --theme_dark--code_builtin: var(--theme_dark--text_yellow);
+ --theme_dark--code_attr-name: var(--theme_dark--text_yellow);
+ --theme_dark--code_comment: var(--theme_dark--text_gray);
+ --theme_dark--code_punctuation: var(--theme_dark--text_gray);
+ --theme_dark--code_doctype: var(--theme_dark--text_gray);
+ --theme_dark--code_number: var(--theme_dark--text_purple);
+ --theme_dark--code_string: var(--theme_dark--text_orange);
+ --theme_dark--code_attr-value: var(--theme_dark--text_orange);
+}
+
+/* Quotations as serif */
+.notion-dark-theme .notion-quote-block {
+ font-family: Georgia, 'Times New Roman', Times, serif;
+ background-color: var(--cola-sec);
+}
diff --git a/mods/core/buttons.js b/mods/core/buttons.js
index e93dddd..d132722 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']
: []),
@@ -83,19 +83,19 @@ module.exports = (store) => {
(async () => {
for (let btn of buttons.insert) {
- buttons.element.innerHTML += `${await buttons.icons[
+ buttons.element.innerHTML += `${await buttons.icons[
btn
]()} `;
}
for (let btn of buttons.insert) {
- document.querySelector(`.window-button#btn-${btn}`).onclick =
+ buttons.element.querySelector(`.window-button.btn-${btn}`).onclick =
buttons.actions[btn];
}
if (store().frameless && !store().tiling_mode && !is_mac) {
window.addEventListener('resize', (event) => {
Promise.resolve(buttons.icons.maximize()).then((icon) => {
icon = icon.toString();
- const el = buttons.element.querySelector('#btn-maximize');
+ const el = buttons.element.querySelector('.btn-maximize');
if (el.innerHTML != icon) el.innerHTML = icon;
});
});
diff --git a/mods/core/client.js b/mods/core/client.js
index 0aca69c..2d8d458 100644
--- a/mods/core/client.js
+++ b/mods/core/client.js
@@ -13,11 +13,61 @@ module.exports = (store, __exports) => {
notionIpc = require(`${helpers.__notion.replace(
/\\/g,
'/'
- )}/app/helpers/notionIpc.js`);
+ )}/app/helpers/notionIpc.js`),
+ { toKeyEvent } = require('keyboardevent-from-electron-accelerator'),
+ tabsEnabled = (store('mods')['e1692c29-475e-437b-b7ff-3eee872e1a42'] || {})
+ .enabled;
- // additional hotkeys
document.defaultView.addEventListener('keyup', (event) => {
- if (event.code === 'F5') location.reload();
+ // additional hotkeys
+ if (event.key === '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 (tabsEnabled) {
+ // switch between tabs via key modifier
+ const select_tab_modifier = toKeyEvent(
+ store('e1692c29-475e-437b-b7ff-3eee872e1a42').select_modifier
+ );
+ let triggered = true;
+ for (let prop in select_tab_modifier)
+ if (select_tab_modifier[prop] !== event[prop]) triggered = false;
+ if (
+ triggered &&
+ [
+ '1',
+ '2',
+ '3',
+ '4',
+ '5',
+ '6',
+ '7',
+ '8',
+ '9',
+ 'ArrowRight',
+ 'ArrowLeft',
+ ].includes(event.key)
+ )
+ electron.ipcRenderer.sendToHost('enhancer:select-tab', event.key);
+ // create/close tab keybindings
+ const new_tab_keybinding = toKeyEvent(
+ store('e1692c29-475e-437b-b7ff-3eee872e1a42').new_tab
+ );
+ triggered = true;
+ for (let prop in new_tab_keybinding)
+ if (new_tab_keybinding[prop] !== event[prop]) triggered = false;
+ if (triggered) electron.ipcRenderer.sendToHost('enhancer:new-tab');
+ const close_tab_keybinding = toKeyEvent(
+ store('e1692c29-475e-437b-b7ff-3eee872e1a42').close_tab
+ );
+ triggered = true;
+ for (let prop in close_tab_keybinding)
+ if (close_tab_keybinding[prop] !== event[prop]) triggered = false;
+ if (triggered) electron.ipcRenderer.sendToHost('enhancer:close-tab');
+ }
});
const attempt_interval = setInterval(enhance, 500);
@@ -29,18 +79,19 @@ module.exports = (store, __exports) => {
return;
clearInterval(attempt_interval);
- // scrollbars
+ // toggleable styles
if (store().smooth_scrollbars)
document.body.classList.add('smooth-scrollbars');
+ if (store().snappy_transitions)
+ document.body.classList.add('snappy-transitions');
// frameless
- if (store().frameless && !store().tiling_mode) {
+ if (store().frameless && !store().tiling_mode && !tabsEnabled) {
document.body.classList.add('frameless');
// draggable area
- const dragarea = helpers.createElement(
- '
'
- );
- document.querySelector('.notion-topbar').prepend(dragarea);
+ document
+ .querySelector('.notion-topbar')
+ .prepend(helpers.createElement('
'));
document.documentElement.style.setProperty(
'--configured--dragarea_height',
`${store().dragarea_height + 2}px`
@@ -48,10 +99,12 @@ module.exports = (store, __exports) => {
}
// window buttons
- const buttons = require('./buttons.js')(store);
- document
- .querySelector('.notion-topbar > div[style*="display: flex"]')
- .appendChild(buttons.element);
+ if (!tabsEnabled) {
+ 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(
@@ -66,7 +119,7 @@ module.exports = (store, __exports) => {
document.querySelector('.notion-app-inner')
).getPropertyValue(prop);
- // ctrl+f theming
+ // external theming
document.defaultView.addEventListener('keydown', (event) => {
if ((event.ctrlKey || event.metaKey) && event.key === 'f') {
notionIpc.sendNotionToIndex('search:set-theme', {
@@ -95,10 +148,9 @@ module.exports = (store, __exports) => {
}
});
- // enhancer menu
function setThemeVars() {
electron.ipcRenderer.send(
- 'enhancer:set-theme-vars',
+ 'enhancer:set-menu-theme',
[
'--theme--main',
'--theme--sidebar',
@@ -115,6 +167,7 @@ module.exports = (store, __exports) => {
'--theme--interactive_hover-border',
'--theme--button_close',
'--theme--button_close-fill',
+ '--theme--selected',
'--theme--primary',
'--theme--primary_click',
'--theme--option-color',
@@ -132,40 +185,77 @@ module.exports = (store, __exports) => {
'--theme--select_red',
'--theme--line_text',
'--theme--line_yellow',
+ '--theme--line_yellow-text',
'--theme--line_green',
+ '--theme--line_green-text',
'--theme--line_blue',
+ '--theme--line_blue-text',
'--theme--line_red',
+ '--theme--line_red-text',
'--theme--code_inline-text',
'--theme--code_inline-background',
].map((rule) => [rule, getStyle(rule)])
);
- }
- setThemeVars();
- const theme_observer = new MutationObserver(setThemeVars);
- theme_observer.observe(document.querySelector('.notion-app-inner'), {
- attributes: true,
- });
- electron.ipcRenderer.on('enhancer:get-theme-vars', setThemeVars);
-
- const sidebar_observer = new MutationObserver(setSidebarWidth);
- sidebar_observer.observe(document.querySelector('.notion-sidebar'), {
- attributes: true,
- });
- let sidebar_width;
- function setSidebarWidth(list) {
- if (!store().frameless && store().tiling_mode) return;
- const new_sidebar_width =
- list[0].target.style.height === 'auto'
- ? '0px'
- : list[0].target.style.width;
- if (new_sidebar_width !== sidebar_width) {
- sidebar_width = new_sidebar_width;
+ if (tabsEnabled) {
electron.ipcRenderer.sendToHost(
- 'enhancer:sidebar-width',
- sidebar_width
+ 'enhancer:set-tab-theme',
+ [
+ '--theme--main',
+ '--theme--dragarea',
+ '--theme--font_sans',
+ '--theme--table-border',
+ '--theme--interactive_hover',
+ '--theme--interactive_hover-border',
+ '--theme--button_close',
+ '--theme--button_close-fill',
+ '--theme--option_active-background',
+ '--theme--selected',
+ '--theme--text',
+ ].map((rule) => [rule, getStyle(rule)])
);
}
}
- setSidebarWidth([{ target: document.querySelector('.notion-sidebar') }]);
+ setThemeVars();
+ new MutationObserver(setThemeVars).observe(
+ document.querySelector('.notion-app-inner'),
+ { attributes: true }
+ );
+ electron.ipcRenderer.on('enhancer:get-menu-theme', setThemeVars);
+
+ if (tabsEnabled) {
+ let tab_title = '';
+ __electronApi.setWindowTitle = (title) => {
+ if (tab_title !== title) {
+ tab_title = title;
+ electron.ipcRenderer.sendToHost('enhancer:set-tab-title', title);
+ }
+ };
+ __electronApi.openInNewWindow = (urlPath) => {
+ electron.ipcRenderer.sendToHost(
+ 'enhancer:new-tab',
+ `notion://www.notion.so${urlPath}`
+ );
+ };
+ } else if (store().frameless && !store().tiling_mode) {
+ let sidebar_width;
+ function setSidebarWidth(list) {
+ const new_sidebar_width =
+ list[0].target.style.height === 'auto'
+ ? '0px'
+ : list[0].target.style.width;
+ if (new_sidebar_width !== sidebar_width) {
+ sidebar_width = new_sidebar_width;
+ electron.ipcRenderer.sendToHost(
+ 'enhancer:sidebar-width',
+ sidebar_width
+ );
+ }
+ }
+ new MutationObserver(setSidebarWidth).observe(
+ document.querySelector('.notion-sidebar'),
+ { attributes: true }
+ );
+ setSidebarWidth([{ target: document.querySelector('.notion-sidebar') }]);
+ }
}
};
diff --git a/mods/core/create.js b/mods/core/createWindow.js
similarity index 100%
rename from mods/core/create.js
rename to mods/core/createWindow.js
diff --git a/mods/core/css/buttons.css b/mods/core/css/buttons.css
index ac3cacc..70b8465 100644
--- a/mods/core/css/buttons.css
+++ b/mods/core/css/buttons.css
@@ -37,9 +37,7 @@
background: var(--theme--interactive_hover);
box-shadow: 0 0 0 0.5px var(--theme--interactive_hover-border);
}
-.window-button#btn-close:hover {
+.window-button.btn-close:hover {
background: var(--theme--button_close);
-}
-.window-button#btn-close:hover svg line {
- stroke: var(--theme--button_close-fill);
+ color: var(--theme--button_close-fill);
}
diff --git a/mods/core/css/menu.css b/mods/core/css/menu.css
index 9bb5c5d..1f36cf7 100644
--- a/mods/core/css/menu.css
+++ b/mods/core/css/menu.css
@@ -50,11 +50,11 @@ body:not([style]) > * {
body:not([style])::after {
content: '';
position: absolute;
- left: 44vw;
- top: calc(50% - 7.5vw);
- width: 10vw;
- height: 10vw;
- border: 4px solid rgb(34, 34, 34);
+ left: calc(50% - 13px);
+ top: calc(50% + 10px);
+ width: 18px;
+ height: 18px;
+ border: 4px solid rgb(34, 34, 34, 0.5);
border-top-color: transparent;
border-radius: 50%;
animation: spin 0.8s linear infinite;
@@ -93,7 +93,7 @@ s {
/* titlebar */
-#menu-titlebar::before {
+#titlebar::before {
content: '';
position: absolute;
width: 100%;
@@ -103,20 +103,18 @@ s {
height: 2px;
}
-#menu-titlebar {
+#titlebar {
display: flex;
-webkit-app-region: drag;
-}
-#menu-titlebar button {
- -webkit-app-region: no-drag;
-}
-#menu-titlebar {
background: var(--theme--dragarea);
}
-#menu-titlebar > .window-buttons-area {
+#titlebar button {
+ -webkit-app-region: no-drag;
+}
+#titlebar .window-buttons-area {
margin: 0.4em 0.4em 0.4em auto;
}
-#menu-titlebar > .window-buttons-area:empty {
+#titlebar .window-buttons-area:empty {
display: none;
}
@@ -148,6 +146,7 @@ s {
color: var(--theme--select_red);
}
#alerts .error {
+ color: var(--theme--line_red-text);
background: var(--theme--line_red);
border-color: var(--theme--select_red);
}
@@ -155,6 +154,7 @@ s {
color: var(--theme--select_yellow);
}
#alerts .warning {
+ color: var(--theme--line_yellow-text);
background: var(--theme--line_yellow);
border-color: var(--theme--select_yellow);
}
@@ -162,6 +162,7 @@ s {
color: var(--theme--select_blue);
}
#alerts .info {
+ color: var(--theme--line_blue-text);
background: var(--theme--line_blue);
border-color: var(--theme--select_blue);
}
@@ -170,6 +171,7 @@ s {
color: var(--theme--select_green);
}
#alerts .success {
+ color: var(--theme--line_green-text);
background: var(--theme--line_green);
border-color: var(--theme--select_green);
}
@@ -231,7 +233,7 @@ s {
background: var(--theme--option-background);
color: var(--theme--option-color);
border-radius: 2px;
- transition: color 200ms, background 200ms;
+ transition: color 200ms, background 200ms, opacity 200ms;
user-select: none;
}
#search #tags > span:not(:last-child) {
@@ -254,6 +256,9 @@ s {
/* module meta */
+#modules {
+ position: relative;
+}
#modules section {
background: var(--theme--sidebar);
border: 1px solid var(--theme--table-border);
@@ -589,3 +594,65 @@ s {
height: 132.5px;
}
}
+
+/* draggable re-ordering of mods */
+
+#draggable-toggle {
+ background: none;
+ border: none;
+ margin-top: 0.8em;
+ padding-left: 0;
+ cursor: pointer;
+ color: var(--theme--text_ui);
+}
+
+[data-bolded] {
+ display: inline-flex;
+ flex-direction: column;
+}
+[data-bolded]::after {
+ content: attr(data-bolded);
+ height: 0;
+ visibility: hidden;
+ overflow: hidden;
+ user-select: none;
+ pointer-events: none;
+ font-weight: bold;
+}
+
+.reorder #search #tags > span,
+.reorder #search #tags > span:hover {
+ opacity: 0.7;
+ background: var(--theme--option-background);
+}
+.reorder #search #tags > .selected,
+.reorder #search #tags > .selected:hover {
+ background: var(--tag_color, var(--theme--option_active-background));
+}
+
+.reorder #modules .dragged-over::after {
+ content: '';
+ height: 0.25em;
+ width: 99%;
+ position: absolute;
+ margin: 0.3em 0;
+ opacity: 0.7;
+ background: var(--theme--selected);
+}
+
+.reorder #modules .switch,
+.reorder #modules .tags,
+.reorder #modules .desc,
+.reorder #modules .options,
+.reorder #modules .author,
+.reorder #modules .version {
+ display: none;
+}
+.reorder #modules label {
+ cursor: pointer;
+}
+.reorder #modules label::before {
+ content: '::';
+ margin-right: 0.4em;
+ color: var(--theme--text_ui);
+}
diff --git a/mods/core/css/responsive.css b/mods/core/css/responsive.css
new file mode 100644
index 0000000..0b92c03
--- /dev/null
+++ b/mods/core/css/responsive.css
@@ -0,0 +1,26 @@
+/*
+ * notion-enhancer
+ * (c) 2020 dragonwocky (https://dragonwocky.me/)
+ * under the MIT license
+ */
+
+@media (max-width: 600px) {
+ .notion-column_list-block [style='display: flex;'] > div {
+ width: 100% !important;
+ }
+ .notion-column_list-block [style='display: flex;'] {
+ flex-direction: column !important;
+ }
+
+ .notion-app-inner {
+ --theme_dark--page_normal-width: 100%;
+ --theme_dark--page-padding: calc(48px + env(safe-area-inset-left));
+ --theme_light--page_normal-width: 100%;
+ --theme_light--page-padding: calc(48px + env(safe-area-inset-left));
+ }
+}
+
+.snappy-transitions * {
+ animation-duration: 0s !important;
+ transition-duration: 0s !important;
+}
diff --git a/mods/core/css/scrollbars.css b/mods/core/css/scrollbars.css
index 2525fb5..2286f9a 100644
--- a/mods/core/css/scrollbars.css
+++ b/mods/core/css/scrollbars.css
@@ -11,6 +11,7 @@
.smooth-scrollbars ::-webkit-scrollbar {
width: 8px; /* vertical */
height: 8px; /* horizontal */
+ -webkit-app-region: no-drag;
}
.smooth-scrollbars ::-webkit-scrollbar-corner {
background-color: transparent; /* overlap */
diff --git a/mods/core/css/tabs.css b/mods/core/css/tabs.css
new file mode 100644
index 0000000..1e38668
--- /dev/null
+++ b/mods/core/css/tabs.css
@@ -0,0 +1,189 @@
+/*
+ * notion-enhancer
+ * (c) 2020 dragonwocky (https://dragonwocky.me/)
+ * under the MIT license
+ */
+
+@import './buttons.css';
+
+* {
+ box-sizing: border-box;
+ word-break: break-word;
+ text-decoration: none;
+ text-size-adjust: 100%;
+ font-family: var(--theme--font_sans) !important;
+ outline-color: var(--theme--table-border);
+}
+
+@keyframes spin {
+ from {
+ transform: rotate(0deg);
+ }
+ to {
+ transform: rotate(360deg);
+ }
+}
+@keyframes tabSlide {
+ from {
+ width: 0;
+ }
+ to {
+ width: 8.5em;
+ }
+}
+
+body:not([style*='--theme']):not(.error) > * {
+ opacity: 0;
+}
+body:not([style*='--theme']):not(.error)::after {
+ content: '';
+ position: absolute;
+ left: calc(50% - 15px);
+ top: calc(50% + 10px);
+ width: 18px;
+ height: 18px;
+ border: 4px solid rgb(34, 34, 34, 0.5);
+ border-top-color: transparent;
+ border-radius: 50%;
+ animation: spin 0.8s linear infinite;
+}
+body[style*='--theme']::after {
+ z-index: 1;
+ content: '';
+ position: absolute;
+ left: calc(50% - 15px);
+ top: calc(50% + 10px);
+ width: 18px;
+ height: 18px;
+ opacity: 0.5;
+ border: 4px solid var(--theme--text);
+ border-top-color: transparent;
+ border-radius: 50%;
+ animation: spin 0.8s linear infinite;
+}
+
+html,
+body,
+#root {
+ background: var(--theme--main) !important;
+ position: relative;
+ height: 100%;
+ margin: 0;
+}
+#root {
+ display: flex;
+ flex-direction: column;
+}
+
+#titlebar::before {
+ content: '';
+ position: absolute;
+ width: 100%;
+ -webkit-app-region: no-drag;
+ top: 0;
+ left: 0;
+ height: 2px;
+}
+#titlebar {
+ display: flex;
+ flex-shrink: 1;
+ user-select: none;
+ -webkit-app-region: drag;
+ background: var(--theme--dragarea);
+}
+#titlebar button {
+ color: var(--theme--text);
+ -webkit-app-region: no-drag;
+ border: none;
+ background: transparent;
+}
+#titlebar .window-buttons-area {
+ margin: 0.5em 0.55em 0.5em auto;
+}
+#titlebar .window-buttons-area:empty {
+ display: none;
+}
+
+#open-enhancer-menu::before {
+ content: '';
+ height: 1.25em;
+ width: 1.25em;
+ display: inline-block;
+ margin: auto 1em -0.25em 1em;
+ background-size: contain;
+ background-image: url('enhancement://core/icons/mac+linux.png');
+ background-repeat: no-repeat;
+}
+#tabs {
+ margin-top: auto;
+}
+#tabs .tab {
+ display: inline-flex;
+ background: var(--theme--main);
+ border: none;
+ font-size: 1.15em;
+ padding: 0.2em 0.4em;
+ text-align: left;
+ border-bottom: 4px solid var(--theme--table-border);
+ opacity: 0.8;
+}
+#tabs .tab:first-child {
+ margin-top: 0.5em;
+}
+#tabs .tab:not(.new) span:not(.close) {
+ width: 8.5em;
+ margin-right: 4px;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
+#tabs .tab.slideIn span:not(.close) {
+ animation: tabSlide 100ms ease-in-out;
+}
+#tabs .tab.slideOut {
+ width: 0;
+ animation: tabSlide 100ms ease-in-out reverse;
+}
+#tabs .tab .close {
+ padding: 0 0.35em 0.1em 0.3em;
+ margin-left: auto;
+ font-weight: bold;
+}
+#tabs .tab.current {
+ opacity: 1;
+ background: var(--theme--selected);
+ border-bottom: 4px solid var(--theme--option_active-background);
+}
+#tabs .tab.new {
+ background: none;
+ border: none;
+ margin-left: -0.1em;
+}
+#tabs .tab.new span {
+ padding: 0 0.35em 0.1em 0.3em;
+ font-weight: bold;
+}
+#tabs .tab:hover {
+ opacity: 1;
+}
+#tabs .tab .close:hover,
+#tabs .tab.new span:hover,
+#titlebar .window-button:hover {
+ border-radius: 4px;
+ background: var(--theme--table-border);
+ box-shadow: 0 0 0 0.5px var(--theme--interactive_hover-border);
+}
+#titlebar .window-button.btn-close:hover {
+ background: var(--theme--button_close);
+ color: var(--theme--button_close-fill);
+}
+#tabs .tab.dragged-over {
+ box-shadow: inset 4px 0 0 0 var(--theme--selected);
+}
+
+.notion {
+ z-index: 2;
+ width: 100%;
+ height: 100%;
+ display: none;
+}
diff --git a/mods/core/css/theme.css b/mods/core/css/theme.css
index 052c6c0..dc1bb30 100644
--- a/mods/core/css/theme.css
+++ b/mods/core/css/theme.css
@@ -9,20 +9,25 @@
/** app **/
+.notion-body,
+.notion-body.dark [style*='background: rgb(47, 52, 55)'],
+.notion-body.dark [style*='background-color: rgb(47, 52, 55)'],
+.notion-body:not(.dark)
+ .notion-light-theme
+ [style*='background: white']:not(.notion-help-button),
+.notion-body:not(.dark)
+ .notion-dark-theme
+ [style*='background: white']:not(.notion-help-button):not([style*='box-shadow: rgba(15, 15, 15, 0.05) 0px 0px 0px 1px, rgba(15, 15, 15, 0.1) 0px 3px 6px, rgba(15, 15, 15, 0.2) 0px 9px 24px;']),
+.notion-body:not(.dark) [style*='background-color: white'] {
+ background: var(--theme--main) !important;
+}
+.notion-sidebar > div,
.notion-body.dark [style*='background: rgb(55, 60, 63)'],
.notion-body.dark [style*='background: rgb(120, 123, 123)'],
.notion-body:not(.dark) [style*='background: rgb(247, 246, 243)'],
.notion-body:not(.dark) [style*='background: rgb(223, 223, 222)'] {
background: var(--theme--sidebar) !important;
}
-.notion-body,
-.notion-body.dark [style*='background: rgb(47, 52, 55)'],
-.notion-body.dark [style*='background-color: rgb(47, 52, 55)'],
-.notion-body:not(.dark)
- [style*='background: white']:not(.notion-help-button):not([style*='box-shadow: rgba(15, 15, 15, 0.05) 0px 0px 0px 1px, rgba(15, 15, 15, 0.1) 0px 3px 6px, rgba(15, 15, 15, 0.2) 0px 9px 24px;']),
-.notion-body:not(.dark) [style*='background-color: white'] {
- background: var(--theme--main) !important;
-}
[style*='background: rgba(15, 15, 15, 0.6)'] {
background: var(--theme--overlay) !important;
}
@@ -40,6 +45,12 @@
width: var(--theme--page_normal-width) !important;
}
+.notion-frame
+ [style*='padding-left: calc(96px + env(safe-area-inset-left)); padding-right: calc(96px + env(safe-area-inset-right));'] {
+ padding-left: var(--theme--page-padding) !important;
+ padding-right: var(--theme--page-padding) !important;
+}
+
.notion-page-content [data-block-id][style*='max-width'] {
max-width: 100% !important;
}
@@ -141,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;
@@ -161,14 +173,19 @@
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-overlay-container
+ .notion-scroller.vertical
.notion-page-content[style*='font-size: 14px'] {
font-size: var(--theme--font_body-size_small) !important;
}
@@ -179,6 +196,13 @@
font-size: var(--theme--font_sidebar-size) !important;
}
+/** text-block readability **/
+
+.notion-selectable.notion-text-block {
+ line-height: var(--theme--text-block_line-height) !important;
+ margin-top: var(--theme--text-block_margin-top) !important;
+}
+
/** databases **/
.notion-body.dark [style*='background: rgb(63, 68, 71)'],
@@ -189,7 +213,8 @@
> a[style*='background: white'],
.notion-body:not(.dark) [style*='background: rgb(247, 246, 243)'],
.notion-body:not(.dark)
- [style*='box-shadow: rgba(15, 15, 15, 0.05) 0px 0px 0px 1px, rgba(15, 15, 15, 0.1) 0px 3px 6px, rgba(15, 15, 15, 0.2) 0px 9px 24px;'] {
+ .notion-dark-theme
+ [style*='background: white'][style*='box-shadow: rgba(15, 15, 15, 0.05) 0px 0px 0px 1px, rgba(15, 15, 15, 0.1) 0px 3px 6px, rgba(15, 15, 15, 0.2) 0px 9px 24px;'] {
background: var(--theme--card) !important;
}
.notion-body.dark
@@ -200,17 +225,36 @@
[style*='background: rgba(55, 53, 47, 0.024)'] {
background: var(--theme--gallery) !important;
}
+.notion-body.dark .notion-scroller > [style*='rgb(55, 60, 63)'],
+.notion-body:not(.dark) [style*='background: rgba(242, 241, 238, 0.6)'] {
+ background: var(--theme--select_input) !important;
+}
.notion-body.dark
- [style*='box-shadow: rgba(15, 15, 15, 0.2) 0px 0px 0px 1px, rgba(15, 15, 15, 0.2) 0px 2px 4px'],
-.notion-body:not(.dark) [style*='box-shadow: white -3px 0px 0px'] {
- box-shadow: rgba(15, 15, 15, 0.1) 0px 0px 0px 1px,
- rgba(15, 15, 15, 0.1) 0px 2px 4px !important;
+ [style*='box-shadow: rgba(255, 255, 255, 0.14) 0px -1px inset;'],
+.notion-body:not(.dark)
+ [style*='box-shadow: rgba(55, 53, 47, 0.16) 0px -1px 0px inset'] {
+ box-shadow: rgba(55, 53, 47, 0.16) 0px -1px inset !important;
+}
+
+.notion-body.dark [style*='box-shadow: rgba(255, 255, 255, 0.07) 0px 1px 0px'],
+.notion-body:not(.dark)
+ [style*='box-shadow: rgba(55, 53, 47, 0.09) 0px 1px 0px'] {
+ box-shadow: var(--theme--ui-border) 0px 1px 0px !important;
+}
+.notion-body.dark
+ [style*='box-shadow: rgba(255, 255, 255, 0.14) 0px 1px 0px inset'],
+.notion-body:not(.dark)
+ [style*='box-shadow: rgba(55, 53, 47, 0.16) 0px 1px 0px inset'] {
+ box-shadow: var(--theme--table-border) 0px 1px 0px inset !important;
}
.notion-body.dark [style*='box-shadow: rgb(47, 52, 55) -3px 0px 0px'] {
box-shadow: var(--theme--main) -3px 0px 0px !important;
}
+.notion-body:not(.dark) [style*='box-shadow: white -3px 0px 0px;'] {
+ box-shadow: none !important;
+}
.notion-body.dark
[style*='box-shadow: rgb(47, 52, 55) -3px 0px 0px, rgba(255, 255, 255, 0.14) 0px 1px 0px'],
.notion-body:not(.dark)
@@ -218,7 +262,7 @@
.notion-body:not(.dark)
[style*='box-shadow: rgba(255, 255, 255, 0.07) 0px -1px 0px'] {
box-shadow: var(--theme--main) -3px 0px 0px,
- var(--theme--table-border) 0px 1px 0px !important;
+ var(--theme--ui-border) 0px 1px 0px !important;
}
.notion-body.dark [style*='border-top: 1px solid rgba(255, 255, 255,'],
@@ -246,7 +290,7 @@
.notion-body.dark [style*='box-shadow: rgba(55, 53, 47, 0.09) 0px -1px 0px'],
.notion-body:not(.dark)
[style*='box-shadow: rgba(55, 53, 47, 0.09) 0px -1px 0px'] {
- box-shadow: var(--theme--table-border) 0px -1px 0px !important;
+ box-shadow: var(--theme--ui-border) 0px -1px 0px !important;
}
.notion-body.dark [style*='border-left: 1px solid rgba(255, 255, 255,'],
.notion-body.dark
@@ -255,12 +299,6 @@
.notion-body:not(.dark) [style*='border-left: 1px solid rgba(55, 53, 47,'] {
border-left: 1px solid var(--theme--table-border) !important;
}
-.notion-body.dark
- [style*='box-shadow: rgba(255, 255, 255, 0.14) 0px 1px 0px inset'],
-.notion-body:not(.dark)
- [style*='box-shadow: rgba(55, 53, 47, 0.16) 0px 1px 0px inset'] {
- box-shadow: var(--theme--table-border) 0px 1px 0px inset !important;
-}
.notion-body.dark
[style*='box-shadow: rgba(255, 255, 255, 0.14) 1px 0px 0px inset'],
.notion-body:not(.dark)
@@ -288,6 +326,7 @@
.notion-body.dark [style*='background: rgb(71, 76, 80)'],
.notion-body.dark [style*='background: rgb(80, 85, 88)'],
.notion-body.dark [style*='background: rgb(98, 102, 104)'],
+.notion-body.dark [style*='height: 1px; background: rgba(255, 255, 255, 0.07)'],
.notion-body:not(.dark) [style*='background: rgba(55, 53, 47,'],
.notion-body:not(.dark) [style*='background: rgb(239, 239, 238)'],
.notion-body:not(.dark) [style*='background: rgba(206, 205, 202, 0.5)'] {
@@ -296,7 +335,8 @@
}
/* normalise inline-table size */
-.notion-page-content .notion-collection_view-block {
+.notion-page-content .notion-collection_view-block[style*=' width'],
+.notion-page-content .notion-collection_view-block[style^='width'] {
width: 100% !important;
}
.notion-page-content
@@ -363,7 +403,8 @@
background: var(--theme--selected) !important;
}
-[style*=' color: rgb(46, 170, 220)'] {
+[style*=' color: rgb(46, 170, 220)'],
+[style^='color: rgb(46, 170, 220)'] {
color: var(--theme--primary) !important;
}
[style*='fill: rgb(46, 170, 220)'] {
@@ -387,6 +428,19 @@
background: var(--theme--primary_indicator) !important;
}
+.notion-body.dark
+ [style*='box-shadow: rgba(15, 15, 15, 0.1) 0px 0px 0px 1px, rgba(15, 15, 15, 0.2) 0px 3px 6px, rgba(15, 15, 15, 0.4) 0px 9px 24px'],
+.notion-body:not(.dark)
+ [style*='box-shadow: rgba(15, 15, 15, 0.05) 0px 0px 0px 1px, rgba(15, 15, 15, 0.1) 0px 3px 6px, rgba(15, 15, 15, 0.2) 0px 9px 24px'] {
+ box-shadow: var(--theme--box-shadow_strong) !important;
+}
+.notion-body.dark
+ [style*='box-shadow: rgba(15, 15, 15, 0.2) 0px 0px 0px 1px, rgba(15, 15, 15, 0.2) 0px 2px 4px'],
+.notion-body:not(.dark)
+ [style*='box-shadow: rgba(15, 15, 15, 0.1) 0px 0px 0px 1px, rgba(15, 15, 15, 0.1) 0px 2px 4px'] {
+ box-shadow: var(--theme--box-shadow) !important;
+}
+
.notion-to_do-block > div [role='button']:hover,
.notion-to_do-block > div [role='button']:hover .checkboxSquare,
.notion-to_do-block > div [role='button']:hover .check {
@@ -422,11 +476,13 @@
/** content colours **/
.notion-body,
-.notion-page-content [style*='color: inherit;'],
.notion-frame .notion-page-block,
.notion-body.dark [style*=' color: rgba(255, 255, 255, 0.9)'],
-.notion-body.dark [style*='color: rgba(255, 255, 255, 0.7)'],
-.notion-body:not(.dark) [style*=' color: rgb(55, 53, 47);'] {
+.notion-body.dark [style^='color: rgba(255, 255, 255, 0.9)'],
+.notion-body.dark [style*=' color: rgba(255, 255, 255, 0.7)'],
+.notion-body.dark [style^='color: rgba(255, 255, 255, 0.7)'],
+.notion-body:not(.dark) [style*=' color: rgb(55, 53, 47);'],
+.notion-body:not(.dark) [style^='color: rgb(55, 53, 47);'] {
color: var(--theme--text) !important;
}
.notion-body.dark [style*='color: rgba(255, 255, 255, 0.6)'],
@@ -434,18 +490,38 @@
.notion-body:not(.dark) [style*='color: rgba(25, 23, 17, 0.6)'] {
color: var(--theme--text_ui) !important;
}
+::placeholder {
+ opacity: 1 !important;
+}
+::placeholder,
+[style*='-webkit-text-fill-color:'],
.notion-body.dark [style*='color: rgba(255, 255, 255, 0.4)'],
-.notion-body:not(.dark) [style*='color: rgba(55, 53, 47, 0.4)'] {
+.notion-body.dark [style*='color: rgba(255, 255, 255, 0.4)']::before,
+.notion-body:not(.dark) [style*='color: rgba(55, 53, 47, 0.4)'],
+.notion-body:not(.dark) [style*='color: rgba(55, 53, 47, 0.4)']::before {
color: var(--theme--text_ui_info) !important;
+ -webkit-text-fill-color: var(--theme--text_ui_info) !important;
}
.notion-body.dark [style*='fill: rgb(202, 204, 206)'] {
fill: var(--theme--text) !important;
}
-.notion-body.dark [style*='fill: rgba(202, 204, 206,'],
+
+.notion-body.dark [style*='fill: rgba(255, 255, 255, 0.6)'],
.notion-body:not(.dark) [style*='fill: rgba(55, 53, 47, 0.8)'],
-.notion-body:not(.dark) [style*='fill: rgba(55, 53, 47,'] {
+.notion-body:not(.dark) [style*='fill: rgba(55, 53, 47, 0.6)'],
+.notion-body:not(.dark) [style*='fill: rgba(25, 23, 17, 0.6)'] {
fill: var(--theme--text_ui) !important;
}
+.notion-body.dark [style*='fill: rgba(202, 204, 206, 0.6)'],
+.notion-body.dark [style*='fill: rgba(202, 204, 206, 0.4)'],
+.notion-body:not(.dark) [style*='fill: rgba(55, 53, 47, 0.4)'],
+.notion-body:not(.dark) [style*='fill: rgba(55, 53, 47, 0.3)'] {
+ fill: var(--theme--text_ui_info) !important;
+}
+.notion-body.dark [style*='border-color:rgba(255,255,255,0.4);opacity:0.7'],
+.notion-body:not(.dark) [style*='border-color:rgba(55,53,47,0.4);opacity:0.7'] {
+ border-color: var(--theme--text_ui_info) !important;
+}
.notion-body.dark [style*='caret-color: rgba(255, 255, 255, 0.9)'],
.notion-body:not(.dark) [style*='caret-color: rgb(55, 53, 47)'] {
caret-color: var(--theme--text) !important;
@@ -487,7 +563,7 @@
.notion-body:not(.dark)
[style*='color: rgb(100, 71, 58); fill: rgb(100, 71, 58);'] {
fill: var(--theme--text_brown) !important;
- color: var(--theme--text_brown-text) !important;
+ color: var(--theme--text_brown) !important;
}
.notion-body.dark [style*='background: rgba(147, 114, 100, 0.5)'],
.notion-body:not(.dark) [style*='background: rgba(140, 46, 0, 0.2)'] {
diff --git a/mods/core/css/titlebar.css b/mods/core/css/titlebar.css
index 0fd160f..9ab225c 100644
--- a/mods/core/css/titlebar.css
+++ b/mods/core/css/titlebar.css
@@ -8,19 +8,23 @@
@import './buttons.css';
.frameless .notion-topbar {
- height: calc(var(--configured--dragarea_height, 10px) + 45px) !important;
+ height: calc(var(--configured--dragarea_height, 15px) + 45px) !important;
}
.frameless .window-dragarea {
- height: var(--configured--dragarea_height, 10px);
+ height: var(--configured--dragarea_height, 15px);
width: 100%;
}
.frameless .window-dragarea {
background: var(--theme--dragarea);
}
+.frameless [style*='top: 10.4972px'] {
+ top: calc(10.4972px + var(--configured--dragarea_height, 15px)) !important;
+}
+
@media (max-width: 760px) {
.frameless .notion-topbar {
- height: calc(var(--configured--dragarea_height, 10px) + 80px) !important;
+ height: calc(var(--configured--dragarea_height, 15px) + 80px) !important;
}
.frameless .notion-topbar > :nth-child(2) {
height: 80px !important;
diff --git a/mods/core/css/variables.css b/mods/core/css/variables.css
index 225fdd3..b23f538 100644
--- a/mods/core/css/variables.css
+++ b/mods/core/css/variables.css
@@ -14,12 +14,17 @@
--theme_dark--sidebar: rgb(55, 60, 63);
--theme_dark--overlay: rgba(15, 15, 15, 0.6);
--theme_dark--dragarea: #272d2f;
+ --theme_dark--box-shadow: rgba(15, 15, 15, 0.2) 0px 0px 0px 1px,
+ rgba(15, 15, 15, 0.2) 0px 2px 4px;
+ --theme_dark--box-shadow_strong: rgba(15, 15, 15, 0.1) 0px 0px 0px 1px,
+ rgba(15, 15, 15, 0.2) 0px 3px 6px, rgba(15, 15, 15, 0.4) 0px 9px 24px;
--theme_dark--page_normal-width: 900px;
--theme_dark--page_full-width: 100%;
+ --theme_dark--page-padding: calc(96px + env(safe-area-inset-left));
+ --theme_dark--page_banner-height: 30vh;
--theme_dark--preview-width: 977px;
--theme_dark--preview-padding: 8rem;
--theme_dark--preview_banner-height: 20vh;
- --theme_dark--page_banner-height: 30vh;
--theme_dark--font_sans: -apple-system, BlinkMacSystemFont, 'Segoe UI',
Helvetica, 'Apple Color Emoji', Arial, sans-serif, 'Segoe UI Emoji',
@@ -40,6 +45,9 @@
--theme_dark--font_body-size_small: 14px;
--theme_dark--font_code-size: 0.796875em;
--theme_dark--font_sidebar-size: 14px;
+
+ --theme_dark--text-block_line-height: 1.5;
+ --theme_dark--text-block_margin-top: 1px;
--theme_dark--scrollbar: #505457;
--theme_dark--scrollbar-border: transparent;
@@ -47,7 +55,9 @@
--theme_dark--card: rgb(63, 68, 71);
--theme_dark--gallery: rgba(255, 255, 255, 0.05);
+ --theme_dark--select_input: rgb(55, 60, 63);
--theme_dark--table-border: rgba(255, 255, 255, 0.1);
+ --theme_dark--ui-border: rgba(255, 255, 255, 0.07);
--theme_dark--interactive_hover: rgb(71, 76, 80);
--theme_dark--interactive_hover-border: transparent;
--theme_dark--button_close: #e81123;
@@ -188,12 +198,17 @@
--theme_light--sidebar: rgb(247, 246, 243);
--theme_light--overlay: rgba(15, 15, 15, 0.6);
--theme_light--dragarea: rgba(55, 53, 47, 0.04);
+ --theme_light--box-shadow: rgba(15, 15, 15, 0.1) 0px 0px 0px 1px,
+ rgba(15, 15, 15, 0.1) 0px 2px 4px;
+ --theme_light--box-shadow_strong: rgba(15, 15, 15, 0.05) 0px 0px 0px 1px,
+ rgba(15, 15, 15, 0.1) 0px 3px 6px, rgba(15, 15, 15, 0.2) 0px 9px 24px;
--theme_light--page_normal-width: 900px;
--theme_light--page_full-width: 100%;
+ --theme_light--page-padding: calc(96px + env(safe-area-inset-left));
+ --theme_light--page_banner-height: 30vh;
--theme_light--preview-width: 977px;
--theme_light--preview-padding: 8rem;
--theme_light--preview_banner-height: 20vh;
- --theme_light--page_banner-height: 30vh;
--theme_light--font_sans: -apple-system, BlinkMacSystemFont, 'Segoe UI',
Helvetica, 'Apple Color Emoji', Arial, sans-serif, 'Segoe UI Emoji',
@@ -214,6 +229,9 @@
--theme_light--font_body-size_small: 14px;
--theme_light--font_code-size: 0.796875em;
--theme_light--font_sidebar-size: 14px;
+
+ --theme_light--text-block_line-height: 1.5;
+ --theme_light--text-block_margin-top: 1px;
--theme_light--scrollbar: #d9d8d6;
--theme_light--scrollbar-border: #cacac8;
@@ -221,7 +239,9 @@
--theme_light--card: rgb(247, 247, 247);
--theme_light--gallery: rgba(55, 53, 47, 0.024);
+ --theme_light--select_input: rgba(242, 241, 238, 0.6);
--theme_light--table-border: rgba(55, 53, 47, 0.16);
+ --theme_light--ui-border: rgba(55, 53, 47, 0.09);
--theme_light--interactive_hover: rgb(239, 239, 239);
--theme_light--interactive_hover-border: transparent;
--theme_light--button_close: #e81123;
@@ -245,6 +265,7 @@
--theme_light--text: rgb(55, 53, 47);
--theme_light--text_ui: rgba(55, 53, 47, 0.6);
+ --theme_light--text_ui: rgba(55, 53, 47, 0.6);
--theme_light--text_ui_info: rgba(55, 53, 47, 0.4);
--theme_light--text_gray: rgb(155, 154, 151);
@@ -362,12 +383,15 @@
--theme--sidebar: var(--theme_dark--sidebar);
--theme--overlay: var(--theme_dark--overlay);
--theme--dragarea: var(--theme_dark--dragarea);
+ --theme--box-shadow: var(--theme_dark--box-shadow);
+ --theme--box-shadow_strong: var(--theme_dark--box-shadow_strong);
--theme--page_normal-width: var(--theme_dark--page_normal-width);
--theme--page_full-width: var(--theme_dark--page_full-width);
+ --theme--page-padding: var(--theme_dark--page-padding);
+ --theme--page_banner-height: var(--theme_dark--page_banner-height);
--theme--preview-width: var(--theme_dark--preview-width);
--theme--preview-padding: var(--theme_dark--preview-padding);
--theme--preview_banner-height: var(--theme_dark--preview_banner-height);
- --theme--page_banner-height: var(--theme_dark--page_banner-height);
--theme--font_sans: var(--theme_dark--font_sans);
--theme--font_serif: var(--theme_dark--font_serif);
--theme--font_mono: var(--theme_dark--font_mono);
@@ -381,12 +405,16 @@
--theme--font_body-size_small: var(--theme_dark--font_body-size_small);
--theme--font_code-size: var(--theme_dark--font_code-size);
--theme--font_sidebar-size: var(--theme_dark--font_sidebar-size);
+ --theme--text-block_line-height: var(--theme_dark--text-block_line-height);
+ --theme--text-block_margin-top: var(--theme_dark--text-block_margin-top);
--theme--scrollbar: var(--theme_dark--scrollbar);
--theme--scrollbar-border: var(--theme_dark--scrollbar-border);
--theme--scrollbar_hover: var(--theme_dark--scrollbar_hover);
--theme--card: var(--theme_dark--card);
--theme--gallery: var(--theme_dark--gallery);
+ --theme--select_input: var(--theme_dark--select_input);
--theme--table-border: var(--theme_dark--table-border);
+ --theme--ui-border: var(--theme_dark--ui-border);
--theme--interactive_hover: var(--theme_dark--interactive_hover);
--theme--interactive_hover-border: var(
--theme_dark--interactive_hover-border
@@ -521,12 +549,15 @@
--theme--sidebar: var(--theme_light--sidebar);
--theme--overlay: var(--theme_light--overlay);
--theme--dragarea: var(--theme_light--dragarea);
- --theme--page_normal-width: var(--theme_dark--page_normal-width);
- --theme--page_full-width: var(--theme_dark--page_full-width);
+ --theme--box-shadow: var(--theme_light--box-shadow);
+ --theme--box-shadow_strong: var(--theme_light--box-shadow_strong);
+ --theme--page_normal-width: var(--theme_light--page_normal-width);
+ --theme--page_full-width: var(--theme_light--page_full-width);
+ --theme--page-padding: var(--theme_light--page-padding);
+ --theme--page_banner-height: var(--theme_light--page_banner-height);
--theme--preview-width: var(--theme_light--preview-width);
--theme--preview-padding: var(--theme_light--preview-padding);
--theme--preview_banner-height: var(--theme_light--preview_banner-height);
- --theme--page_banner-height: var(--theme_light--page_banner-height);
--theme--font_sans: var(--theme_light--font_sans);
--theme--font_serif: var(--theme_light--font_serif);
--theme--font_mono: var(--theme_light--font_mono);
@@ -540,12 +571,16 @@
--theme--font_body-size_small: var(--theme_light--font_body-size_small);
--theme--font_code-size: var(--theme_light--font_code-size);
--theme--font_sidebar-size: var(--theme_light--font_sidebar-size);
+ --theme--text-block_line-height: var(--theme_light--text-block_line-height);
+ --theme--text-block_margin-top: var(--theme_light--text-block_margin-top);
--theme--scrollbar: var(--theme_light--scrollbar);
--theme--scrollbar-border: var(--theme_light--scrollbar-border);
--theme--scrollbar_hover: var(--theme_light--scrollbar_hover);
--theme--card: var(--theme_light--card);
--theme--gallery: var(--theme_light--gallery);
+ --theme--select_input: var(--theme_light--select_input);
--theme--table-border: var(--theme_light--table-border);
+ --theme--ui-border: var(--theme_light--ui-border);
--theme--interactive_hover: var(--theme_light--interactive_hover);
--theme--interactive_hover-border: var(
--theme_light--interactive_hover-border
diff --git a/mods/core/menu.js b/mods/core/enhancerMenu.js
similarity index 67%
rename from mods/core/menu.js
rename to mods/core/enhancerMenu.js
index d839720..cdea17f 100644
--- a/mods/core/menu.js
+++ b/mods/core/enhancerMenu.js
@@ -7,57 +7,52 @@
'use strict';
const store = require('../../pkg/store.js'),
- { id } = require('./mod.js'),
helpers = require('../../pkg/helpers.js'),
fs = require('fs-extra'),
path = require('path'),
electron = require('electron'),
- browser = electron.remote.getCurrentWindow();
+ { 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: true,
+ tiling_mode: coreStore().tiling_mode,
+ frameless: coreStore().frameless,
}));
- document.querySelector('#menu-titlebar').appendChild(buttons.element);
+ 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-theme-vars');
- electron.ipcRenderer.on('enhancer:set-theme-vars', (event, theme) => {
+ electron.ipcRenderer.send('enhancer:get-menu-theme');
+ electron.ipcRenderer.on('enhancer:set-menu-theme', (event, theme) => {
for (const style of theme)
document.body.style.setProperty(style[0], style[1]);
});
@@ -121,32 +116,52 @@ 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.key === 'F5') location.reload();
+ // further-configuration popup
if (
$popup.classList.contains('visible') &&
- [13, 27].includes(event.keyCode)
+ ['Enter', 'Escape'].includes(event.key)
)
$popup.classList.remove('visible');
+ // close window on hotkey toggle
+ const hotkey = toKeyEvent(coreStore().menu_toggle);
+ let triggered = true;
+ for (let prop in hotkey)
+ if (hotkey[prop] !== event[prop]) triggered = false;
+ if (triggered || ((event.ctrlKey || event.metaKey) && event.key === 'w'))
+ 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')
@@ -159,7 +174,6 @@ window['__start'] = async () => {
store(colorpicker_target.id)[colorpicker_target.key] = color.css();
})
.update();
-
document
.querySelector('#colorpicker')
.appendChild(
@@ -184,12 +198,12 @@ window['__start'] = async () => {
};
function innerText(elem) {
let text = '';
- for (let node of elem.childNodes) {
- if (node.nodeType === 3) text += node.textContent;
- if (node.nodeType === 1)
- text += ['text', 'number'].includes(node.type)
- ? node.value
- : innerText(node);
+ for (let $node of elem.childNodes) {
+ if ($node.nodeType === 3) text += $node.textContent;
+ if ($node.nodeType === 1)
+ text += ['text', 'number'].includes($node.type)
+ ? $node.value
+ : innerText($node);
}
return text;
}
@@ -197,13 +211,15 @@ window['__start'] = async () => {
modules.loaded.forEach((mod) => {
const $search_input = document.querySelector('#search > input');
if (
- (mod.elem.classList.contains('enabled') && !search_filters.enabled) ||
- (mod.elem.classList.contains('disabled') && !search_filters.disabled) ||
- !mod.tags.some((tag) => search_filters.tags.has(tag)) ||
- ($search_input.value &&
- !innerText(mod.elem)
- .toLowerCase()
- .includes($search_input.value.toLowerCase().trim()))
+ !document.body.classList.contains('reorder') &&
+ ((mod.elem.classList.contains('enabled') && !search_filters.enabled) ||
+ (mod.elem.classList.contains('disabled') &&
+ !search_filters.disabled) ||
+ !mod.tags.some((tag) => search_filters.tags.has(tag)) ||
+ ($search_input.value &&
+ !innerText(mod.elem)
+ .toLowerCase()
+ .includes($search_input.value.toLowerCase().trim())))
)
return (mod.elem.style.display = 'none');
mod.elem.style.display = 'block';
@@ -223,21 +239,20 @@ window['__start'] = async () => {
);
document.querySelector('#tags').append(el);
el.addEventListener('click', (event) => {
- el.className = el.className === 'selected' ? '' : 'selected';
- onclick(el.className === 'selected');
+ if (!document.body.classList.contains('reorder')) {
+ el.className = el.className === 'selected' ? '' : 'selected';
+ onclick(el.className === 'selected');
+ }
});
return el;
}
- createTag(
- 'enabled',
- (state) => [(search_filters.enabled = state), search()]
- // 'var(--theme--bg_green)'
- );
- createTag(
- 'disabled',
- (state) => [(search_filters.disabled = state), search()]
- // 'var(--theme--bg_red)'
- );
+ createTag('enabled', (state) => [
+ ((search_filters.enabled = state), search()),
+ ]);
+ createTag('disabled', (state) => [
+ (search_filters.disabled = state),
+ search(),
+ ]);
for (let tag of search_filters.tags)
createTag(`#${tag}`, (state) => [
state ? search_filters.tags.add(tag) : search_filters.tags.delete(tag),
@@ -284,20 +299,20 @@ window['__start'] = async () => {
return parsed;
}
- let modified_notice;
+ let $modified_notice;
function modified() {
- if (modified_notice) return;
- modified_notice = createAlert(
+ if ($modified_notice) return;
+ $modified_notice = createAlert(
'info',
`changes may not fully apply until app relaunch .`
);
- modified_notice.el
+ $modified_notice.el
.querySelector('[data-relaunch]')
.addEventListener('click', (event) => {
electron.remote.app.relaunch();
electron.remote.app.quit();
});
- modified_notice.append();
+ $modified_notice.append();
}
const file_icon = await fs.readFile(
@@ -389,15 +404,8 @@ window['__start'] = async () => {
}
const $modules = document.querySelector('#modules');
- 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)
- )) {
+
+ for (let mod of modules.loaded) {
for (let fonts of mod.fonts || []) {
document
.querySelector('head')
@@ -417,37 +425,41 @@ window['__start'] = async () => {
avatar: `https://github.com/${mod.author}.png`,
};
mod.elem = helpers.createElement(`
-
+
+ ${
+ mod.options && mod.options.length
+ ? '
'
+ : ''
+ }
+
`);
const $enable = mod.elem.querySelector(`#enable_${mod.id}`);
if ($enable)
@@ -500,12 +512,102 @@ window['__start'] = async () => {
}
$options.appendChild($opt);
}
- $modules.append(mod.elem);
+ if (mod.tags.includes('core')) $modules.append(mod.elem);
}
-
document
.querySelectorAll('input[type="checkbox"]')
.forEach((checkbox) =>
checkbox.addEventListener('click', (event) => event.target.blur())
);
+
+ // draggable re-ordering
+ const draggable = {
+ state: 0,
+ tags: ['b', 'span'],
+ $toggle: document.querySelector('#draggable-toggle'),
+ list: modules.loaded
+ .filter((m) => !m.tags.includes('core'))
+ .map((m) => m.elem),
+ target: null,
+ render() {
+ draggable.target = null;
+ for (let $node of draggable.list) {
+ $node.draggable = false;
+ $modules.append($node);
+ }
+ },
+ mouseover(event) {
+ if (!draggable.target && event.target.innerText) {
+ for (let $node of draggable.list) $node.draggable = false;
+ const $node = draggable.list.find(
+ (node) => node.innerText === event.target.innerText
+ );
+ if ($node) $node.draggable = draggable.state;
+ }
+ },
+ };
+ document.addEventListener('dragstart', (event) => {
+ draggable.target = event.target;
+ event.target.style.opacity = 0.5;
+ });
+ document.addEventListener('dragend', (event) => {
+ event.target.style.opacity = '';
+ });
+ document.addEventListener('dragover', (event) => {
+ event.preventDefault();
+ document
+ .querySelectorAll('.dragged-over')
+ .forEach((el) => el.classList.remove('dragged-over'));
+ const $node = [
+ draggable.list[0].previousElementSibling,
+ ...draggable.list,
+ ].find((node) => node.innerText === event.target.innerText);
+ if ($node) $node.classList.add('dragged-over');
+ });
+ document.addEventListener('drop', (event) => {
+ event.preventDefault();
+ document
+ .querySelectorAll('.dragged-over')
+ .forEach((el) => el.classList.remove('dragged-over'));
+ if (
+ draggable.target &&
+ draggable.target.innerText !== event.target.innerText
+ ) {
+ const from = draggable.list.findIndex(
+ (node) => node.innerText === draggable.target.innerText
+ ),
+ to =
+ event.target.innerText ===
+ draggable.list[0].previousElementSibling.innerText
+ ? 0
+ : draggable.list.findIndex(
+ (node) => node.innerText === event.target.innerText
+ ) + 1;
+ if (to >= 0) {
+ draggable.list.splice(
+ to > from ? to - 1 : to,
+ 0,
+ draggable.list.splice(from, 1)[0]
+ );
+ store('mods').priority = draggable.list.map((m) => m.id);
+ }
+ }
+ draggable.render();
+ modified();
+ });
+ document.addEventListener('mouseover', draggable.mouseover);
+ draggable.render();
+ draggable.$toggle.addEventListener('click', (event) => {
+ draggable.state = !draggable.state;
+ draggable.tags = draggable.tags.reverse();
+ draggable.$toggle.innerHTML = `
+ <${draggable.tags[0]} data-bolded="configure">configure${draggable.tags[0]}> |
+ <${draggable.tags[1]} data-bolded="reorder">reorder${draggable.tags[1]}>
+ `;
+ document.body.classList[draggable.state ? 'add' : 'remove']('reorder');
+ $modules
+ .querySelectorAll('input')
+ .forEach((input) => (input.disabled = draggable.state));
+ search();
+ });
};
diff --git a/mods/core/icons/alwaysontop_off.svg b/mods/core/icons/alwaysontop_off.svg
index 9fa0fb5..96afcf0 100644
--- a/mods/core/icons/alwaysontop_off.svg
+++ b/mods/core/icons/alwaysontop_off.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/mods/core/icons/alwaysontop_on.svg b/mods/core/icons/alwaysontop_on.svg
index 1c344f8..3fec5d5 100644
--- a/mods/core/icons/alwaysontop_on.svg
+++ b/mods/core/icons/alwaysontop_on.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/mods/core/icons/maximize_off.svg b/mods/core/icons/maximize_off.svg
index 7241f63..0bf56b0 100644
--- a/mods/core/icons/maximize_off.svg
+++ b/mods/core/icons/maximize_off.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/mods/core/icons/maximize_on.svg b/mods/core/icons/maximize_on.svg
index 681fdc9..af77a3e 100644
--- a/mods/core/icons/maximize_on.svg
+++ b/mods/core/icons/maximize_on.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/mods/core/icons/minimize.svg b/mods/core/icons/minimize.svg
index abcebb7..d179e14 100644
--- a/mods/core/icons/minimize.svg
+++ b/mods/core/icons/minimize.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/mods/core/menu.html b/mods/core/menu.html
index 83e6d60..56da84e 100644
--- a/mods/core/menu.html
+++ b/mods/core/menu.html
@@ -9,7 +9,7 @@
-
+
@@ -20,6 +20,10 @@
+
+ configure |
+ reorder
+
diff --git a/mods/core/mod.js b/mods/core/mod.js
index 2294d0a..1d3bd3f 100644
--- a/mods/core/mod.js
+++ b/mods/core/mod.js
@@ -56,6 +56,12 @@ module.exports = {
type: 'toggle',
value: true,
},
+ {
+ key: 'snappy_transitions',
+ label: 'snappy transitions',
+ type: 'toggle',
+ value: false,
+ },
{
key: 'hotkey',
label: 'window display hotkey:',
@@ -68,10 +74,17 @@ module.exports = {
type: 'input',
value: 'Alt+E',
},
+ {
+ key: 'default_page',
+ label: 'open to default page id/url:',
+ type: 'input',
+ value: '',
+ },
],
hacks: {
'main/main.js': require('./tray.js'),
- 'main/createWindow.js': require('./create.js'),
+ 'main/systemMenu.js': require('./systemMenu.js'),
+ 'main/createWindow.js': require('./createWindow.js'),
'renderer/index.js': require('./render.js'),
'renderer/preload.js': require('./client.js'),
},
diff --git a/mods/core/render.js b/mods/core/render.js
index 9b17f03..c2e731e 100644
--- a/mods/core/render.js
+++ b/mods/core/render.js
@@ -6,30 +6,1067 @@
'use strict';
+const url = require('url'),
+ path = require('path'),
+ electron = require('electron'),
+ { __notion } = require('../../pkg/helpers.js'),
+ config = require(`${__notion}/app/config.js`),
+ constants = require(`${__notion}/app/shared/constants.js`),
+ notion_intl = require(`${__notion}/app/shared/notion-intl/index.js`),
+ notionIpc = require(`${__notion}/app/helpers/notionIpc.js`),
+ localizationHelper = require(`${__notion}/app/helpers/localizationHelper.js`),
+ koMessages = require(`${__notion}/app/i18n/ko_KR/messages.json`),
+ schemeHelpers = require(`${__notion}/app/shared/schemeHelpers.js`),
+ React = require(`${__notion}/app/node_modules/react/index.js`),
+ ReactDOM = require(`${__notion}/app/node_modules/react-dom/index.js`),
+ { toKeyEvent } = require('keyboardevent-from-electron-accelerator');
+
+const insertCSP = `
+ const csp = document.createElement('meta');
+ csp.httpEquiv = 'Content-Security-Policy';
+ csp.content = "script-src 'self' 'unsafe-inline' 'unsafe-eval' enhancement: https://gist.github.com https://apis.google.com https://api.amplitude.com https://widget.intercom.io https://js.intercomcdn.com https://logs-01.loggly.com https://cdn.segment.com https://analytics.pgncs.notion.so https://checkout.stripe.com https://embed.typeform.com https://admin.typeform.com https://platform.twitter.com https://cdn.syndication.twimg.com; connect-src 'self' https://msgstore.www.notion.so wss://msgstore.www.notion.so https://notion-emojis.s3-us-west-2.amazonaws.com https://s3-us-west-2.amazonaws.com https://s3.us-west-2.amazonaws.com https://notion-production-snapshots-2.s3.us-west-2.amazonaws.com https: http: https://api.amplitude.com https://api.embed.ly https://js.intercomcdn.com https://api-iam.intercom.io wss://nexus-websocket-a.intercom.io https://logs-01.loggly.com https://api.segment.io https://api.pgncs.notion.so https://checkout.stripe.com https://cdn.contentful.com https://preview.contentful.com https://images.ctfassets.net https://api.unsplash.com https://boards-api.greenhouse.io; font-src 'self' data: enhancement: https: http:; img-src 'self' data: blob: https: https://platform.twitter.com https://syndication.twitter.com https://pbs.twimg.com https://ton.twimg.com; style-src 'self' 'unsafe-inline' enhancement: https: http:; frame-src https: http:; media-src https: http:";
+ document.head.appendChild(csp);
+`,
+ idToNotionURL = (id) =>
+ `notion://www.notion.so/${
+ url.parse(id).pathname.split('/').reverse()[0] || ''
+ }/${url.parse(id).search || ''}`;
+
module.exports = (store, __exports) => {
- const __start = window['__start'];
+ if ((store('mods')['e1692c29-475e-437b-b7ff-3eee872e1a42'] || {}).enabled) {
+ class Index extends React.PureComponent {
+ constructor() {
+ super(...arguments);
+ this.state = {
+ error: false,
+ searching: false,
+ searchingPeekView: false,
+ zoomFactor: 1,
+ tabs: new Map([[0, { title: 'notion.so', open: true }]]),
+ slideIn: new Set(),
+ slideOut: new Set(),
+ };
+ this.$titlebar = null;
+ this.$dragging = null;
+ this.views = {
+ active: null,
+ current: {
+ $el: () => this.views.html[this.views.current.id],
+ id: 0,
+ },
+ react: {},
+ html: {},
+ loaded: {},
+ tabs: {},
+ };
+ this.$search = null;
+ this.handleReload = () => {
+ this.setState({ error: false });
+ Object.values(this.views.html).forEach(($notion) => {
+ if ($notion.isWaitingForResponse()) $notion.reload();
+ });
+ };
+ this.communicateWithView = this.communicateWithView.bind(this);
+ this.startSearch = this.startSearch.bind(this);
+ this.stopSearch = this.stopSearch.bind(this);
+ this.nextSearch = this.nextSearch.bind(this);
+ this.prevSearch = this.prevSearch.bind(this);
+ this.clearSearch = this.clearSearch.bind(this);
+ this.doneSearch = this.doneSearch.bind(this);
- window['__start'] = function () {
- __start();
- const dragarea = document.querySelector(
- '#root [style*="-webkit-app-region: drag"]'
- ),
- default_styles = dragarea.getAttribute('style');
+ // draggable re-ordering
+ const getTab = ($el) => {
+ if ($el.tagName !== 'BUTTON') $el = $el.parentElement;
+ if ($el.innerText === '+')
+ return [null, document.querySelector('.tab.new')];
+ const tab = Object.entries(this.views.tabs).find(
+ ([id, $node]) => $node === $el
+ );
+ return tab ? [+tab[0], tab[1]] : [];
+ };
+ document.addEventListener('dragstart', (event) => {
+ if (!this.$titlebar) return;
+ const tab = getTab(event.target);
+ this.$dragging = tab[0];
+ event.dataTransfer.setData(
+ 'text',
+ JSON.stringify({
+ target: electron.remote.getCurrentWindow().webContents.id,
+ tab: tab[0],
+ title: tab[1].children[0].innerText,
+ url: document.getElementById(getTab(event.target)[0]).src,
+ })
+ );
+ event.target.style.opacity = 0.5;
+ });
+ document.addEventListener('dragend', (event) => {
+ if (!this.$titlebar) return;
+ event.target.style.opacity = '';
+ document
+ .querySelectorAll('.dragged-over')
+ .forEach((el) => el.classList.remove('dragged-over'));
+ });
+ document.addEventListener('dragover', (event) => {
+ if (!this.$titlebar) return;
+ event.preventDefault();
+ document
+ .querySelectorAll('.dragged-over')
+ .forEach((el) => el.classList.remove('dragged-over'));
+ const tab = getTab(event.target)[1];
+ if (tab) tab.classList.add('dragged-over');
+ });
+ document.addEventListener('drop', async (event) => {
+ event.preventDefault();
+ const eventData = JSON.parse(event.dataTransfer.getData('text'));
+ if (
+ eventData.target !==
+ electron.remote.getCurrentWindow().webContents.id
+ ) {
+ electron.ipcRenderer.send(
+ 'enhancer:close-tab',
+ eventData.target,
+ eventData.tab
+ );
+ this.$dragging = await this.newTab(
+ eventData.url,
+ eventData.title,
+ false
+ );
+ }
+ if (this.$titlebar) {
+ const from = getTab(this.views.tabs[+this.$dragging]),
+ to = getTab(event.target);
+ if (from[0] !== to[0]) {
+ if (to[1].classList.contains('new')) {
+ const list = new Map(this.state.tabs);
+ list.delete(from[0]);
+ list.set(from[0], this.state.tabs.get(from[0]));
+ this.setState({ tabs: list });
+ } else {
+ const list = [...this.state.tabs],
+ fromIndex = list.findIndex(
+ ([id, { title, open }]) => id === from[0]
+ ),
+ toIndex = list.findIndex(
+ ([id, { title, open }]) => id === to[0]
+ );
+ list.splice(
+ toIndex > fromIndex ? toIndex - 1 : toIndex,
+ 0,
+ list.splice(fromIndex, 1)[0]
+ );
+ this.setState({ tabs: new Map(list) });
+ }
+ }
+ this.$dragging = null;
+ }
+ });
+ document.addEventListener('keyup', (event) => {
+ if (!electron.remote.getCurrentWindow().isFocused()) return;
+ // switch between tabs via key modifier
+ const select_tab_modifier = toKeyEvent(
+ store('e1692c29-475e-437b-b7ff-3eee872e1a42').select_modifier
+ );
+ let triggered = true;
+ for (let prop in select_tab_modifier)
+ if (select_tab_modifier[prop] !== event[prop]) triggered = false;
+ if (
+ triggered &&
+ [
+ '1',
+ '2',
+ '3',
+ '4',
+ '5',
+ '6',
+ '7',
+ '8',
+ '9',
+ 'ArrowRight',
+ 'ArrowLeft',
+ ].includes(event.key)
+ )
+ this.selectTab(event.key);
+ // create/close tab keybindings
+ const new_tab_keybinding = toKeyEvent(
+ store('e1692c29-475e-437b-b7ff-3eee872e1a42').new_tab
+ );
+ triggered = true;
+ for (let prop in new_tab_keybinding)
+ if (new_tab_keybinding[prop] !== event[prop]) triggered = false;
+ if (triggered) this.newTab();
+ const close_tab_keybinding = toKeyEvent(
+ store('e1692c29-475e-437b-b7ff-3eee872e1a42').close_tab
+ );
+ triggered = true;
+ for (let prop in close_tab_keybinding)
+ if (close_tab_keybinding[prop] !== event[prop]) triggered = false;
+ if (triggered && document.querySelector('.tab.current .close'))
+ document.querySelector('.tab.current .close').click();
+ });
+ electron.ipcRenderer.on('enhancer:close-tab', (event, tab) => {
+ this.closeTab(tab);
+ });
+ }
- if (store().tiling_mode) {
- dragarea.style.display = 'none';
- } else {
- 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]};`
+ componentDidMount() {
+ const buttons = require('./buttons.js')(store);
+ this.$titlebar.appendChild(buttons.element);
+ this.loadListeners();
+
+ 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;
+ }
+ electronWindow.addListener('app-command', (e, cmd) => {
+ const webContents = this.views.current.$el().getWebContents();
+ if (cmd === 'browser-backward' && webContents.canGoBack()) {
+ webContents.goBack();
+ } else if (cmd === 'browser-forward' && webContents.canGoForward()) {
+ webContents.goForward();
+ }
+ });
+ electronWindow.addListener('swipe', (e, dir) => {
+ const webContents = this.views.current.$el().getWebContents();
+ if (dir === 'left' && webContents.canGoBack()) {
+ webContents.goBack();
+ } else if (dir === 'right' && webContents.canGoForward()) {
+ webContents.goForward();
+ }
+ });
+ }
+
+ newTab(url = '', title = 'notion.so', animate = true) {
+ let id = 0;
+ const list = new Map(this.state.tabs);
+ while (this.state.tabs.get(id) && this.state.tabs.get(id).open) id++;
+ list.delete(id);
+ return this.openTab(id, {
+ state: list,
+ load: url || true,
+ title,
+ animate,
+ });
+ }
+ openTab(
+ id,
+ {
+ state = new Map(this.state.tabs),
+ slideOut = new Set(this.state.slideOut),
+ load,
+ animate,
+ title = 'notion.so',
+ } = {
+ state: new Map(this.state.tabs),
+ slideOut: new Set(this.state.slideOut),
+ load: false,
+ title: 'notion.so',
+ animate: false,
+ }
+ ) {
+ return new Promise((res, rej) => {
+ if (!id && id !== 0) {
+ if (state.get(this.views.current.id).open) return res(id);
+ const currentIndex = [...state].findIndex(
+ ([id, { title, open }]) => id === this.views.current.id
+ );
+ id = ([...state].find(
+ ([id, { title, open }], tabIndex) =>
+ open && tabIndex > currentIndex
+ ) || [...state].find(([id, { title, open }]) => open))[0];
+ }
+ const current_src = this.views.current.$el().src;
+ this.views.current.id = id;
+ this.setState(
+ {
+ tabs: state.set(id, {
+ title: state.get(id) ? state.get(id).title : title,
+ open: true,
+ }),
+ slideIn: animate
+ ? this.state.slideIn.add(id)
+ : this.state.slideIn,
+ slideOut: slideOut,
+ },
+ async () => {
+ this.focusTab();
+ new Promise((resolve, reject) => {
+ let attempt,
+ clear = () => {
+ clearInterval(attempt);
+ return true;
+ };
+ attempt = setInterval(() => {
+ if (this.views.current.id !== id) return clear() && reject();
+ if (document.body.contains(this.views.html[id]))
+ return clear() && resolve();
+ }, 50);
+ })
+ .then(() => {
+ if (load) {
+ 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(
+ typeof load === 'string'
+ ? load
+ : store().default_page
+ ? idToNotionURL(store().default_page)
+ : current_src
+ );
+ }
+ })
+ .catch(() => {
+ // nothing
+ })
+ .finally(() => {
+ setTimeout(() => {
+ this.setState(
+ { slideIn: new Set(), slideOut: new Set() },
+ () => res(id)
+ );
+ }, 150);
+ });
+ }
);
});
+ }
+ closeTab(id) {
+ if ((!id && id !== 0) || !this.state.tabs.get(id)) return;
+ const list = new Map(this.state.tabs);
+ list.set(id, { ...list.get(id), open: false });
+ if (![...list].filter(([id, { title, open }]) => open).length)
+ return electron.remote.getCurrentWindow().close();
+ return this.openTab(
+ this.views.current.id === id ? null : this.views.current.id,
+ { state: list, slideOut: this.state.slideOut.add(id) }
+ );
+ }
+ focusTab() {
+ if (this.views.active === this.views.current.id) return;
+ this.loadListeners();
+ this.blurListeners();
+ this.focusListeners();
+ for (const id in this.views.loaded) {
+ if (this.views.loaded.hasOwnProperty(id) && this.views.loaded[id]) {
+ const selected =
+ id == this.views.current.id &&
+ this.state.tabs.get(+id) &&
+ this.state.tabs.get(+id).open;
+ this.views.loaded[id].style.display = selected ? 'flex' : 'none';
+ if (selected) {
+ this.views.active = +id;
+ this.views.loaded[id].focus();
+ const electronWindow = electron.remote.getCurrentWindow();
+ if (
+ electronWindow &&
+ electronWindow.getTitle() !== this.state.tabs.get(+id).title
+ ) {
+ electronWindow.setTitle(this.state.tabs.get(+id).title);
+ }
+ }
+ }
+ }
+ }
+ selectTab(num) {
+ if (num === 'ArrowLeft') {
+ const prev = document.querySelector('.tab.current')
+ .previousElementSibling;
+ if (prev) prev.click();
+ } else if (num === 'ArrowRight') {
+ const next = document.querySelector('.tab.current')
+ .nextElementSibling;
+ if (next && !next.classList.contains('new')) next.click();
+ } else {
+ num = +num;
+ if (num == 9) {
+ document
+ .querySelector('#tabs')
+ .children[
+ document.querySelector('#tabs').children.length - 2
+ ].click();
+ } else if (
+ document.querySelector('#tabs').children[num - 1] &&
+ document.querySelector('#tabs').children.length > num
+ ) {
+ document.querySelector('#tabs').children[num - 1].click();
+ }
+ }
+ }
+
+ communicateWithView(event) {
+ switch (event.channel) {
+ case 'enhancer:set-tab-theme':
+ for (const style of event.args[0])
+ document.body.style.setProperty(style[0], style[1]);
+ break;
+ case 'enhancer:set-tab-title':
+ if (this.state.tabs.get(+event.target.id)) {
+ this.setState({
+ tabs: new Map(
+ this.state.tabs.set(+event.target.id, {
+ ...this.state.tabs.get(+event.target.id),
+ title: event.args[0],
+ })
+ ),
+ });
+ const electronWindow = electron.remote.getCurrentWindow();
+ if (
+ event.target.id == this.views.current.id &&
+ electronWindow.getTitle() !== event.args[0]
+ )
+ electronWindow.setTitle(event.args[0]);
+ }
+ break;
+ case 'enhancer:select-tab':
+ this.selectTab(event.args[0]);
+ break;
+ case 'enhancer:new-tab':
+ this.newTab(event.args[0]);
+ break;
+ case 'enhancer:close-tab':
+ this.closeTab(
+ event.args[0] || event.args[0] === 0
+ ? event.args[0]
+ : this.views.current.id
+ );
+ break;
+ }
+ }
+ startSearch(isPeekView) {
+ this.setState(
+ {
+ searching: true,
+ searchingPeekView: isPeekView,
+ },
+ () => {
+ if (document.activeElement instanceof HTMLElement)
+ document.activeElement.blur();
+ this.$search.focus();
+ notionIpc.sendIndexToSearch(this.$search, 'search:start');
+ notionIpc.sendIndexToNotion(this.$search, 'search:started');
+ }
+ );
+ }
+ stopSearch() {
+ notionIpc.sendIndexToSearch(this.$search, 'search:reset');
+ this.setState({
+ searching: false,
+ });
+ this.lastSearchQuery = undefined;
+ this.views.current
+ .$el()
+ .getWebContents()
+ .stopFindInPage('clearSelection');
+ notionIpc.sendIndexToNotion(this.views.current.$el(), 'search:stopped');
+ }
+ nextSearch(query) {
+ this.views.current
+ .$el()
+ .getWebContents()
+ .findInPage(query, {
+ forward: true,
+ findNext: query === this.lastSearchQuery,
+ });
+ this.lastSearchQuery = query;
+ }
+ prevSearch(query) {
+ this.views.current
+ .$el()
+ .getWebContents()
+ .findInPage(query, {
+ forward: false,
+ findNext: query === this.lastSearchQuery,
+ });
+ this.lastSearchQuery = query;
+ }
+ clearSearch() {
+ this.lastSearchQuery = undefined;
+ this.views.current
+ .$el()
+ .getWebContents()
+ .stopFindInPage('clearSelection');
+ }
+ doneSearch() {
+ this.lastSearchQuery = undefined;
+ this.views.current
+ .$el()
+ .getWebContents()
+ .stopFindInPage('clearSelection');
+ this.setState({ searching: false });
+ if (document.activeElement instanceof HTMLElement) {
+ document.activeElement.blur();
+ }
+ this.views.current.$el().focus();
+ notionIpc.sendIndexToNotion(this.views.current.$el(), 'search:stopped');
+ }
+ focusListeners() {
+ if (!this.views.current.$el() || !this.$search) return;
+ this.views.current
+ .$el()
+ .addEventListener('ipc-message', this.communicateWithView);
+ notionIpc.receiveIndexFromNotion.addListener(
+ this.views.current.$el(),
+ 'search:start',
+ this.startSearch
+ );
+ notionIpc.receiveIndexFromNotion.addListener(
+ this.views.current.$el(),
+ 'search:stop',
+ this.stopSearch
+ );
+ notionIpc.receiveIndexFromSearch.addListener(
+ this.$search,
+ 'search:next',
+ this.nextSearch
+ );
+ notionIpc.receiveIndexFromSearch.addListener(
+ this.$search,
+ 'search:prev',
+ this.prevSearch
+ );
+ notionIpc.receiveIndexFromSearch.addListener(
+ this.$search,
+ 'search:clear',
+ this.clearSearch
+ );
+ notionIpc.receiveIndexFromSearch.addListener(
+ this.$search,
+ 'search:stop',
+ this.doneSearch
+ );
+ }
+ blurListeners() {
+ if (!this.views.current.$el() || !this.$search) return;
+ if (this.state.searching) this.stopSearch();
+ this.views.current
+ .$el()
+ .removeEventListener('ipc-message', this.communicateWithView);
+ notionIpc.receiveIndexFromNotion.removeListener(
+ this.views.current.$el(),
+ 'search:start',
+ this.startSearch
+ );
+ notionIpc.receiveIndexFromNotion.removeListener(
+ this.views.current.$el(),
+ 'search:stop',
+ this.stopSearch
+ );
+ notionIpc.receiveIndexFromSearch.removeListener(
+ this.$search,
+ 'search:next',
+ this.nextSearch
+ );
+ notionIpc.receiveIndexFromSearch.removeListener(
+ this.$search,
+ 'search:prev',
+ this.prevSearch
+ );
+ notionIpc.receiveIndexFromSearch.removeListener(
+ this.$search,
+ 'search:clear',
+ this.clearSearch
+ );
+ notionIpc.receiveIndexFromSearch.removeListener(
+ this.$search,
+ 'search:stop',
+ this.doneSearch
+ );
+ }
+ loadListeners() {
+ if (!this.$search) return;
+ Object.entries(this.views.html)
+ .filter(([id, $notion]) => !this.views.loaded[id] && $notion)
+ .forEach(([id, $notion]) => {
+ if (!$notion) return;
+ this.views.loaded[id] = $notion;
+ $notion.addEventListener('did-fail-load', (error) => {
+ // logger.info('Failed to load:', error);
+ if (
+ error.errorCode === -3 ||
+ !error.validatedURL.startsWith(
+ schemeHelpers.getSchemeUrl({
+ httpUrl: config.default.baseURL,
+ protocol: config.default.protocol,
+ })
+ )
+ ) {
+ return;
+ }
+ this.setState({ error: true });
+ });
+ $notion.addEventListener('dom-ready', () => {
+ $notion.getWebContents().executeJavaScript(insertCSP);
+ $notion
+ .getWebContents()
+ .addListener('found-in-page', (event, result) => {
+ const matches = result
+ ? {
+ count: result.matches,
+ index: result.activeMatchOrdinal,
+ }
+ : { count: 0, index: 0 };
+ notionIpc.sendIndexToSearch(
+ this.$search,
+ 'search:result',
+ matches
+ );
+ });
+ notionIpc.proxyAllMainToNotion($notion);
+ });
+ notionIpc.receiveIndexFromNotion.addListener(
+ $notion,
+ 'search:set-theme',
+ (theme) => {
+ notionIpc.sendIndexToSearch(
+ this.$search,
+ 'search:set-theme',
+ theme
+ );
+ }
+ );
+ notionIpc.receiveIndexFromNotion.addListener(
+ $notion,
+ 'zoom',
+ (zoomFactor) => {
+ $notion.getWebContents().setZoomFactor(zoomFactor);
+ this.$search.getWebContents().setZoomFactor(zoomFactor);
+ 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'
+ );
+ };
+ electronWindow.addListener(
+ 'enter-full-screen',
+ sendFullScreenChangeEvent
+ );
+ electronWindow.addListener(
+ 'leave-full-screen',
+ sendFullScreenChangeEvent
+ );
+ electronWindow.addListener(
+ 'enter-html-full-screen',
+ sendFullScreenChangeEvent
+ );
+ electronWindow.addListener(
+ 'leave-html-full-screen',
+ sendFullScreenChangeEvent
+ );
+ });
+ }
+
+ renderTitlebar() {
+ return React.createElement(
+ 'header',
+ {
+ id: 'titlebar',
+ ref: ($titlebar) => {
+ this.$titlebar = $titlebar;
+ },
+ },
+ React.createElement('button', {
+ id: 'open-enhancer-menu',
+ onClick: (e) => {
+ electron.ipcRenderer.send('enhancer:open-menu');
+ },
+ }),
+ React.createElement(
+ 'div',
+ { id: 'tabs' },
+ ...[...this.state.tabs]
+ .filter(
+ ([id, { title, open }]) => open || this.state.slideOut.has(id)
+ )
+ .map(([id, { title, open }]) =>
+ React.createElement(
+ 'button',
+ {
+ className:
+ 'tab' +
+ (id === this.views.current.id ? ' current' : '') +
+ (this.state.slideIn.has(id) ? ' slideIn' : '') +
+ (this.state.slideOut.has(id) ? ' slideOut' : ''),
+ draggable: true,
+ onClick: (e) => {
+ if (!e.target.classList.contains('close'))
+ this.openTab(id);
+ },
+ onMouseUp: (e) => {
+ if (window.event.which === 2) this.closeTab(id);
+ },
+ ref: ($tab) => {
+ this.views.tabs[id] = $tab;
+ },
+ },
+ React.createElement('span', {}, title),
+ React.createElement(
+ 'span',
+ {
+ className: 'close',
+ onClick: () => {
+ this.closeTab(id);
+ },
+ },
+ '×'
+ )
+ )
+ ),
+ React.createElement(
+ 'button',
+ {
+ className: 'tab new',
+ onClick: () => {
+ this.newTab();
+ },
+ },
+ React.createElement('span', {}, '+')
+ )
+ )
+ );
+ }
+ renderNotionContainer() {
+ this.views.react = Object.fromEntries(
+ [...this.state.tabs].map(([id, { title, open }]) => {
+ return [
+ id,
+ this.views.react[id] ||
+ React.createElement('webview', {
+ className: 'notion',
+ id,
+ ref: ($notion) => {
+ this.views.html[id] = $notion;
+ this.focusTab();
+ },
+ partition: constants.electronSessionPartition,
+ preload: path.resolve(`${__notion}/app/renderer/preload.js`),
+ src: this.props.notionUrl,
+ }),
+ ];
+ })
+ );
+ return React.createElement(
+ 'div',
+ {
+ style: {
+ flexGrow: 1,
+ display: this.state.error ? 'none' : 'flex',
+ },
+ },
+ ...Object.values(this.views.react)
+ );
+ }
+ renderSearchContainer() {
+ return React.createElement(
+ 'div',
+ {
+ style: {
+ position: 'fixed',
+ overflow: 'hidden',
+ pointerEvents: 'none',
+ padding: '0 20px',
+ top:
+ (this.state.searchingPeekView
+ ? 0
+ : process.platform === 'darwin'
+ ? 37
+ : 45) * this.state.zoomFactor,
+ right: (48 - 24) * this.state.zoomFactor,
+ width: 460 * this.state.zoomFactor,
+ height: 72 * this.state.zoomFactor,
+ zIndex: 99,
+ },
+ },
+ React.createElement('webview', {
+ id: 'search',
+ style: {
+ width: '100%',
+ height: '100%',
+ transition: `transform 70ms ease-${
+ this.state.searching ? 'out' : 'in'
+ }`,
+ transform: `translateY(${this.state.searching ? '0' : '-100'}%)`,
+ pointerEvents: this.state.searching ? 'auto' : 'none',
+ },
+ ref: ($search) => {
+ this.$search = $search;
+ this.focusTab();
+ },
+ partition: constants.electronSessionPartition,
+ preload: `file://${path.resolve(
+ `${__notion}/app/renderer/search.js`
+ )}`,
+ src: `file://${path.resolve(
+ `${__notion}/app/renderer/search.html`
+ )}`,
+ })
+ );
+ }
+ renderErrorContainer() {
+ return React.createElement(
+ 'div',
+ {
+ style: {
+ position: 'fixed',
+ top: 0,
+ left: 0,
+ right: 0,
+ bottom: 0,
+ display: this.state.error ? 'flex' : 'none',
+ flexDirection: 'column',
+ alignItems: 'center',
+ justifyContent: 'center',
+ padding: 24,
+ paddingBottom: '8vh',
+ },
+ },
+ React.createElement('img', {
+ style: {
+ width: 300,
+ maxWidth: '100%',
+ },
+ src: './onboarding-offline.png',
+ }),
+ React.createElement(
+ 'div',
+ {
+ style: {
+ paddingTop: 16,
+ paddingBottom: 16,
+ textAlign: 'center',
+ lineHeight: 1.4,
+ fontSize: 17,
+ letterSpacing: '-0.01em',
+ color: '#424241',
+ fontWeight: 500,
+ },
+ },
+ React.createElement(
+ 'div',
+ null,
+ React.createElement(notion_intl.FormattedMessage, {
+ id: 'desktopLogin.offline.title',
+ defaultMessage: 'Welcome to Notion !',
+ values: {
+ strong: (...chunks) =>
+ React.createElement('strong', null, chunks),
+ },
+ })
+ ),
+ React.createElement(
+ 'div',
+ null,
+ React.createElement(notion_intl.FormattedMessage, {
+ id: 'desktopLogin.offline.message',
+ defaultMessage: 'Connect to the internet to get started.',
+ })
+ )
+ ),
+ React.createElement(
+ 'div',
+ null,
+ React.createElement(
+ 'button',
+ {
+ style: {
+ background: '#fefaf8',
+ border: '1px solid #f1cbca',
+ boxSizing: 'border-box',
+ boxShadow: '0px 1px 2px rgba(0, 0, 0, 0.1)',
+ borderRadius: 3,
+ lineHeight: 'normal',
+ fontSize: 14,
+ fontWeight: 600,
+ letterSpacing: '-0.03em',
+ color: '#d8615c',
+ paddingLeft: 12,
+ paddingRight: 12,
+ height: 36,
+ },
+ onClick: this.handleReload,
+ },
+ React.createElement(notion_intl.FormattedMessage, {
+ id:
+ 'desktopLogin.offline.retryConnectingToInternetButton.label',
+ defaultMessage: 'Try again',
+ })
+ )
+ )
+ );
+ }
+ render() {
+ const notionLocale = localizationHelper.getNotionLocaleFromElectronLocale(
+ window.navigator.language
+ ),
+ result = React.createElement(
+ notion_intl.IntlProvider,
+ {
+ locale: notionLocale,
+ messages:
+ notionLocale === 'ko-KR'
+ ? koMessages
+ : {
+ 'desktopLogin.offline.title':
+ 'Welcome to Notion !',
+ 'desktopLogin.offline.message':
+ 'Connect to the internet to get started.',
+ 'desktopLogin.offline.retryConnectingToInternetButton.label':
+ 'Try again',
+ },
+ },
+ this.renderTitlebar(),
+ this.renderNotionContainer(),
+ this.renderSearchContainer(),
+ this.renderErrorContainer()
+ );
+ document.body.classList[this.state.error ? 'add' : 'remove']('error');
+ this.loadListeners();
+ return result;
+ }
}
- };
+
+ 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 ||
+ (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);
+ window.history.replaceState(undefined, undefined, plainUrl);
+
+ document.title = localizationHelper
+ .createIntlShape(
+ localizationHelper.getNotionLocaleFromElectronLocale(
+ window.navigator.language
+ )
+ )
+ .formatMessage(
+ notion_intl.defineMessages({
+ documentTitle: {
+ id: 'desktop.documentTitle',
+ defaultMessage: 'Notion Desktop',
+ },
+ }).documentTitle
+ );
+ const $root = document.getElementById('root');
+ ReactDOM.render(
+ React.createElement(Index, { notionUrl: notionUrl }),
+ $root
+ );
+ };
+ } else {
+ 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"]'
+ ),
+ default_styles = dragarea.getAttribute('style');
+ if (store().tiling_mode) {
+ dragarea.style.display = 'none';
+ } else {
+ 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]};`
+ );
+ });
+
+ document.getElementById('notion').addEventListener('dom-ready', () => {
+ document
+ .getElementById('notion')
+ .getWebContents()
+ .executeJavaScript(insertCSP);
+ });
+ }
+ };
+ }
};
diff --git a/mods/core/styles.css b/mods/core/styles.css
index da69ff5..fbfe5be 100644
--- a/mods/core/styles.css
+++ b/mods/core/styles.css
@@ -8,3 +8,4 @@
@import './css/variables.css';
@import './css/scrollbars.css';
@import './css/titlebar.css';
+@import './css/responsive.css';
diff --git a/mods/core/systemMenu.js b/mods/core/systemMenu.js
new file mode 100644
index 0000000..d301476
--- /dev/null
+++ b/mods/core/systemMenu.js
@@ -0,0 +1,476 @@
+/*
+ * notion-enhancer
+ * (c) 2020 dragonwocky (https://dragonwocky.me/)
+ * under the MIT license
+ */
+
+'use strict';
+
+module.exports = (store, __exports) => {
+ const electron = require('electron'),
+ fs = require('fs-extra'),
+ { __notion } = require('../../pkg/helpers.js'),
+ createWindow = require(`${__notion}/app/main/createWindow.js`),
+ config = require(`${__notion}/app/config.js`),
+ notion_intl = require(`${__notion}/app/shared/notion-intl/index.js`),
+ localizationHelper = require(`${__notion}/app/helpers/localizationHelper.js`),
+ isMac = process.platform === 'darwin',
+ // why is it inversed? i have no idea, but for some reason this is what works
+ tabsEnabled = !(store('mods')['e1692c29-475e-437b-b7ff-3eee872e1a42'] || {})
+ .enabled,
+ menuMessages = notion_intl.defineMessages({
+ fileMenuTitle: {
+ id: 'desktopTopbar.fileMenu.title',
+ defaultMessage: 'File',
+ },
+ editMenuTitle: {
+ id: 'desktopTopbar.editMenu.title',
+ defaultMessage: 'Edit',
+ },
+ viewMenuTitle: {
+ id: 'desktopTopbar.viewMenu.title',
+ defaultMessage: 'View',
+ },
+ windowMenuTitle: {
+ id: 'desktopTopbar.windowMenu.title',
+ defaultMessage: 'Window',
+ },
+ helpTitle: {
+ id: 'desktopTopbar.helpMenu.title',
+ defaultMessage: 'Help',
+ },
+ newWindow: {
+ id: 'desktopTopbar.fileMenu.newWindow',
+ defaultMessage: 'New Window',
+ },
+ closeWindow: {
+ id: 'desktopTopbar.fileMenu.close',
+ defaultMessage: 'Close Window',
+ },
+ quit: {
+ id: 'desktopTopbar.fileMenu.quit',
+ defaultMessage: 'Exit',
+ },
+ undo: {
+ id: 'desktopTopbar.editMenu.undo',
+ defaultMessage: 'Undo',
+ },
+ redo: {
+ id: 'desktopTopbar.editMenu.redo',
+ defaultMessage: 'Redo',
+ },
+ cut: {
+ id: 'desktopTopbar.editMenu.cut',
+ defaultMessage: 'Cut',
+ },
+ copy: {
+ id: 'desktopTopbar.editMenu.copy',
+ defaultMessage: 'Copy',
+ },
+ paste: {
+ id: 'desktopTopbar.editMenu.paste',
+ defaultMessage: 'Paste',
+ },
+ selectAll: {
+ id: 'desktopTopbar.editMenu.selectAll',
+ defaultMessage: 'Select All',
+ },
+ startSpeaking: {
+ id: 'desktopTopbar.editMenu.speech.startSpeaking',
+ defaultMessage: 'Start Speaking',
+ },
+ stopSpeaking: {
+ id: 'desktopTopbar.editMenu.speech.stopSpeaking',
+ defaultMessage: 'Stop Speaking',
+ },
+ speech: {
+ id: 'desktopTopbar.editMenu.speech',
+ defaultMessage: 'Speech',
+ },
+ reload: {
+ id: 'desktopTopbar.viewMenu.reload',
+ defaultMessage: 'Reload',
+ },
+ togglefullscreen: {
+ id: 'desktopTopbar.viewMenu.togglefullscreen',
+ defaultMessage: 'Toggle Full Screen',
+ },
+ toggleDevTools: {
+ id: 'desktopTopbar.toggleDevTools',
+ defaultMessage: 'Toggle Developer Tools',
+ },
+ toggleWindowDevTools: {
+ id: 'desktopTopbar.toggleWindowDevTools',
+ defaultMessage: 'Toggle Window Developer Tools',
+ },
+ maximize: {
+ id: 'desktopTopbar.windowMenu.maximize',
+ defaultMessage: 'Maximize',
+ },
+ minimize: {
+ id: 'desktopTopbar.windowMenu.minimize',
+ defaultMessage: 'Minimize',
+ },
+ zoom: {
+ id: 'desktopTopbar.windowMenu.zoom',
+ defaultMessage: 'Zoom',
+ },
+ front: {
+ id: 'desktopTopbar.windowMenu.front',
+ defaultMessage: 'Front',
+ },
+ close: {
+ id: 'desktopTopbar.windowMenu.close',
+ defaultMessage: 'Close',
+ },
+ help: {
+ id: 'desktopTopbar.helpMenu.openHelpAndSupport',
+ defaultMessage: 'Open Help & Support',
+ },
+ reset: {
+ id: 'desktopTopbar.appMenu.resetAppAndClearData',
+ defaultMessage: 'Reset App & Clear Local Data',
+ },
+ about: {
+ id: 'desktopTopbar.appMenu.about',
+ defaultMessage: 'About Notion',
+ },
+ services: {
+ id: 'desktopTopbar.appMenu.services',
+ defaultMessage: 'Services',
+ },
+ hide: { id: 'desktopTopbar.appMenu.hide', defaultMessage: 'Hide Notion' },
+ hideOthers: {
+ id: 'desktopTopbar.appMenu.hideOthers',
+ defaultMessage: 'Hide Others',
+ },
+ unhide: {
+ id: 'desktopTopbar.appMenu.unhide',
+ defaultMessage: 'Show All',
+ },
+ quitMac: { id: 'desktopTopbar.appMenu.quit', defaultMessage: 'Quit' },
+ }),
+ escapeAmpersand = (message) => message.replace(/&/g, '&&');
+ __exports.setupSystemMenu = (locale) => {
+ const intl = localizationHelper.createIntlShape(locale),
+ fileMenu = {
+ role: 'fileMenu',
+ label: escapeAmpersand(intl.formatMessage(menuMessages.fileMenuTitle)),
+ submenu: isMac
+ ? [
+ {
+ label: escapeAmpersand(
+ intl.formatMessage(menuMessages.newWindow)
+ ),
+ accelerator: 'CmdOrCtrl+Shift+N',
+ click: () => createWindow.createWindow(),
+ },
+ ...(tabsEnabled
+ ? [
+ {
+ role: 'close',
+ label: escapeAmpersand(
+ intl.formatMessage(menuMessages.closeWindow)
+ ),
+ },
+ ]
+ : []),
+ ]
+ : [
+ {
+ label: escapeAmpersand(
+ intl.formatMessage(menuMessages.newWindow)
+ ),
+ accelerator: 'CmdOrCtrl+Shift+N',
+ click: () => createWindow.createWindow(),
+ },
+ ...(tabsEnabled
+ ? [
+ {
+ role: 'quit',
+ label: escapeAmpersand(
+ intl.formatMessage(menuMessages.quit)
+ ),
+ },
+ ]
+ : []),
+ ],
+ },
+ editMenu = {
+ role: 'editMenu',
+ label: escapeAmpersand(intl.formatMessage(menuMessages.editMenuTitle)),
+ submenu: isMac
+ ? [
+ {
+ role: 'undo',
+ label: escapeAmpersand(intl.formatMessage(menuMessages.undo)),
+ },
+ {
+ role: 'redo',
+ label: escapeAmpersand(intl.formatMessage(menuMessages.redo)),
+ },
+ { type: 'separator' },
+ {
+ role: 'cut',
+ label: escapeAmpersand(intl.formatMessage(menuMessages.cut)),
+ },
+ {
+ role: 'copy',
+ label: escapeAmpersand(intl.formatMessage(menuMessages.copy)),
+ },
+ {
+ role: 'paste',
+ label: escapeAmpersand(intl.formatMessage(menuMessages.paste)),
+ },
+ {
+ role: 'selectAll',
+ label: escapeAmpersand(
+ intl.formatMessage(menuMessages.selectAll)
+ ),
+ },
+ { type: 'separator' },
+ {
+ label: escapeAmpersand(intl.formatMessage(menuMessages.speech)),
+ submenu: [
+ {
+ role: 'startSpeaking',
+ label: escapeAmpersand(
+ intl.formatMessage(menuMessages.startSpeaking)
+ ),
+ },
+ {
+ role: 'stopSpeaking',
+ label: escapeAmpersand(
+ intl.formatMessage(menuMessages.stopSpeaking)
+ ),
+ },
+ ],
+ },
+ ]
+ : [
+ {
+ role: 'undo',
+ label: escapeAmpersand(intl.formatMessage(menuMessages.undo)),
+ },
+ {
+ role: 'redo',
+ label: escapeAmpersand(intl.formatMessage(menuMessages.redo)),
+ },
+ { type: 'separator' },
+ {
+ role: 'cut',
+ label: escapeAmpersand(intl.formatMessage(menuMessages.cut)),
+ },
+ {
+ role: 'copy',
+ label: escapeAmpersand(intl.formatMessage(menuMessages.copy)),
+ },
+ {
+ role: 'paste',
+ label: escapeAmpersand(intl.formatMessage(menuMessages.paste)),
+ },
+ { type: 'separator' },
+ {
+ role: 'selectAll',
+ label: escapeAmpersand(
+ intl.formatMessage(menuMessages.selectAll)
+ ),
+ },
+ ],
+ },
+ viewMenu = {
+ role: 'viewMenu',
+ label: escapeAmpersand(intl.formatMessage(menuMessages.viewMenuTitle)),
+ submenu: [
+ {
+ label: escapeAmpersand(intl.formatMessage(menuMessages.reload)),
+ accelerator: 'CmdOrCtrl+R',
+ click() {
+ const focusedWebContents = electron.webContents.getFocusedWebContents();
+ if (focusedWebContents) {
+ if (focusedWebContents.hostWebContents) {
+ for (const webContentsInstance of electron.webContents.getAllWebContents()) {
+ if (
+ webContentsInstance.hostWebContents ===
+ focusedWebContents.hostWebContents
+ ) {
+ webContentsInstance.reload();
+ }
+ }
+ } else {
+ focusedWebContents.reload();
+ }
+ }
+ },
+ },
+ {
+ label: escapeAmpersand(
+ intl.formatMessage(menuMessages.toggleDevTools)
+ ),
+ accelerator: isMac ? 'Alt+Command+I' : 'Ctrl+Shift+I',
+ click() {
+ let focusedWebContents = electron.webContents.getFocusedWebContents();
+ if (focusedWebContents) {
+ const focusedWebContentsUrl = focusedWebContents.getURL();
+ if (
+ focusedWebContentsUrl.startsWith('file://') &&
+ focusedWebContentsUrl.endsWith('/search.html')
+ ) {
+ const notionWebviewWebContents = electron.webContents
+ .getAllWebContents()
+ .find(
+ (webContentsInstance) =>
+ webContentsInstance.hostWebContents ===
+ focusedWebContents.hostWebContents &&
+ webContentsInstance !== focusedWebContents
+ );
+ if (notionWebviewWebContents) {
+ focusedWebContents = notionWebviewWebContents;
+ }
+ }
+ focusedWebContents.toggleDevTools();
+ }
+ },
+ },
+ {
+ label: escapeAmpersand(
+ intl.formatMessage(menuMessages.toggleWindowDevTools)
+ ),
+ accelerator: isMac ? 'Shift+Alt+Command+I' : 'Alt+Ctrl+Shift+I',
+ visible: false,
+ click(menuItem, focusedWindow) {
+ if (focusedWindow) {
+ focusedWindow.webContents.toggleDevTools();
+ }
+ },
+ },
+ { type: 'separator' },
+ {
+ role: 'togglefullscreen',
+ label: escapeAmpersand(
+ intl.formatMessage(menuMessages.togglefullscreen)
+ ),
+ },
+ ],
+ },
+ windowMenu = {
+ role: 'windowMenu',
+ label: escapeAmpersand(
+ intl.formatMessage(menuMessages.windowMenuTitle)
+ ),
+ submenu: isMac
+ ? [
+ {
+ role: 'minimize',
+ label: escapeAmpersand(
+ intl.formatMessage(menuMessages.minimize)
+ ),
+ },
+ {
+ role: 'zoom',
+ label: escapeAmpersand(intl.formatMessage(menuMessages.zoom)),
+ },
+ { type: 'separator' },
+ {
+ role: 'front',
+ label: escapeAmpersand(intl.formatMessage(menuMessages.front)),
+ },
+ ]
+ : [
+ {
+ role: 'minimize',
+ label: escapeAmpersand(
+ intl.formatMessage(menuMessages.minimize)
+ ),
+ },
+ {
+ label: escapeAmpersand(
+ intl.formatMessage(menuMessages.maximize)
+ ),
+ click(item, focusedWindow) {
+ if (focusedWindow) {
+ if (focusedWindow.isMaximized()) {
+ focusedWindow.unmaximize();
+ } else {
+ focusedWindow.maximize();
+ }
+ }
+ },
+ },
+ ...(tabsEnabled
+ ? [
+ {
+ role: 'close',
+ label: escapeAmpersand(
+ intl.formatMessage(menuMessages.close)
+ ),
+ },
+ ]
+ : []),
+ ],
+ },
+ helpMenu = {
+ role: 'help',
+ label: escapeAmpersand(intl.formatMessage(menuMessages.helpTitle)),
+ submenu: [
+ {
+ label: escapeAmpersand(intl.formatMessage(menuMessages.help)),
+ click() {
+ electron.shell.openExternal(config.default.baseURL + '/help');
+ },
+ },
+ ],
+ },
+ appMenu = {
+ role: 'appMenu',
+ submenu: [
+ {
+ role: 'about',
+ label: escapeAmpersand(intl.formatMessage(menuMessages.about)),
+ },
+ { type: 'separator' },
+ {
+ label: escapeAmpersand(intl.formatMessage(menuMessages.reset)),
+ async click(item, focusedWindow) {
+ await fs.remove(electron.app.getPath('userData'));
+ electron.app.relaunch();
+ electron.app.exit();
+ },
+ },
+ { type: 'separator' },
+ {
+ role: 'services',
+ label: escapeAmpersand(intl.formatMessage(menuMessages.services)),
+ },
+ { type: 'separator' },
+ {
+ role: 'hide',
+ label: escapeAmpersand(intl.formatMessage(menuMessages.hide)),
+ },
+ {
+ role: 'hideOthers',
+ label: escapeAmpersand(intl.formatMessage(menuMessages.hideOthers)),
+ },
+ {
+ role: 'unhide',
+ label: escapeAmpersand(intl.formatMessage(menuMessages.unhide)),
+ },
+ ...(tabsEnabled
+ ? [
+ { type: 'separator' },
+ {
+ role: 'quit',
+ label: escapeAmpersand(
+ intl.formatMessage(menuMessages.quitMac)
+ ),
+ },
+ ]
+ : []),
+ ],
+ },
+ template = [fileMenu, editMenu, viewMenu, windowMenu, helpMenu];
+ if (isMac) template.unshift(appMenu);
+ const menu = electron.Menu.buildFromTemplate(template);
+ electron.Menu.setApplicationMenu(menu);
+ };
+};
diff --git a/mods/core/tray.js b/mods/core/tray.js
index 871cbdb..59e292a 100644
--- a/mods/core/tray.js
+++ b/mods/core/tray.js
@@ -17,6 +17,8 @@ module.exports = (store, __exports) => {
helpers = require('../../pkg/helpers.js');
electron.app.on('ready', () => {
+ // tray
+
tray = new electron.Tray(
is_win
? path.resolve(`${__dirname}/icons/windows.ico`)
@@ -28,17 +30,27 @@ module.exports = (store, __exports) => {
})
);
- electron.ipcMain.on('enhancer:set-theme-vars', (event, arg) => {
- if (!enhancer_menu) return;
- enhancer_menu.webContents.send('enhancer:set-theme-vars', arg);
+ // menu
+
+ electron.ipcMain.on('enhancer:open-menu', (event, arg) => {
+ openEnhancerMenu();
});
- electron.ipcMain.on('enhancer:get-theme-vars', (event, arg) => {
+ electron.ipcMain.on('enhancer:set-menu-theme', (event, arg) => {
+ if (!enhancer_menu) return;
+ enhancer_menu.webContents.send('enhancer:set-menu-theme', arg);
+ });
+ electron.ipcMain.on('enhancer:get-menu-theme', (event, arg) => {
electron.webContents
.getAllWebContents()
.forEach((webContents) =>
- webContents.send('enhancer:get-theme-vars', arg)
+ webContents.send('enhancer:get-menu-theme', arg)
);
});
+ electron.ipcMain.on('enhancer:close-tab', (event, target, tab) => {
+ electron.webContents
+ .fromId(target)
+ .webContents.send('enhancer:close-tab', tab);
+ });
function calculateWindowPos(width, height) {
const screen = electron.screen.getDisplayNearestPoint({
@@ -74,13 +86,13 @@ module.exports = (store, __exports) => {
};
}
- function openExtensionMenu() {
+ function openEnhancerMenu() {
if (enhancer_menu) return enhancer_menu.show();
const window_state = require(`${helpers.__notion.replace(
/\\/g,
'/'
)}/app/node_modules/electron-window-state/index.js`)({
- file: 'menu-windowstate.json',
+ file: 'menu.windowstate.json',
path: helpers.__data,
defaultWidth: 275,
defaultHeight: 600,
@@ -88,7 +100,7 @@ module.exports = (store, __exports) => {
electron.shell.openExternal(JSON.stringify(window_state));
enhancer_menu = new electron.BrowserWindow({
show: true,
- frame: false,
+ frame: !store().frameless,
titleBarStyle: 'hiddenInset',
x:
window_state.x ||
@@ -99,7 +111,7 @@ module.exports = (store, __exports) => {
width: window_state.width,
height: window_state.height,
webPreferences: {
- preload: path.resolve(`${__dirname}/menu.js`),
+ preload: path.resolve(`${__dirname}/enhancerMenu.js`),
nodeIntegration: true,
session: electron.session.fromPartition('persist:notion'),
},
@@ -109,8 +121,11 @@ module.exports = (store, __exports) => {
window_state.saveState(enhancer_menu);
enhancer_menu = null;
});
+ // enhancer_menu.webContents.openDevTools();
}
+ // tray
+
const contextMenu = electron.Menu.buildFromTemplate([
{
type: 'normal',
@@ -156,13 +171,13 @@ module.exports = (store, __exports) => {
type: 'normal',
label: 'Enhancements',
accelerator: store().menu_toggle,
- click: openExtensionMenu,
+ click: openEnhancerMenu,
},
{
type: 'normal',
label: 'New Window',
click: () => {
- require('./create.js')(
+ require('./createWindow.js')(
store,
require(path.resolve(
`${helpers.__notion}/app/main/createWindow.js`
@@ -185,6 +200,13 @@ module.exports = (store, __exports) => {
{
type: 'separator',
},
+ {
+ label: 'Relaunch',
+ click: () => {
+ electron.app.relaunch();
+ electron.app.quit();
+ },
+ },
{
label: 'Quit',
role: 'quit',
@@ -193,16 +215,7 @@ module.exports = (store, __exports) => {
tray.setContextMenu(contextMenu);
tray.setToolTip('Notion');
- electron.globalShortcut.register(store().menu_toggle, () => {
- if (
- electron.BrowserWindow.getAllWindows()
- .filter((win) => win.getTitle() !== 'notion-enhancer menu')
- .some((win) => win.isFocused())
- ) {
- openExtensionMenu();
- } else if (enhancer_menu && enhancer_menu.isFocused())
- enhancer_menu.close();
- });
+ // hotkey
function showWindows() {
const windows = electron.BrowserWindow.getAllWindows();
diff --git a/mods/custom-inserts/mod.js b/mods/custom-inserts/mod.js
index 59c0ba0..8ae3aa4 100644
--- a/mods/custom-inserts/mod.js
+++ b/mods/custom-inserts/mod.js
@@ -12,8 +12,9 @@ module.exports = {
id: 'b4b0aced-2059-43bf-8d1d-ccd757ee5ebb',
tags: ['extension'],
name: 'custom inserts',
- desc: 'link files for small client-side tweaks.',
- version: '0.1.2',
+ desc: `link files for small client-side tweaks. (not sure how to do something? check out the
+ [tweaks](https://github.com/dragonwocky/notion-enhancer/blob/master/TWEAKS.md) collection.)`,
+ version: '0.1.3',
author: 'dragonwocky',
options: [
{
diff --git a/mods/dracula-theme/mod.js b/mods/dracula-theme/mod.js
new file mode 100644
index 0000000..cd3668a
--- /dev/null
+++ b/mods/dracula-theme/mod.js
@@ -0,0 +1,18 @@
+/*
+ * dracula-theme
+ * (c) 2020 u/mimi-shahzad
+ * (c) 2020 Dracula Theme
+ * under the MIT license
+ */
+
+'use strict';
+
+module.exports = {
+ id: '033bff54-50ba-4cec-bdc0-b2ca7e307086',
+ tags: ['theme', 'dark'],
+ name: 'dracula',
+ desc:
+ 'a theme based on the popular dracula color palette originally by zeno rocha and friends. ',
+ version: '0.1.0',
+ author: 'mimi-shahzad',
+};
diff --git a/mods/dracula-theme/styles.css b/mods/dracula-theme/styles.css
new file mode 100644
index 0000000..67e9a74
--- /dev/null
+++ b/mods/dracula-theme/styles.css
@@ -0,0 +1,186 @@
+/*
+ * dracula-theme
+ * (c) 2020 u/mimi-shahzad
+ * (c) 2020 Dracula Theme
+ * under the MIT license
+ */
+
+:root {
+ --theme_dark--main: #282a36;
+ --theme_dark--sidebar: #282a36;
+ --theme_dark--overlay: #282a36;
+ --theme_dark--dragarea: #282a36;
+
+ --theme_dark--font_sans: -apple-system, BlinkMacSystemFont, 'Segoe UI',
+ Helvetica, 'Apple Color Emoji', Arial, sans-serif, 'Segoe UI Emoji',
+ 'Segoe UI Symbol';
+
+ --theme_dark--scrollbar: #282a36;
+ --theme_dark--scrollbar_hover: #6272a4;
+
+ --theme_dark--card: #6272a4;
+ --theme_dark--gallery: #282a36;
+ --theme_dark--table-border: #6272a4;
+ --theme_dark--interactive_hover: #282a36;
+ --theme_dark--button_close: #ff5555;
+
+ --theme_dark--selected: #454158;
+ --theme_dark--primary: #bd93f9;
+ --theme_dark--primary_hover: #8be9fd;
+ --theme_dark--primary_click: #bd93f9;
+ --theme_dark--primary_indicator: #8be9fd;
+
+ --theme_dark--option_active-background: var(--theme_dark--primary);
+ --theme_dark--option_hover-background: var(--theme_dark--primary_hover);
+
+ --theme_dark--danger_text: #ff5555;
+ --theme_dark--danger_border: #ffb86c;
+
+ --theme_dark--text: #f8f8f2;
+ --theme_dark--text_ui: #f8f8f2;
+ --theme_dark--text_ui_info: #f8f8f2;
+
+ --theme_dark--text_gray: #454158;
+ --theme_dark--text_brown: #6272a4;
+ --theme_dark--text_orange: #ffb86c;
+ --theme_dark--text_yellow: #f1fa8c;
+ --theme_dark--text_green: #50fa7b;
+ --theme_dark--text_blue: #8be9fd;
+ --theme_dark--text_purple: #bd93f9;
+ --theme_dark--text_pink: #ff79c6;
+ --theme_dark--text_red: #ff5555;
+
+ --theme_dark--select-text: #000000;
+ --theme_dark--select_gray: #454158;
+ --theme_dark--select_brown: #6272a4;
+ --theme_dark--select_orange: #ffb86c;
+ --theme_dark--select_yellow: #f1fa8c;
+ --theme_dark--select_green: #50fa7b;
+ --theme_dark--select_blue: #8be9fd;
+ --theme_dark--select_purple: #bd93f9;
+ --theme_dark--select_pink: #ff79c6;
+ --theme_dark--select_red: #ff5555;
+
+ --theme_dark--bg-text: var(--theme_dark--select-text);
+ --theme_dark--bg_gray: var(--theme_dark--select_gray);
+ --theme_dark--bg_brown: var(--theme_dark--select_brown);
+ --theme_dark--bg_orange: var(--theme_dark--select_orange);
+ --theme_dark--bg_yellow: var(--theme_dark--select_yellow);
+ --theme_dark--bg_green: var(--theme_dark--select_green);
+ --theme_dark--bg_blue: var(--theme_dark--select_blue);
+ --theme_dark--bg_purple: var(--theme_dark--select_purple);
+ --theme_dark--bg_pink: var(--theme_dark--select_pink);
+ --theme_dark--bg_red: var(--theme_dark--select_red);
+
+ --theme_dark--line-text: #000000;
+ --theme_dark--line_gray: #454158;
+ --theme_dark--line_brown: #6272a4;
+ --theme_dark--line_orange: #ffb86c;
+ --theme_dark--line_yellow: #f1fa8c;
+ --theme_dark--line_green: #50fa7b;
+ --theme_dark--line_blue: #8be9fd;
+ --theme_dark--line_purple: #bd93f9;
+ --theme_dark--line_pink: #ff79c6;
+ --theme_dark--line_red: #ff5555;
+
+ --theme_dark--callout-text: var(--theme_dark--line-text);
+ --theme_dark--callout_gray: var(--theme_dark--line_gray);
+ --theme_dark--callout_brown: var(--theme_dark--line_brown);
+ --theme_dark--callout_orange: var(--theme_dark--line_orange);
+ --theme_dark--callout_yellow: var(--theme_dark--line_yellow);
+ --theme_dark--callout_green: var(--theme_dark--line_green);
+ --theme_dark--callout_blue: var(--theme_dark--line_blue);
+ --theme_dark--callout_purple: var(--theme_dark--line_purple);
+ --theme_dark--callout_pink: var(--theme_dark--line_pink);
+ --theme_dark--callout_red: var(--theme_dark--line_red);
+
+ --theme_dark--code_inline-text: #50fa7b;
+ --theme_dark--code_inline-background: #44475a;
+ --theme_dark--code-text: var(--theme_dark--text);
+ --theme_dark--code-background: #44475a;
+ --theme_dark--code_function: var(--theme_dark--text_blue);
+ --theme_dark--code_keyword: var(--theme_dark--text_pink);
+ --theme_dark--code_tag: var(--theme_dark--text_pink);
+ --theme_dark--code_operator: var(--theme_dark--text_yellow);
+ --theme_dark--code_important: var(--theme_dark--text_yellow);
+ --theme_dark--code_property: var(--theme_dark--text_pink);
+ --theme_dark--code_builtin: var(--theme_dark--text_yellow);
+ --theme_dark--code_attr-name: var(--theme_dark--text_yellow);
+ --theme_dark--code_comment: var(--theme_dark--text_ui);
+ --theme_dark--code_punctuation: var(--theme_dark--text_gray);
+ --theme_dark--code_doctype: var(--theme_dark--text_gray);
+ --theme_dark--code_number: var(--theme_dark--text_purple);
+ --theme_dark--code_string: var(--theme_dark--text_orange);
+ --theme_dark--code_attr-value: var(--theme_dark--text_orange);
+}
+
+.notion-dark-theme img[src*='/images/onboarding/use-case-note.png'],
+.notion-dark-theme
+ img[src*='/images/onboarding/team-features-illustration.png'] {
+ filter: invert(1) !important;
+}
+.notion-dark-theme img[src*='/images/onboarding/checked.svg'] {
+ filter: hue-rotate(45deg) !important;
+}
+.notion-dark-theme
+ img[style*='display: block; object-fit: cover; border-radius: 100%; width: 90px; height: 90px;'],
+.notion-dark-theme
+ img[style*='display: block; object-fit: cover; border-radius: 3px; width: 56.832px; height: 56.832px; transition: opacity 100ms ease-out 0s;'] {
+ transition: filter 0.4s ease !important;
+}
+.notion-dark-theme
+ img[style*='display: block; object-fit: cover; border-radius: 100%; width: 90px; height: 90px;']:hover,
+.notion-dark-theme
+ img[style*='display: block; object-fit: cover; border-radius: 3px; width: 56.832px; height: 56.832px; transition: opacity 100ms ease-out 0s;']:hover {
+ filter: brightness(1.2);
+}
+
+.notion-dark-theme
+ [style*='font-family: Fira Code, Menlo, Courier, monospace;'] {
+ filter: hue-rotate(170deg) !important;
+}
+
+.notion-dark-theme
+ .notion-token-remove-button[role*='button'][tabindex*='0']:hover,
+.notion-dark-theme .notion-record-icon {
+ background: transparent !important;
+}
+
+.notion-dark-theme .notion-focusable:focus-within,
+.notion-dark-theme .notion-to_do-block > div > div > div[style*='background:'],
+.notion-dark-theme div[role='button'],
+[style*='height: 4px;']
+ > .notion-selectable.notion-collection_view_page-block
+ > *,
+.notion-dark-theme .notion-calendar-view-day[style*='background: #282a36;'],
+.DayPicker-Day--today,
+.notion-dark-theme
+ .DayPicker:not(.DayPicker--interactionDisabled)
+ .DayPicker-Day--outside:hover,
+.notion-dark-theme
+ .DayPicker:not(.DayPicker--interactionDisabled)
+ .DayPicker-Day:not(.DayPicker-Day--disabled):not(.DayPicker-Day--value)
+ .DayPicker-Day.DayPicker-Day--start.DayPicker-Day--selected,
+.notion-dark-theme .DayPicker-Day.DayPicker-Day--range.DayPicker-Day--start,
+.notion-dark-theme .DayPicker-Day.DayPicker-Day--range.DayPicker-Day--end {
+ transition: color 0.4s ease, background 0.4s ease, box-shadow 0.4s ease !important;
+}
+
+.notion-dark-theme [style*='background: #282a36;'],
+.notion-dark-theme
+ [style*='background: rgb(80, 85, 88);'][style*='color: rgba(255, 255, 255, 0.7)'],
+.notion-dark-theme
+ [style*='background: rgb(80, 85, 88);'][style*='width: 18px;'][style*='height: 18px;'],
+.notion-dark-theme
+ [style*='box-shadow: rgba(15, 15, 15, 0.1) 0px 0px 0px 1px, rgba(15, 15, 15, 0.2) 0px 5px 10px, rgba(15, 15, 15, 0.4) 0px 15px 40px;'],
+.notion-dark-theme [style*='background: rgba(151, 154, 155, 0.5);'],
+.notion-dark-theme [style*='background: rgba(147, 114, 100, 0.5)'],
+.notion-dark-theme [style*='background: rgba(255, 163, 68, 0.5)'],
+.notion-dark-theme [style*='background: rgba(255, 220, 73, 0.5)'],
+.notion-dark-theme [style*='background: rgba(77, 171, 154, 0.5)'],
+.notion-dark-theme [style*='background: rgba(82, 156, 202, 0.5)'],
+.notion-dark-theme [style*='background: rgba(154, 109, 215, 0.5)'],
+.notion-dark-theme [style*='background: rgba(226, 85, 161, 0.5)'],
+.notion-dark-theme [style*='background: rgba(255, 115, 105, 0.5)'] {
+ box-shadow: 0 2px 4px rgb(0 0 0 / 66%) !important;
+}
diff --git a/mods/emoji-sets/mod.js b/mods/emoji-sets/mod.js
index 289da8b..8ceb5b5 100644
--- a/mods/emoji-sets/mod.js
+++ b/mods/emoji-sets/mod.js
@@ -29,7 +29,6 @@ module.exports = {
'joypixels',
'openmoji',
'emojidex',
- 'messenger',
'lg',
'htc',
'mozilla',
@@ -109,6 +108,15 @@ module.exports = {
el.style.display = 'none';
if (el.parentElement.getAttribute('contenteditable'))
el.remove();
+ } else if (
+ el.previousElementSibling.matches(
+ 'span[role="image"][aria-label]'
+ )
+ ) {
+ el.previousElementSibling.innerText = el.getAttribute(
+ 'alt'
+ );
+ el.setAttribute('aria-label', el.getAttribute('alt'));
}
});
} else {
@@ -116,11 +124,11 @@ module.exports = {
el.parentElement
.querySelectorAll('span[role="image"][aria-label]')
.forEach((text) => text.remove());
+ el.style.display = 'inline-block';
if (!el.style.background.includes(store().style)) {
el.style.background = `url(https://emojicdn.elk.sh/${el.getAttribute(
'aria-label'
)}?style=${store().style})`;
- el.style.display = 'inline-block';
el.style.backgroundSize = 'contain';
el.style.backgroundRepeat = 'no-repeat';
el.style.opacity = 1;
@@ -135,12 +143,3 @@ module.exports = {
},
},
};
-// span[role="image"][aria-label]
-/* */
-
-//
-//
-//
-//
-
-//
diff --git a/mods/emoji-sets/styles.css b/mods/emoji-sets/styles.css
deleted file mode 100644
index 600e758..0000000
--- a/mods/emoji-sets/styles.css
+++ /dev/null
@@ -1,5 +0,0 @@
-.notion-emoji::after {
- content: attr(aria-label, '');
- width: 1em;
- height: 1em;
-}
diff --git a/mods/focus-mode/mod.js b/mods/focus-mode/mod.js
index 3f61241..10994ac 100644
--- a/mods/focus-mode/mod.js
+++ b/mods/focus-mode/mod.js
@@ -13,6 +13,6 @@ module.exports = {
name: 'focus mode',
desc:
'hide the titlebar/menubar if the sidebar is closed (will be shown on hover).',
- version: '0.1.0',
+ version: '0.1.1',
author: 'arecsu',
};
diff --git a/mods/focus-mode/styles.css b/mods/focus-mode/styles.css
index 77f14b5..c71829f 100644
--- a/mods/focus-mode/styles.css
+++ b/mods/focus-mode/styles.css
@@ -5,6 +5,11 @@
* under the MIT license
*/
+/* add space at the bottom of the main frame when sidebar is hidden
+ * -- matches space at top for titlebar */
+.notion-dark-theme .notion-frame {
+ transition: height 100ms ease 0s;
+}
.notion-sidebar-container[style*='width: 0px;'] + .notion-frame {
height: calc(
100% - (var(--configured--dragarea_height, 10px) + 45px)
diff --git a/mods/material-ocean/mod.js b/mods/material-ocean/mod.js
new file mode 100644
index 0000000..dd3eab5
--- /dev/null
+++ b/mods/material-ocean/mod.js
@@ -0,0 +1,16 @@
+/*
+ * material ocean
+ * (c) 2020 Abubakar Yagoub (https://blacksuan19.tk)
+ * under the MIT license
+ */
+
+'use strict';
+
+module.exports = {
+ id: '69e7ccb2-4aef-484c-876d-3de1b433d2b9',
+ tags: ['theme', 'dark'],
+ name: 'material ocean',
+ desc: 'an oceanic colour palette.',
+ version: '0.1.0',
+ author: 'blacksuan19',
+};
diff --git a/mods/material-ocean/styles.css b/mods/material-ocean/styles.css
new file mode 100644
index 0000000..cb6bc4f
--- /dev/null
+++ b/mods/material-ocean/styles.css
@@ -0,0 +1,123 @@
+/*
+ * material ocean
+ * (c) 2020 Abubakar Yagoub (https://blacksuan19.tk)
+ * under the MIT license
+ */
+
+:root {
+ --ocean-main: #0f111a;
+ --ocean-sec: #00010a;
+ --ocean-accent: #ff4151;
+ --ocean-gray: #e0e0e0;
+ --ocean-brown: #d8b6a6;
+ --ocean-orange: #fde3c0;
+ --ocean-yellow: #ebcb8b;
+ --ocean-green: #a3be8c;
+ --ocean-blue: #81a1c1;
+ --ocean-purple: #b48ead;
+ --ocean-pink: #ffc0cb;
+ --ocean-red: #bf616a;
+
+ --theme_dark--main: var(--ocean-main);
+ --theme_dark--sidebar: var(--ocean-sec);
+ --theme_dark--overlay: var(--ocean-sec);
+ --theme_dark--dragarea: var(--ocean-sec);
+
+ --theme_dark--scrollbar: var(--ocean-sec);
+ --theme_dark--scrollbar_hover: var(--ocean-accent);
+
+ --theme_dark--card: var(--ocean-sec);
+ --theme_dark--gallery: var(--ocean-sec);
+ --theme_dark--table-border: rgba(255, 255, 255, 0.1);
+ --theme_dark--interactive_hover: var(--ocean-main);
+ --theme_dark--button_close: var(--ocean-accent);
+
+ --theme_dark--selected: rgba(255, 65, 81, 0.2);
+ --theme_dark--primary: var(--ocean-accent);
+ --theme_dark--primary_hover: var(--ocean-accent);
+ --theme_dark--primary_click: var(--ocean-sec);
+ --theme_dark--primary_indicator: var(--ocean-accent);
+
+ --theme_dark--option_active-background: var(--theme_dark--primary);
+ --theme_dark--option_hover-background: var(--theme_dark--primary_hover);
+
+ --theme_dark--danger_text: #eb5757;
+ --theme_dark--danger_border: rgba(235, 87, 87, 0.5);
+
+ --theme_dark--text: #ffffff;
+ --theme_dark--text_ui: var(--ocean-gray);
+ --theme_dark--text_ui_info: var(--ocean-gray);
+
+ --theme_dark--text_gray: var(--ocean-gray);
+ --theme_dark--text_brown: var(--ocean-brown);
+ --theme_dark--text_orange: var(--ocean-orange);
+ --theme_dark--text_yellow: var(--ocean-yellow);
+ --theme_dark--text_green: var(--ocean-green);
+ --theme_dark--text_blue: var(--ocean-blue);
+ --theme_dark--text_purple: var(--ocean-purple);
+ --theme_dark--text_pink: var(--ocean-pink);
+ --theme_dark--text_red: var(--ocean-red);
+
+ --theme_dark--select-text: var(--ocean-main);
+ --theme_dark--select_gray: var(--ocean-gray);
+ --theme_dark--select_brown: var(--ocean-brown);
+ --theme_dark--select_orange: var(--ocean-orange);
+ --theme_dark--select_yellow: var(--ocean-yellow);
+ --theme_dark--select_green: var(--ocean-green);
+ --theme_dark--select_blue: var(--ocean-blue);
+ --theme_dark--select_purple: var(--ocean-purple);
+ --theme_dark--select_pink: var(--ocean-pink);
+ --theme_dark--select_red: var(--ocean-red);
+
+ --theme_dark--line-text: var(--ocean-main);
+ --theme_dark--line_gray: #e0e0e089;
+ --theme_dark--line_brown: #d8b6a692;
+ --theme_dark--line_orange: #fde3c09f;
+ --theme_dark--line_yellow: #ffe6a6ad;
+ --theme_dark--line_green: #a3be8ca3;
+ --theme_dark--line_blue: #81a1c1a3;
+ --theme_dark--line_purple: #b48eada8;
+ --theme_dark--line_pink: #ffc0cbb1;
+ --theme_dark--line_red: #bf616a9e;
+
+ --theme_dark--bg-text: var(--theme_dark--select-text);
+ --theme_dark--bg_gray: var(--theme_dark--select_gray);
+ --theme_dark--bg_brown: var(--theme_dark--select_brown);
+ --theme_dark--bg_orange: var(--theme_dark--select_orange);
+ --theme_dark--bg_yellow: var(--theme_dark--select_yellow);
+ --theme_dark--bg_green: var(--theme_dark--select_green);
+ --theme_dark--bg_blue: var(--theme_dark--select_blue);
+ --theme_dark--bg_purple: var(--theme_dark--select_purple);
+ --theme_dark--bg_pink: var(--theme_dark--select_pink);
+ --theme_dark--bg_red: var(--theme_dark--select_red);
+
+ --theme_dark--callout-text: var(--theme_dark--line-text);
+ --theme_dark--callout_gray: var(--theme_dark--line_gray);
+ --theme_dark--callout_brown: var(--theme_dark--line_brown);
+ --theme_dark--callout_orange: var(--theme_dark--line_orange);
+ --theme_dark--callout_yellow: var(--theme_dark--line_yellow);
+ --theme_dark--callout_green: var(--theme_dark--line_green);
+ --theme_dark--callout_blue: var(--theme_dark--line_blue);
+ --theme_dark--callout_purple: var(--theme_dark--line_purple);
+ --theme_dark--callout_pink: var(--theme_dark--line_pink);
+ --theme_dark--callout_red: var(--theme_dark--line_red);
+
+ --theme_dark--code_inline-text: #b3f5c8;
+ --theme_dark--code_inline-background: var(--ocean-sec);
+ --theme_dark--code-text: var(--theme_dark--text);
+ --theme_dark--code-background: var(--ocean-sec);
+ --theme_dark--code_function: var(--theme_dark--text_blue);
+ --theme_dark--code_keyword: var(--theme_dark--text_pink);
+ --theme_dark--code_tag: var(--theme_dark--text_pink);
+ --theme_dark--code_operator: var(--theme_dark--text_yellow);
+ --theme_dark--code_important: var(--theme_dark--text_yellow);
+ --theme_dark--code_property: var(--theme_dark--text_pink);
+ --theme_dark--code_builtin: var(--theme_dark--text_yellow);
+ --theme_dark--code_attr-name: var(--theme_dark--text_yellow);
+ --theme_dark--code_comment: var(--theme_dark--text_gray);
+ --theme_dark--code_punctuation: var(--theme_dark--text_gray);
+ --theme_dark--code_doctype: var(--theme_dark--text_gray);
+ --theme_dark--code_number: var(--theme_dark--text_purple);
+ --theme_dark--code_string: var(--theme_dark--text_orange);
+ --theme_dark--code_attr-value: var(--theme_dark--text_orange);
+}
diff --git a/mods/neutral/mod.js b/mods/neutral/mod.js
index 8f1533a..a695dc9 100644
--- a/mods/neutral/mod.js
+++ b/mods/neutral/mod.js
@@ -12,7 +12,7 @@ module.exports = {
tags: ['theme', 'dark'],
name: 'neutral',
desc: 'smoother colours and fonts, designed to be more pleasing to the eye.',
- version: '0.1.3',
+ version: '0.1.4',
author: 'arecsu',
fonts: [
'https://rsms.me/inter/inter.css',
diff --git a/mods/neutral/styles.css b/mods/neutral/styles.css
index 8b28df9..5f6c242 100644
--- a/mods/neutral/styles.css
+++ b/mods/neutral/styles.css
@@ -143,17 +143,6 @@
padding-top: 5px !important;
} */
-/* add space at the bottom of the main frame when sidebar is hidden
- * -- matches space at top for titlebar */
-.notion-dark-theme .notion-frame {
- transition: height 300ms ease 0s;
-}
-.notion-dark-theme
- .notion-sidebar-container[style*='width: 0px;']
- + .notion-frame {
- height: calc(100vh - 40px) !important;
-}
-
/* hide sidebar "new page" button */
.notion-dark-theme
.notion-sidebar
diff --git a/mods/night-shift/mod.js b/mods/night-shift/mod.js
index 51d5702..0c29d7c 100644
--- a/mods/night-shift/mod.js
+++ b/mods/night-shift/mod.js
@@ -12,7 +12,7 @@ module.exports = {
name: 'night shift',
desc:
'sync dark/light theme with the system (overrides normal theme setting).',
- version: '0.1.0',
+ version: '0.1.1',
author: 'dragonwocky',
hacks: {
'renderer/preload.js'(store, __exports) {
@@ -27,6 +27,7 @@ module.exports = {
const observer = new MutationObserver(process);
observer.observe(notion_elem, {
attributes: true,
+ subtree: true,
});
function process(list, observer) {
const mode = `notion-app-inner notion-${
@@ -34,8 +35,7 @@ module.exports = {
? 'dark'
: 'light'
}-theme`;
- if (list[0].target.className !== mode)
- list[0].target.className = mode;
+ if (notion_elem.className !== mode) notion_elem.className = mode;
}
}
});
diff --git a/mods/right-to-left/mod.js b/mods/right-to-left/mod.js
index 270669a..3f1fb80 100644
--- a/mods/right-to-left/mod.js
+++ b/mods/right-to-left/mod.js
@@ -12,7 +12,7 @@ module.exports = {
tags: ['extension'],
name: 'right-to-left',
desc: 'enables auto rtl/ltr text direction detection.',
- version: '1.4.0',
+ version: '1.4.1',
author: 'obahareth',
hacks: {
'renderer/preload.js'(store, __exports) {
@@ -48,7 +48,9 @@ module.exports = {
function autoAlignPageContent() {
document
.querySelectorAll(
- '.notion-page-content > div[data-block-id]:not([dir]), [placeholder="Untitled"]:not([dir])'
+ `.notion-page-content > div[data-block-id]:not([dir]):not(.notion-column_list-block),
+ [placeholder="Untitled"]:not([dir]),
+ .notion-column-block > div[data-block-id]:not([dir])`
)
.forEach((block) => block.setAttribute('dir', 'auto'));
document
diff --git a/mods/tabs/mod.js b/mods/tabs/mod.js
new file mode 100644
index 0000000..7e9d7dc
--- /dev/null
+++ b/mods/tabs/mod.js
@@ -0,0 +1,49 @@
+/*
+ * 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',
+ options: [
+ {
+ key: 'select_modifier',
+ label:
+ 'tab select modifier (key+1, +2, +3, ... +9 and key+left/right arrows):',
+ type: 'select',
+ value: [
+ 'Alt',
+ 'Command',
+ 'Control',
+ 'Super',
+ 'Alt+Shift',
+ 'Command+Shift',
+ 'Control+Shift',
+ 'Super+Shift',
+ ],
+ },
+ {
+ key: 'new_tab',
+ label: 'new tab keybinding:',
+ type: 'input',
+ value: 'CommandOrControl+T',
+ },
+ {
+ key: 'close_tab',
+ label: 'close tab keybinding:',
+ type: 'input',
+ value: 'CommandOrControl+W',
+ },
+ ],
+};
diff --git a/mods/word-counter/mod.js b/mods/word-counter/mod.js
index 19edd55..ea183c1 100644
--- a/mods/word-counter/mod.js
+++ b/mods/word-counter/mod.js
@@ -54,7 +54,7 @@ module.exports = {
let queue = [],
$page = document.getElementsByClassName('notion-page-content')[0];
const DOCUMENT_OBSERVER = new MutationObserver((list, observer) => {
- if (!queue.length) requestIdleCallback(() => process(queue));
+ if (!queue.length) requestIdleCallback(() => handle(queue));
queue.push(...list);
}),
PAGE_OBSERVER = new MutationObserver(showPageWordDetails);
@@ -62,7 +62,7 @@ module.exports = {
childList: true,
subtree: true,
});
- function process(list) {
+ function handle(list) {
queue = [];
for (let { addedNodes } of list) {
if (
diff --git a/package-lock.json b/package-lock.json
new file mode 100644
index 0000000..a9ea556
--- /dev/null
+++ b/package-lock.json
@@ -0,0 +1,198 @@
+{
+ "name": "notion-enhancer",
+ "version": "0.9.1",
+ "lockfileVersion": 1,
+ "requires": true,
+ "dependencies": {
+ "@jsdevtools/file-path-filter": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/@jsdevtools/file-path-filter/-/file-path-filter-3.0.2.tgz",
+ "integrity": "sha512-+SbZG6stIE/nRF2PpRnubtuzhh4pouDsk/hEWwM5mKsSKlFfr4ziAE5VMogGG/K++i9NHbUTxxW0y4vdM678ew==",
+ "requires": {
+ "glob-to-regexp": "^0.4.1"
+ }
+ },
+ "@jsdevtools/readdir-enhanced": {
+ "version": "6.0.4",
+ "resolved": "https://registry.npmjs.org/@jsdevtools/readdir-enhanced/-/readdir-enhanced-6.0.4.tgz",
+ "integrity": "sha512-I6D6Omu6C7XWHzvlVbXeCS0FSxYYQ13XzdrFuo1K30unnRSpdt9AxY2KyJZbYJyfI2uNNidqDkG9/K/y699AjA==",
+ "requires": {
+ "@jsdevtools/file-path-filter": "^3.0.2"
+ }
+ },
+ "@types/glob": {
+ "version": "7.1.3",
+ "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.3.tgz",
+ "integrity": "sha512-SEYeGAIQIQX8NN6LDKprLjbrd5dARM5EXsd8GI/A5l0apYI1fGMWgPHSe4ZKL4eozlAyI+doUE9XbYS4xCkQ1w==",
+ "optional": true,
+ "requires": {
+ "@types/minimatch": "*",
+ "@types/node": "*"
+ }
+ },
+ "@types/minimatch": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz",
+ "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==",
+ "optional": true
+ },
+ "@types/node": {
+ "version": "14.11.2",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-14.11.2.tgz",
+ "integrity": "sha512-jiE3QIxJ8JLNcb1Ps6rDbysDhN4xa8DJJvuC9prr6w+1tIh+QAbYyNF3tyiZNLDBIuBCf4KEcV2UvQm/V60xfA==",
+ "optional": true
+ },
+ "asar": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/asar/-/asar-3.0.3.tgz",
+ "integrity": "sha512-k7zd+KoR+n8pl71PvgElcoKHrVNiSXtw7odKbyNpmgKe7EGRF9Pnu3uLOukD37EvavKwVFxOUpqXTIZC5B5Pmw==",
+ "requires": {
+ "@types/glob": "^7.1.1",
+ "chromium-pickle-js": "^0.2.0",
+ "commander": "^5.0.0",
+ "glob": "^7.1.6",
+ "minimatch": "^3.0.4"
+ }
+ },
+ "at-least-node": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz",
+ "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg=="
+ },
+ "balanced-match": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
+ "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c="
+ },
+ "brace-expansion": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "requires": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "cac": {
+ "version": "6.6.1",
+ "resolved": "https://registry.npmjs.org/cac/-/cac-6.6.1.tgz",
+ "integrity": "sha512-uhki4T3Ax68hw7Dufi0bATVAF8ayBSwOKUEJHjObPrUN4tlQ8Lf7oljpTje/mArLxYN0D743c2zJt4C1bVTCqg=="
+ },
+ "chromium-pickle-js": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/chromium-pickle-js/-/chromium-pickle-js-0.2.0.tgz",
+ "integrity": "sha1-BKEGZywYsIWrd02YPfo+oTjyIgU="
+ },
+ "commander": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz",
+ "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg=="
+ },
+ "concat-map": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+ "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
+ },
+ "fs-extra": {
+ "version": "9.0.1",
+ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.0.1.tgz",
+ "integrity": "sha512-h2iAoN838FqAFJY2/qVpzFXy+EBxfVE220PalAqQLDVsFOHLJrZvut5puAbCdNv6WJk+B8ihI+k0c7JK5erwqQ==",
+ "requires": {
+ "at-least-node": "^1.0.0",
+ "graceful-fs": "^4.2.0",
+ "jsonfile": "^6.0.1",
+ "universalify": "^1.0.0"
+ }
+ },
+ "fs.realpath": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+ "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
+ },
+ "glob": {
+ "version": "7.1.6",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
+ "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
+ "requires": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.0.4",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ }
+ },
+ "glob-to-regexp": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz",
+ "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw=="
+ },
+ "graceful-fs": {
+ "version": "4.2.4",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz",
+ "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw=="
+ },
+ "inflight": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+ "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
+ "requires": {
+ "once": "^1.3.0",
+ "wrappy": "1"
+ }
+ },
+ "inherits": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
+ },
+ "jsonfile": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.0.1.tgz",
+ "integrity": "sha512-jR2b5v7d2vIOust+w3wtFKZIfpC2pnRmFAhAC/BuweZFQR8qZzxH1OyrQ10HmdVYiXWkYUqPVsz91cG7EL2FBg==",
+ "requires": {
+ "graceful-fs": "^4.1.6",
+ "universalify": "^1.0.0"
+ }
+ },
+ "minimatch": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
+ "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
+ "requires": {
+ "brace-expansion": "^1.1.7"
+ }
+ },
+ "once": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+ "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
+ "requires": {
+ "wrappy": "1"
+ }
+ },
+ "path-is-absolute": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+ "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18="
+ },
+ "readdir-enhanced": {
+ "version": "6.0.4",
+ "resolved": "https://registry.npmjs.org/readdir-enhanced/-/readdir-enhanced-6.0.4.tgz",
+ "integrity": "sha512-MWY048D/nEpHwqdnsBiUxpqjJPkEw2i2RmY5gM2Gadn0rkHS/DhUBqrYTkOqKHF4RoUlYZZ8GnP4ymlRGuo30A==",
+ "requires": {
+ "@jsdevtools/readdir-enhanced": "6.0.4"
+ }
+ },
+ "universalify": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/universalify/-/universalify-1.0.0.tgz",
+ "integrity": "sha512-rb6X1W158d7pRQBg5gkR8uPaSfiids68LTJQYOtEUhoJUWBdaQHsuT/EUduxXYxcrt4r5PJ4fuHW1MHT6p0qug=="
+ },
+ "wrappy": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+ "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
+ }
+ }
+}
diff --git a/package.json b/package.json
index d0cc94f..a71d9c9 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "notion-enhancer",
- "version": "0.9.1",
+ "version": "0.10.0-wip",
"description": "an enhancer/customiser for the all-in-one productivity workspace notion.so",
"main": "index.js",
"bin": {
@@ -36,6 +36,7 @@
"asar": "^3.0.3",
"cac": "^6.5.12",
"fs-extra": "^9.0.1",
+ "keyboardevent-from-electron-accelerator": "^2.0.0",
"readdir-enhanced": "^6.0.3"
}
}
diff --git a/pkg/apply.js b/pkg/apply.js
index 36f95ab..9956c07 100644
--- a/pkg/apply.js
+++ b/pkg/apply.js
@@ -55,7 +55,7 @@ module.exports = async function ({ overwrite_version, friendly_errors } = {}) {
console.info(' ...unpacking app.asar.');
const asar_app = path.resolve(`${helpers.__notion}/app.asar`);
extractAll(asar_app, `${path.resolve(`${helpers.__notion}/app`)}`);
- fs.move(asar_app, path.resolve(`${helpers.__notion}/app.asar.bak`));
+ await fs.move(asar_app, path.resolve(`${helpers.__notion}/app.asar.bak`));
// patching launch script target of custom wrappers
if (
@@ -76,8 +76,8 @@ module.exports = async function ({ overwrite_version, friendly_errors } = {}) {
await fs.outputFile(
bin_path,
bin_script
- .replace('electron app.asar\n', 'electron app\n')
- .replace('electron6 app.asar\n', 'electron6 app\n')
+ .replace('electron app.asar', 'electron app')
+ .replace('electron6 app.asar', 'electron6 app')
);
}
}
@@ -90,18 +90,40 @@ module.exports = async function ({ overwrite_version, friendly_errors } = {}) {
filter: (stats) => stats.isFile() && stats.path.endsWith('.js'),
}
)) {
- insertion_target = path.resolve(
+ const insertion_file = path.resolve(
`${helpers.__notion}/app/${insertion_target}`
);
- fs.appendFile(
- insertion_target,
- `\n\n//notion-enhancer\nrequire('${helpers.realpath(
- __dirname
- )}/loader.js')(__filename, exports);`
- );
+ if (insertion_target === 'main/main.js') {
+ // https://github.com/dragonwocky/notion-enhancer/issues/160
+ // patch the notion:// url scheme/protocol to work on linux
+ fs.readFile(insertion_file, 'utf8', (err, data) => {
+ if (err) throw err;
+ fs.writeFile(
+ insertion_file,
+ `${data.replace(
+ /process.platform === "win32"/g,
+ 'process.platform === "win32" || process.platform === "linux"'
+ )}\n\n//notion-enhancer\nrequire('${helpers.realpath(
+ __dirname
+ )}/loader.js')(__filename, exports);`,
+ 'utf8',
+ (err) => {
+ if (err) throw err;
+ }
+ );
+ });
+ } else {
+ fs.appendFile(
+ insertion_file,
+ `\n\n//notion-enhancer\nrequire('${helpers.realpath(
+ __dirname
+ )}/loader.js')(__filename, exports);`
+ );
+ }
}
- // not resolved, nothing depends on it so it's just a "let it do its thing"
+ // not resolved, nothing else in application depends on it
+ // so it's just a "let it do its thing"
console.info(' ...recording enhancement version.');
fs.outputFile(
path.resolve(`${helpers.__notion}/app/ENHANCER_VERSION.txt`),
@@ -112,11 +134,25 @@ module.exports = async function ({ overwrite_version, friendly_errors } = {}) {
return true;
} catch (err) {
console.error('### ERROR ###');
- if (err.toString().includes('EACCESS') && friendly_errors) {
+ if (err.code === 'EACCES' && friendly_errors) {
console.error(
- 'file access forbidden: try again with sudo or in an elevated/admin prompt.'
+ `file access forbidden - ${
+ process.platform === 'win32'
+ ? 'make sure your user has elevated permissions.'
+ : `try running "sudo chmod -R a+wr ${err.path.replace(
+ 'Notion.app',
+ 'Notion'
+ )}" ${
+ err.dest
+ ? `and/or "sudo chmod -R a+wr ${err.dest.replace(
+ 'Notion.app',
+ 'Notion'
+ )}"`
+ : ''
+ }`
+ }`
);
- } else if (err.toString().includes('EIO') && friendly_errors) {
+ } else if (['EIO', 'EBUSY'].includes(err.code) && friendly_errors) {
console.error('file access failed: is notion running?');
} else console.error(err);
return false;
diff --git a/pkg/helpers.js b/pkg/helpers.js
index c905331..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,
@@ -140,6 +145,17 @@ function getEnhancements() {
modules.invalid.push(dir);
}
}
+ modules.loaded = modules.loaded.sort((a, b) => a.name.localeCompare(b.name));
+ const priority = require('./store.js')('mods', { priority: [] }).priority;
+ modules.loaded = [
+ ...modules.loaded.filter((m) => m.tags.includes('core')),
+ ...modules.loaded.filter(
+ (m) => !m.tags.includes('core') && !priority.includes(m.id)
+ ),
+ ...priority
+ .map((id) => modules.loaded.find((m) => m.id === id))
+ .filter((m) => m),
+ ];
return modules;
}
diff --git a/pkg/loader.js b/pkg/loader.js
index 9466004..93a92ef 100644
--- a/pkg/loader.js
+++ b/pkg/loader.js
@@ -55,9 +55,12 @@ module.exports = function (__file, __exports) {
}
const modules = helpers.getEnhancements();
- for (let mod of modules.loaded) {
+ for (let mod of [
+ ...modules.loaded.filter((m) => m.tags.includes('core')),
+ ...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 (
@@ -81,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
- ? 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);
}
}
}
diff --git a/pkg/remove.js b/pkg/remove.js
index bf28f00..5528c3a 100644
--- a/pkg/remove.js
+++ b/pkg/remove.js
@@ -103,8 +103,9 @@ module.exports = async function ({
await fs.outputFile(
bin_path,
bin_script
- .replace('electron app\n', 'electron app.asar\n')
- .replace('electron6 app\n', 'electron6 app.asar\n')
+ .replace('electron app', 'electron app.asar')
+ .replace('electron6 app', 'electron6 app.asar')
+ .replace(/(.asar)+/g, '.asar')
);
}
}
@@ -114,11 +115,25 @@ module.exports = async function ({
return true;
} catch (err) {
console.error('### ERROR ###');
- if (err.toString().includes('EACCESS') && friendly_errors) {
+ if (err.code === 'EACCES' && friendly_errors) {
console.error(
- 'file access forbidden: try again with sudo or in an elevated/admin prompt.'
+ `file access forbidden - ${
+ process.platform === 'win32'
+ ? 'make sure your user has elevated permissions.'
+ : `try running "sudo chmod -R a+wr ${err.path.replace(
+ 'Notion.app',
+ 'Notion'
+ )}" ${
+ err.dest
+ ? `and/or "sudo chmod -R a+wr ${err.dest.replace(
+ 'Notion.app',
+ 'Notion'
+ )}"`
+ : ''
+ }`
+ }`
);
- } else if (err.toString().includes('EIO') && friendly_errors) {
+ } else if (['EIO', 'EBUSY'].includes(err.code) && friendly_errors) {
console.error('file access failed: is notion running?');
} else console.error(err);
return false;
diff --git a/yarn.lock b/yarn.lock
index 42d4db4..0b9ca31 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -143,6 +143,11 @@ jsonfile@^6.0.1:
optionalDependencies:
graceful-fs "^4.1.6"
+keyboardevent-from-electron-accelerator@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/keyboardevent-from-electron-accelerator/-/keyboardevent-from-electron-accelerator-2.0.0.tgz#ace21b1aa4e47148815d160057f9edb66567c50c"
+ integrity sha512-iQcmNA0M4ETMNi0kG/q0h/43wZk7rMeKYrXP7sqKIJbHkTU8Koowgzv+ieR/vWJbOwxx5nDC3UnudZ0aLSu4VA==
+
minimatch@^3.0.4:
version "3.0.4"
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"