diff --git a/LICENSE b/LICENSE index b503961..78b49b6 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2021 dragonwocky (https://dragonwocky.me/) +Copyright (c) 2022 dragonwocky (https://dragonwocky.me/) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/scripts/enhance-desktop-app.mjs b/scripts/enhance-desktop-app.mjs index 5cdfb54..b7f784f 100755 --- a/scripts/enhance-desktop-app.mjs +++ b/scripts/enhance-desktop-app.mjs @@ -121,15 +121,7 @@ const unpackApp = async () => { insertPath = getResourcePath("app/node_modules/notion-enhancer"); if (existsSync(insertPath)) await fsp.rm(insertPath, { recursive: true }); // insert the notion-enhancer/src folder into notion's node_modules folder - const excludedDests = [ - getResourcePath("app/node_modules/notion-enhancer/browser"), - getResourcePath("app/node_modules/notion-enhancer/manifest.json"), - ]; - await fsp.cp(srcPath, insertPath, { - recursive: true, - // exclude browser-specific files - filter: (_, dest) => !excludedDests.includes(dest), - }); + await fsp.cp(srcPath, insertPath, { recursive: true }); // call patch-desktop-app.mjs on each file // prettier-ignore const notionScripts = (await readdirDeep(appPath)) diff --git a/src/api/browser.js b/src/api/browser.js index 67ac0dd..4f4d91e 100644 --- a/src/api/browser.js +++ b/src/api/browser.js @@ -20,7 +20,21 @@ const readFile = async (file) => { const res = await fetch(file); return await res.json(); }, - reloadApp = () => chrome.runtime.sendMessage({ action: "reload" }); + reloadApp = () => { + chrome.runtime.sendMessage({ + channel: "notion-enhancer", + message: "reload-app", + }); + }; + +const sendMessage = (channel, message) => { + chrome.runtime.sendMessage({ channel, message }); + }, + onMessage = (channel, listener) => { + chrome.runtime.onMessage.addListener((msg) => { + if (msg?.channel === channel) listener(msg.message); + }); + }; const initDatabase = (namespace, fallbacks = {}) => { if (Array.isArray(namespace)) namespace = namespace.join("__"); @@ -66,5 +80,7 @@ Object.assign(globalThis.__enhancerApi, { readFile, readJson, reloadApp, + sendMessage, + onMessage, initDatabase, }); diff --git a/src/api/electron.cjs b/src/api/electron.cjs index 667238b..bd32d36 100644 --- a/src/api/electron.cjs +++ b/src/api/electron.cjs @@ -37,6 +37,15 @@ const readFile = (file) => { app.exit(); }; +const sendMessage = (channel, message) => { + const { ipcRenderer } = require("electron"); + ipcRenderer.send(channel, message); + }, + onMessage = (channel, listener) => { + const { ipcRenderer } = require("electron"); + ipcRenderer.on(channel, listener); + }; + let __db; const initDatabase = (namespace, fallbacks = {}) => { if (Array.isArray(namespace)) namespace = namespace.join("__"); @@ -97,5 +106,7 @@ Object.assign(globalThis.__enhancerApi, { readFile, readJson, reloadApp, + sendMessage, + onMessage, initDatabase, }); diff --git a/src/core/client.mjs b/src/core/client.mjs index 496c4c0..f4a3377 100644 --- a/src/core/client.mjs +++ b/src/core/client.mjs @@ -7,7 +7,7 @@ const notionSidebar = `.notion-sidebar-container .notion-sidebar > :nth-child(3) > div > :nth-child(2)`; export default async (api, db) => { - const { enhancerUrl, platform } = api, + const { platform, enhancerUrl, onMessage, sendMessage } = api, { html, addMutationListener, addKeyListener } = api, openMenuHotkey = await db.get("openMenuHotkey"), menuButtonIconStyle = await db.get("menuButtonIconStyle"), @@ -34,18 +34,41 @@ export default async (api, db) => { // menu let $menuModal, $menuFrame; - const getTheme = () => { - return document.body.classList.contains("dark") ? "dark" : "light"; + const setTheme = () => { + if (platform !== "browser") $menuFrame.contentWindow.__enhancerApi = api; + const msg = { + namespace: "notion-enhancer", + mode: document.body.classList.contains("dark") ? "dark" : "light", + }; + $menuFrame.contentWindow.postMessage(msg, "*"); }, openMenu = () => { if (!$menuFrame) return; - const msg = { namespace: "notion-enhancer", mode: getTheme() }; - if (platform !== "browser") $menuFrame.contentWindow.__enhancerApi = api; - $menuFrame.contentWindow.postMessage(msg, "*"); + setTheme(); $menuModal.setAttribute("data-open", true); }, closeMenu = () => $menuModal.removeAttribute("data-open"); + $menuFrame = html``; + $menuModal = html`
+
+
+ ${$menuFrame} +
+
`; + document.body.append($menuModal); + const $menuButton = html`
{ }); document.querySelector(notionSidebar)?.append($menuButton); - $menuModal = html`
-
-
- -
-
`; - document.body.append($menuModal); - + onMessage("notion-enhancer", (message) => { + if (message === "open-menu") openMenu(); + }); addKeyListener(openMenuHotkey, (event) => { event.preventDefault(); openMenu(); @@ -97,4 +104,6 @@ export default async (api, db) => { if (document.activeElement?.nodeName === "INPUT") return; closeMenu(); }); + + sendMessage("notion-enhancer", "load-complete"); }; diff --git a/src/core/menu/menu.mjs b/src/core/menu/menu.mjs index 3a37c17..2922e35 100644 --- a/src/core/menu/menu.mjs +++ b/src/core/menu/menu.mjs @@ -37,5 +37,4 @@ window.addEventListener("message", async (event) => { updateTheme(event.data?.mode); await importApi(); await importStyles(); - console.log(globalThis.__enhancerApi); }); diff --git a/src/manifest.json b/src/manifest.json index 57b0ccc..ade0312 100644 --- a/src/manifest.json +++ b/src/manifest.json @@ -5,6 +5,10 @@ "author": "dragonwocky (https://dragonwocky.me/)", "description": "an enhancer/customiser for the all-in-one productivity workspace notion.so", "homepage_url": "https://notion-enhancer.github.io", + "content_scripts": [{ "matches": ["*://*.notion.so/*"], "js": ["/init.js"] }], + "background": { "service_worker": "/worker.js" }, + "options_page": "/core/menu/index.html", + "action": {}, "icons": { "16": "/assets/colour-x16.png", "32": "/assets/colour-x32.png", @@ -13,7 +17,6 @@ "256": "/assets/colour-x256.png", "512": "/assets/colour-x512.png" }, - "action": {}, "permissions": [ "tabs", "storage", @@ -22,14 +25,6 @@ "unlimitedStorage" ], "host_permissions": ["*://*.notion.so/*"], - "background": { "service_worker": "/worker.mjs" }, - "options_page": "/core/menu/index.html", - "content_scripts": [ - { - "matches": ["*://*.notion.so/*"], - "js": ["/init.js"] - } - ], "web_accessible_resources": [ { "matches": ["*://*.notion.so/*"], diff --git a/src/worker.js b/src/worker.js new file mode 100644 index 0000000..dcfa9b9 --- /dev/null +++ b/src/worker.js @@ -0,0 +1,53 @@ +/* + * notion-enhancer + * (c) 2022 dragonwocky (https://dragonwocky.me/) + * (https://notion-enhancer.github.io/) under the MIT license + */ + +"use strict"; + +const notionUrl = "https://www.notion.so/", + isNotionTab = (tab) => tab?.url?.startsWith(notionUrl); + +const tabQueue = new Set(), + openEnhancerMenu = async (tab) => { + if (!isNotionTab(tab)) { + const openTabs = await chrome.tabs.query({ + windowId: chrome.windows.WINDOW_ID_CURRENT, + }); + tab = openTabs.find(isNotionTab); + tab ??= await chrome.tabs.create({ url: notionUrl }); + } + chrome.tabs.highlight({ tabs: [tab.index] }); + if (tab.status === "complete") { + chrome.tabs.sendMessage(tab.id, { + channel: "notion-enhancer", + message: "open-menu", + }); + } else tabQueue.add(tab.id); + }; + +const reloadNotionTabs = async () => { + const openTabs = await chrome.tabs.query({ + windowId: chrome.windows.WINDOW_ID_CURRENT, + }), + notionTabs = openTabs.filter(isNotionTab); + notionTabs.forEach((tab) => chrome.tabs.reload(tab.id)); +}; + +chrome.action.onClicked.addListener(openEnhancerMenu); +chrome.runtime.onMessage.addListener((msg, sender) => { + if (msg?.channel !== "notion-enhancer") return; + if (sender.tab && msg.message === "load-complete") { + if (tabQueue.has(sender.tab.id)) { + chrome.tabs.sendMessage(sender.tab.id, { + channel: "notion-enhancer", + message: "open-menu", + }); + tabQueue.delete(sender.tab.id); + } + } else if (msg.message === "reload-app") { + reloadNotionTabs(); + } + return true; +}); diff --git a/src/worker.mjs b/src/worker.mjs deleted file mode 100644 index f31a373..0000000 --- a/src/worker.mjs +++ /dev/null @@ -1,47 +0,0 @@ -/* - * notion-enhancer - * (c) 2021 dragonwocky (https://dragonwocky.me/) - * (https://notion-enhancer.github.io/) under the MIT license - */ - -"use strict"; - -// function focusMenu() { -// chrome.tabs.query({ windowId: chrome.windows.WINDOW_ID_CURRENT }, (tabs) => { -// const url = chrome.runtime.getURL("repo/menu/menu.html"), -// menu = tabs.find((tab) => tab.url.startsWith(url)); -// if (menu) { -// chrome.tabs.highlight({ tabs: menu.index }); -// } else chrome.tabs.create({ url }); -// }); -// } -// chrome.browserAction.onClicked.addListener(focusMenu); - -// function reload() { -// chrome.tabs.query({ windowId: chrome.windows.WINDOW_ID_CURRENT }, (tabs) => { -// const menu = chrome.runtime.getURL("repo/menu/menu.html"); -// tabs.forEach((tab) => { -// const url = new URL(tab.url), -// matches = -// url.host.endsWith(".notion.so") || -// url.host.endsWith(".notion.site") || -// tab.url.startsWith(menu); -// if (matches) chrome.tabs.reload(tab.id); -// }); -// }); -// } - -// chrome.runtime.onMessage.addListener((request, sender, sendResponse) => { -// switch (request.action) { -// case "focusMenu": -// focusMenu(); -// break; -// case "focusNotion": -// focusNotion(); -// break; -// case "reload": -// reload(); -// break; -// } -// return true; -// });