diff --git a/src/api/electron.cjs b/src/api/electron.cjs index cabd997..722ab34 100644 --- a/src/api/electron.cjs +++ b/src/api/electron.cjs @@ -72,10 +72,10 @@ const initDatabase = (namespace, fallbacks = {}) => { // schema: // - ("agreedToTerms") -> boolean + // - ("telemetryEnabled") -> boolean // - ("profileIds") -> $profileId[] // - ("activeProfile") -> $profileId // - $profileId: ("profileName") -> string - // - $profileId: ("telemetryEnabled") -> boolean // - $profileId__enabledMods: ($modId) -> boolean // - $profileId__$modId: ($optionKey) -> value diff --git a/src/core/client.mjs b/src/core/client.mjs index bd4542e..dc8d0a8 100644 --- a/src/core/client.mjs +++ b/src/core/client.mjs @@ -5,186 +5,128 @@ */ import { checkForUpdate } from "./update.mjs"; +import { Frame, Modal, Button } from "./components.mjs"; -const notionSidebar = `.notion-sidebar-container .notion-sidebar > :nth-child(3) > div > :nth-child(2)`; +// prettier-ignore +const asyncFilter = async (arr, predicate) => Promise.all(arr.map(predicate)) + .then((results) => arr.filter((_v, index) => results[index])); -function SidebarButton( - { icon, notifications, themeOverridesLoaded, ...props }, - ...children -) { - const { html } = globalThis.__enhancerApi; - return html`
`; -} - -export default async (api, db) => { - const { - html, - platform, - version, - getMods, - isEnabled, - enhancerUrl, - onMessage, - sendMessage, - addMutationListener, - addKeyListener, - initDatabase, - } = api, - openMenuHotkey = await db.get("openMenuHotkey"), - menuButtonIconStyle = await db.get("menuButtonIconStyle"), - loadThemeOverrides = await db.get("loadThemeOverrides"), - customStyles = (await db.get("customStyles"))?.content; - - // appearance - - const enabledThemes = (await getMods("themes")).map((theme) => - isEnabled(theme.id) - ), - forceLoadOverrides = loadThemeOverrides === "Enabled", - autoLoadOverrides = - loadThemeOverrides === "Auto" && - (await Promise.all(enabledThemes)).some((enabled) => enabled); - if (forceLoadOverrides || autoLoadOverrides) { +const doThemeOverride = async (db) => { + const { getMods, isEnabled } = globalThis.__enhancerApi, + enabledFilter = (theme) => isEnabled(theme.id), + overrideThemes = await db.get("loadThemeOverrides"), + enabledThemes = await asyncFilter(await getMods("themes"), enabledFilter); + return ( + overrideThemes === "Enabled" || + (overrideThemes === "Auto" && enabledThemes.length) + ); + }, + overrideThemes = async (db) => { + const { html, enhancerUrl } = globalThis.__enhancerApi; + if (!(await doThemeOverride(db))) return; document.head.append(html``); - } - - if (customStyles) { - const $customStyles = html``; - document.head.append($customStyles); - } - - // menu - - let $menuModal, $menuFrame, _notionTheme; - const updateTheme = (force = false) => { - const darkMode = document.body.classList.contains("dark"), - notionTheme = darkMode ? "dark" : "light"; - if (notionTheme !== _notionTheme || force) { - _notionTheme = notionTheme; - const msg = { - namespace: "notion-enhancer", - hotkey: openMenuHotkey, - theme: notionTheme, - icon: menuButtonIconStyle, - }; - $menuFrame?.contentWindow.postMessage(msg, "*"); - } + `); }; - const openMenu = () => { - updateTheme(true); - $menuModal?.setAttribute("open", true); - $menuFrame?.contentWindow.focus(); - }, - closeMenu = () => $menuModal?.removeAttribute("open"); +const insertMenu = async (db) => { + const notionSidebar = `.notion-sidebar-container .notion-sidebar > :nth-child(3) > div > :nth-child(2)`, + { html, addKeyListener, addMutationListener } = globalThis.__enhancerApi, + { platform, enhancerUrl, onMessage } = globalThis.__enhancerApi, + menuButtonIconStyle = await db.get("menuButtonIconStyle"), + openMenuHotkey = await db.get("openMenuHotkey"), + renderPing = { + namespace: "notion-enhancer", + hotkey: openMenuHotkey, + icon: menuButtonIconStyle, + }; - $menuFrame = html``; - $menuModal = html` `; - document.body.append($menuModal); + let _contentWindow; + const sendThemePing = () => { + if (!_contentWindow) return; + const darkMode = document.body.classList.contains("dark"), + notionTheme = darkMode ? "dark" : "light"; + if (renderPing.theme === notionTheme) return; + renderPing.theme = notionTheme; + _contentWindow.postMessage(renderPing, "*"); + }, + sendRenderPing = (contentWindow) => { + _contentWindow ??= contentWindow; + if (!$modal.hasAttribute("open")) return; + delete renderPing.theme; + _contentWindow.focus(); + sendThemePing(); + }; - const $menuButton = html`<${SidebarButton} - onclick=${openMenu} - notifications=${(await checkForUpdate()) ? 1 : 0} - icon="notion-enhancer${menuButtonIconStyle === "Monochrome" - ? "?mask" - : " text-[16px]"}" - >notion-enhancer - />`; - addMutationListener(notionSidebar, () => { - if (document.contains($menuButton)) return; - document.querySelector(notionSidebar)?.append($menuButton); - }); - document.querySelector(notionSidebar)?.append($menuButton); + const $modal = html`<${Modal} onopen=${sendRenderPing}> + <${Frame} + title="notion-enhancer menu" + src="${enhancerUrl("core/menu/index.html")}" + onload=${function () { + // pass notion-enhancer api to electron menu process + if (platform !== "browser") { + const apiKey = "__enhancerApi"; + this.contentWindow[apiKey] = globalThis[apiKey]; + } + sendRenderPing(this.contentWindow); + }} + /> + />`, + $button = html`<${Button} + onclick=${$modal.open} + notifications=${(await checkForUpdate()) ? 1 : 0} + themeOverridesLoaded=${await doThemeOverride(db)} + icon="notion-enhancer${menuButtonIconStyle === "Monochrome" + ? "?mask" + : " text-[16px]"}" + >notion-enhancer + />`; + document.body.append($modal); + addMutationListener(notionSidebar, () => { + if (document.contains($button)) return; + document.querySelector(notionSidebar)?.append($button); + }); + document.querySelector(notionSidebar)?.append($button); + addMutationListener("body", sendThemePing); + window.addEventListener("focus", sendRenderPing); - window.addEventListener("focus", () => updateTheme(true)); - window.addEventListener("message", (event) => { - if (event.data?.namespace !== "notion-enhancer") return; - if (event.data?.action === "close-menu") closeMenu(); - if (event.data?.action === "open-menu") openMenu(); - }); - addMutationListener("body", () => { - if ($menuModal?.hasAttribute("open")) updateTheme(); - }); - onMessage("notion-enhancer", (message) => { - if (message === "open-menu") openMenu(); - }); - addKeyListener(openMenuHotkey, (event) => { - event.preventDefault(); - openMenu(); - }); - addKeyListener("Escape", () => { - if (document.activeElement?.nodeName === "INPUT") return; - closeMenu(); - }); - - sendMessage("notion-enhancer", "load-complete"); - - if ((await initDatabase().get("agreedToTerms")) === version) { + addKeyListener(openMenuHotkey, (event) => { + event.preventDefault(); + $modal.open(); + }); + window.addEventListener("message", (event) => { + if (event.data?.namespace !== "notion-enhancer") return; + if (event.data?.action === "close-menu") $modal.close(); + if (event.data?.action === "open-menu") $modal.open(); + }); + onMessage("notion-enhancer", (message) => { + if (message === "open-menu") $modal.open(); + }); + }, + sendTelemetryPing = async () => { + const { version } = globalThis.__enhancerApi, + db = globalThis.__enhancerApi.initDatabase(), + agreedToTerms = await db.get("agreedToTerms"), + telemetryEnabled = await db.get("telemetryEnabled"); + if (!telemetryEnabled || agreedToTerms !== version) return; // telemetry - } + }; + +export default async (api, db) => { + await Promise.all([ + overrideThemes(db), + insertCustomStyles(db), + insertMenu(db), + sendTelemetryPing(), + ]); + api.sendMessage("notion-enhancer", "load-complete"); }; diff --git a/src/core/components.mjs b/src/core/components.mjs new file mode 100644 index 0000000..2d406e2 --- /dev/null +++ b/src/core/components.mjs @@ -0,0 +1,95 @@ +/** + * notion-enhancer + * (c) 2023 dragonwocky"${platform}"
), timezone
("${timezone}"
), notion-enhancer version
("${version}"
), and enabled mods (${$enabledMods}). You can
- opt in or out of telemetry at any time. For more information, read the
- notion-enhancer's privacy policy.`}
+ opt in or out of telemetry at any time. This setting syncs across
+ configuration profiles. For more information, read the notion-enhancer's
+ privacy policy.`}
...${{ _get, _set }}
/>`;
}