diff --git a/scripts/patch-desktop-app.mjs b/scripts/patch-desktop-app.mjs index 7753919..71b5975 100755 --- a/scripts/patch-desktop-app.mjs +++ b/scripts/patch-desktop-app.mjs @@ -9,7 +9,7 @@ const injectTriggerOnce = (file, content) => content + (!/require\(['|"]notion-enhancer['|"]\)/.test(content) - ? `\n\nrequire("notion-enhancer")('${file}',exports,(js)=>eval(js));` + ? `\n\nrequire("notion-enhancer")("${file}",exports,(js)=>eval(js));` : ""), replaceIfNotFound = ({ string, mode = "replace" }, search, replacement) => string.includes(replacement) @@ -59,18 +59,11 @@ const patches = { protocolInterceptor = `{const n="notion://www.notion.so/__notion-enhancer/";if(e.url.startsWith(n))return require("electron").net.fetch(\`file://\${require("path").join(__dirname,"..","..","node_modules","notion-enhancer",e.url.slice(n.length))}\`)}`; prepend(protocolHandler, protocolInterceptor); - // expose the app config to the global namespace for manipulation - // e.g. to enable development mode + // expose the app's config + cache + preferences to the global namespace + // e.g. to enable development mode or check if keep in background is enabled prepend(/\w\.exports=JSON\.parse\('\{"env":"production"/, "globalThis.__notionConfig="); - - // expose the app store to the global namespace for reading - // e.g. to check if keep in background is enabled - prepend(/\w\.Store=\(0,\w\.configureStore\)/, "globalThis.__notionStore="); prepend(/\w\.updatePreferences=\w\.updatePreferences/, "globalThis.__updatePreferences="); - - // conditionally create frameless windows - const titlebarStyle = `titleBarStyle:globalThis.__notionConfig?.titlebarStyle??"hiddenInset"`; - replace(`titleBarStyle:"hiddenInset"`, titlebarStyle); + prepend(/\w\.Store=\(0,\w\.configureStore\)/, "globalThis.__notionStore="); return content; }, diff --git a/src/api/interface.mjs b/src/api/interface.mjs index 6800dd2..8f8a24f 100644 --- a/src/api/interface.mjs +++ b/src/api/interface.mjs @@ -100,7 +100,7 @@ let documentObserver, characterData: true, // whether to observe added/removed nodes childList: true, - // whether to observe parent/descendant nodes + // whether to observe nested nodes subtree: true, }, mutationListeners = []; diff --git a/src/extensions/focus-mode/client.css b/src/extensions/focus-mode/client.css deleted file mode 100644 index d615b0c..0000000 --- a/src/extensions/focus-mode/client.css +++ /dev/null @@ -1,21 +0,0 @@ -/** - * notion-enhancer: focus mode - * (c) 2020 Arecsu - * (c) 2021 dragonwocky (https://dragonwocky.me/) - * (https://notion-enhancer.github.io/) under the MIT license - */ - -.notion-sidebar-container[style*='width: 0px;'] ~ div .notion-topbar > :first-child { - opacity: 0 !important; - transition: opacity 200ms ease-in-out !important; -} -.notion-sidebar-container[style*='width: 0px;'] ~ div .notion-topbar > :first-child:hover { - opacity: 1 !important; -} - -[data-focus-mode='padded'] - .notion-sidebar-container[style*='width: 0px;'] - ~ div - .notion-frame { - height: calc(100vh - 90px) !important; -} diff --git a/src/extensions/focus-mode/client.mjs b/src/extensions/focus-mode/client.mjs deleted file mode 100644 index 8423026..0000000 --- a/src/extensions/focus-mode/client.mjs +++ /dev/null @@ -1,12 +0,0 @@ -/** - * notion-enhancer: focus mode - * (c) 2020 Arecsu - * (c) 2021 dragonwocky (https://dragonwocky.me/) - * (https://notion-enhancer.github.io/) under the MIT license - */ - -'use strict'; - -export default async function (api, db) { - if (await db.get(['padded'])) document.body.dataset.focusMode = 'padded'; -} diff --git a/src/extensions/focus-mode/mod.json b/src/extensions/focus-mode/mod.json deleted file mode 100644 index 0ffb3c8..0000000 --- a/src/extensions/focus-mode/mod.json +++ /dev/null @@ -1,39 +0,0 @@ -{ - "name": "focus mode", - "id": "5a08598d-bfac-4167-9ae8-2bd0e2ef141e", - "version": "0.3.0", - "description": "hide the titlebar/menubar when the sidebar is closed (returns on hover).", - "tags": ["extension", "layout"], - "authors": [ - { - "name": "arecsu", - "email": "alejandro9r@gmail.com", - "homepage": "https://github.com/Arecsu", - "avatar": "https://avatars.githubusercontent.com/u/12679098" - } - ], - "css": { - "frame": ["tabs.css"], - "client": ["client.css"] - }, - "js": { - "frame": ["tabs.mjs"], - "client": ["client.mjs"] - }, - "options": [ - { - "type": "toggle", - "key": "padded", - "label": "even padding", - "tooltip": "matches the empty space at the top and sides of the frame with **extra padding at the bottom when the sidebar is hidden**", - "value": true - }, - { - "type": "toggle", - "key": "tabs", - "label": "hide tabs", - "tooltip": "makes the tab bar transparent unless hovered over", - "value": false - } - ] -} diff --git a/src/extensions/focus-mode/tabs.css b/src/extensions/focus-mode/tabs.css deleted file mode 100644 index 8b0414f..0000000 --- a/src/extensions/focus-mode/tabs.css +++ /dev/null @@ -1,14 +0,0 @@ -/** - * notion-enhancer: focus mode - * (c) 2021 dragonwocky (https://dragonwocky.me/) - * (https://notion-enhancer.github.io/) under the MIT license - */ - -[data-focus-mode='hide-tabs'] header:not(:hover) { - background: var(--theme--bg); - border-bottom-color: transparent; -} -[data-focus-mode='hide-tabs'] header:not(:hover) > * { - opacity: 0; - transition: opacity 200ms ease-in-out; -} diff --git a/src/extensions/focus-mode/tabs.mjs b/src/extensions/focus-mode/tabs.mjs deleted file mode 100644 index 6074834..0000000 --- a/src/extensions/focus-mode/tabs.mjs +++ /dev/null @@ -1,12 +0,0 @@ -/** - * notion-enhancer: focus mode - * (c) 2020 Arecsu - * (c) 2021 dragonwocky (https://dragonwocky.me/) - * (https://notion-enhancer.github.io/) under the MIT license - */ - -'use strict'; - -export default async function (api, db) { - if (await db.get(['tabs'])) document.body.dataset.focusMode = 'hide-tabs'; -} diff --git a/src/extensions/focus/client.css b/src/extensions/focus/client.css new file mode 100644 index 0000000..8f4444b --- /dev/null +++ b/src/extensions/focus/client.css @@ -0,0 +1,23 @@ +/** + * notion-enhancer: focus + * (c) 2020 Arecsu + * (c) 2024 dragonwocky (https://dragonwocky.me/) + * (https://notion-enhancer.github.io/) under the MIT license + */ + +/* hide topbar */ +.notion-sidebar-container[aria-hidden] ~ div .notion-topbar { + opacity: 0 !important; + transition: opacity 200ms ease-in-out !important; +} +.notion-sidebar-container[aria-hidden] ~ div .notion-topbar:hover { + opacity: 1 !important; +} + +/* hide tabs */ +body > #root.sidebar-collapsed { + transition: opacity 200ms ease-in-out; +} +body > #root.sidebar-collapsed:not(:hover) { + opacity: 0; +} diff --git a/src/extensions/focus/client.mjs b/src/extensions/focus/client.mjs new file mode 100644 index 0000000..e3104ed --- /dev/null +++ b/src/extensions/focus/client.mjs @@ -0,0 +1,23 @@ +/** + * notion-enhancer: focus + * (c) 2020 Arecsu + * (c) 2024 dragonwocky (https://dragonwocky.me/) + * (https://notion-enhancer.github.io/) under the MIT license + */ + +export default async (api, db) => { + // tabs can only be hidden in the desktop app + const { platform, sendMessage, addMutationListener } = api; + if (!["linux", "win32", "darwin"].includes(platform)) return; + + let _state; + const sidebar = ".notion-sidebar-container", + onUpdate = () => { + const $sidebar = document.querySelector(sidebar), + state = $sidebar.hasAttribute("aria-hidden") ? "collapsed" : "pinned"; + if (state === _state) return; + sendMessage("notion-enhancer:focus", "sidebar-" + (_state = state)); + }; + addMutationListener(sidebar, onUpdate, { childList: false, subtree: false }); + onUpdate(); +}; diff --git a/src/extensions/focus/electron.cjs b/src/extensions/focus/electron.cjs new file mode 100644 index 0000000..370208c --- /dev/null +++ b/src/extensions/focus/electron.cjs @@ -0,0 +1,17 @@ +/** + * notion-enhancer: focus + * (c) 2020 Arecsu + * (c) 2024 dragonwocky (https://dragonwocky.me/) + * (https://notion-enhancer.github.io/) under the MIT license + */ + +"use strict"; + +module.exports = async (api, db) => { + const { ipcMain, BrowserWindow } = require("electron"), + channel = "notion-enhancer:focus"; + ipcMain.on(channel, ({ sender }, message) => { + const views = BrowserWindow.fromWebContents(sender).getBrowserViews(); + for (const view of views) view.webContents.send(channel, message); + }); +}; diff --git a/src/extensions/focus/mod.json b/src/extensions/focus/mod.json new file mode 100644 index 0000000..1d618cd --- /dev/null +++ b/src/extensions/focus/mod.json @@ -0,0 +1,25 @@ +{ + "name": "Focus", + "version": "0.4.0", + "id": "5a08598d-bfac-4167-9ae8-2bd0e2ef141e", + "description": "Enter focus mode when the left sidebar is closed, hiding Notion's extraneous interface elements (e.g. the topbar) until they are hovered over.", + "tags": ["productivity", "focus-mode"], + "authors": [ + { + "name": "dragonwocky", + "homepage": "https://dragonwocky.me/", + "avatar": "https://dragonwocky.me/avatar.jpg" + }, + { + "name": "Arecsu", + "homepage": "https://github.com/Arecsu", + "avatar": "https://avatars.githubusercontent.com/u/12679098" + } + ], + "clientStyles": ["client.css"], + "clientScripts": ["client.mjs"], + "electronScripts": [ + [".webpack/main/index.js", "electron.cjs"], + [".webpack/renderer/tabs/preload.js", "tabs.cjs"] + ] +} diff --git a/src/extensions/focus/tabs.cjs b/src/extensions/focus/tabs.cjs new file mode 100644 index 0000000..fa21713 --- /dev/null +++ b/src/extensions/focus/tabs.cjs @@ -0,0 +1,18 @@ +/** + * notion-enhancer: focus + * (c) 2020 Arecsu + * (c) 2021 dragonwocky (https://dragonwocky.me/) + * (https://notion-enhancer.github.io/) under the MIT license + */ + +"use strict"; + +module.exports = async (api, db) => { + const { onMessage } = api, + focusClass = "sidebar-collapsed"; + onMessage("notion-enhancer:focus", (message) => { + const $root = document.querySelector("#root"); + if (message === "sidebar-pinned") $root?.classList.remove(focusClass); + if (message === "sidebar-collapsed") $root?.classList.add(focusClass); + }); +}; diff --git a/src/extensions/fonts/client.mjs b/src/extensions/fonts/client.mjs index f738505..7a22e68 100644 --- a/src/extensions/fonts/client.mjs +++ b/src/extensions/fonts/client.mjs @@ -6,9 +6,8 @@ * (https://notion-enhancer.github.io/) under the MIT license */ -"use strict"; - export default async (api, db) => { + const $root = document.documentElement; for (const style of [ "sans", "serif", @@ -19,7 +18,6 @@ export default async (api, db) => { "headings", ]) { const font = await db.get(style); - if (!font) continue; - document.documentElement.style.setProperty(`--font--${style}`, font); + if (font) $root.style.setProperty(`--font--${style}`, font); } }; diff --git a/src/extensions/fonts/mod.json b/src/extensions/fonts/mod.json index 9e01474..c2c0d46 100644 --- a/src/extensions/fonts/mod.json +++ b/src/extensions/fonts/mod.json @@ -5,15 +5,15 @@ "description": "Replace Notion's default fonts with any font installed on your system.", "tags": ["customisation", "font-chooser"], "authors": [ - { - "name": "TorchAtlas", - "homepage": "https://github.com/torchatlas/", - "avatar": "https://avatars.githubusercontent.com/u/12666855" - }, { "name": "dragonwocky", "homepage": "https://dragonwocky.me/", "avatar": "https://dragonwocky.me/avatar.jpg" + }, + { + "name": "TorchAtlas", + "homepage": "https://github.com/torchatlas/", + "avatar": "https://avatars.githubusercontent.com/u/12666855" } ], "options": [ diff --git a/src/extensions/topbar/electron.cjs b/src/extensions/topbar/electron.cjs index 1f7f929..1660f71 100644 --- a/src/extensions/topbar/electron.cjs +++ b/src/extensions/topbar/electron.cjs @@ -6,7 +6,7 @@ "use strict"; -module.exports = async ({}, db) => { +module.exports = async (api, db) => { const { ipcMain, BrowserWindow } = require("electron"); ipcMain.on("notion-enhancer:topbar", ({ sender }, message) => { const window = BrowserWindow.fromWebContents(sender); diff --git a/src/extensions/tweaks/client.css b/src/extensions/tweaks/client.css index c8dcd43..98b7864 100644 --- a/src/extensions/tweaks/client.css +++ b/src/extensions/tweaks/client.css @@ -1,8 +1,8 @@ /** * notion-enhancer: tweaks * (c) 2024 1280px - * (c) 2021 dragonwocky (https://dragonwocky.me/) - * (c) 2020 arecsu + * (c) 2020 Arecsu + * (c) 2024 dragonwocky (https://dragonwocky.me/) * (https://notion-enhancer.github.io/) under the MIT license */ diff --git a/src/init.js b/src/init.js index c691a0b..9ab81a2 100644 --- a/src/init.js +++ b/src/init.js @@ -18,11 +18,7 @@ if (isElectron()) { require("./api/registry.js"); const { enhancerUrl } = globalThis.__enhancerApi, - { getMods, isEnabled, modDatabase } = globalThis.__enhancerApi, - API_LOADED = new Promise((res) => { - const onReady = globalThis.__enhancerReady; - globalThis.__enhancerReady = () => (onReady?.(), res()); - }); + { getMods, isEnabled, modDatabase } = globalThis.__enhancerApi; module.exports = async (target, __exports, __eval) => { const __getApi = () => globalThis.__enhancerApi; @@ -41,10 +37,12 @@ if (isElectron()) { document.head.append($script); // register user-provided javascript for execution in-app - const { webFrame } = require("electron"), - db = await modDatabase("0f0bf8b6-eae6-4273-b307-8fc43f2ee082"), - customScript = (await db.get("customScript"))?.content; - if (customScript) webFrame.executeJavaScript(customScript); + if (target === ".webpack/renderer/tab_browser_view/preload.js") { + const { webFrame } = require("electron"), + db = await modDatabase("0f0bf8b6-eae6-4273-b307-8fc43f2ee082"), + customScript = (await db.get("customScript"))?.content; + if (customScript) webFrame.executeJavaScript(customScript); + } }); } @@ -55,7 +53,7 @@ if (isElectron()) { for (let [scriptTarget, script] of mod.electronScripts ?? []) { if (target !== scriptTarget) continue; script = require(`./${mod._src}/${script}`); - API_LOADED.then(() => script(__getApi(), db, __exports, __eval)); + script(__getApi(), db, __exports, __eval); } } }; diff --git a/src/load.mjs b/src/load.mjs index 1d47870..1c49c04 100644 --- a/src/load.mjs +++ b/src/load.mjs @@ -14,11 +14,11 @@ export default (async () => { signedIn = localStorage["LRU:KeyValueStore2:current-user-id"], pageLoaded = /(^\/$)|((-|\/)[0-9a-f]{32}((\?.+)|$))/.test(location.pathname), IS_MENU = location.href.startsWith(enhancerUrl("core/menu/index.html")), - IS_TABS = /\/app\/\.webpack\/renderer\/(draggable_)?tabs\/index.html$/.test(location.href), + IS_TABS = /\.webpack\/renderer\/tabs\/index.html$/.test(location.href), IS_ELECTRON = ['linux', 'win32', 'darwin'].includes(platform), API_LOADED = new Promise((res, rej) => { - const onReady = globalThis.__enhancerReady; - globalThis.__enhancerReady = () => (onReady?.(), res()); + const onReady = globalThis.__enhancerApi.onReady; + globalThis.__enhancerApi.onReady = () => (onReady?.(), res()); }); globalThis.IS_TABS = IS_TABS; @@ -72,11 +72,11 @@ export default (async () => { Promise.resolve(isCore || API_LOADED) .then(() => import(enhancerUrl(`${mod._src}/${script}`))) .then((script) => script.default(globalThis.__enhancerApi, db)) - .then(() => !isCore || globalThis.__enhancerReady?.()); + .then(() => !isCore || globalThis.__enhancerApi.onReady?.()); } } - if (IS_MENU || IS_TABS) globalThis.__enhancerReady?.(); + if (IS_MENU || IS_TABS) globalThis.__enhancerApi.onReady?.(); return API_LOADED.then(() => { if (IS_MENU) console.log("notion-enhancer: ready"); return globalThis.__enhancerApi; diff --git a/src/registry.json b/src/registry.json index cd93a1f..0a288dd 100644 --- a/src/registry.json +++ b/src/registry.json @@ -7,5 +7,6 @@ "extensions/outliner", "extensions/word-counter", "extensions/no-peeking", + "extensions/focus", "themes/classic-dark" ] diff --git a/src/themes/neutral/mod.json b/src/themes/neutral/mod.json index dc17747..f8d7f65 100644 --- a/src/themes/neutral/mod.json +++ b/src/themes/neutral/mod.json @@ -7,7 +7,7 @@ "tags": ["theme", "dark"], "authors": [ { - "name": "arecsu", + "name": "Arecsu", "email": "alejandro9r@gmail.com", "homepage": "https://github.com/Arecsu", "avatar": "https://avatars.githubusercontent.com/u/12679098" diff --git a/src/worker.js b/src/worker.js index 8328e48..9d77973 100644 --- a/src/worker.js +++ b/src/worker.js @@ -215,4 +215,3 @@ if (IS_ELECTRON) { } Object.assign((globalThis.__enhancerApi ??= {}), { queryDatabase }); -globalThis.__enhancerReady?.();