fix: delay menu open until dom is ready to preserve transition

This commit is contained in:
dragonwocky 2023-08-07 11:48:29 +10:00
parent 1d501dffa5
commit 09b24147c5
Signed by: dragonwocky
GPG Key ID: 7998D08F7D7BD7A8
19 changed files with 81 additions and 84 deletions

View File

@ -11,8 +11,8 @@ import { MenuButton } from "./islands/MenuButton.mjs";
import { TopbarButton } from "./islands/TopbarButton.mjs"; import { TopbarButton } from "./islands/TopbarButton.mjs";
import { Panel } from "./islands/Panel.mjs"; import { Panel } from "./islands/Panel.mjs";
const shouldLoadThemeOverrides = async (db) => { const shouldLoadThemeOverrides = async (api, db) => {
const { getMods, isEnabled } = globalThis.__enhancerApi, const { getMods, isEnabled } = api,
loadThemeOverrides = await db.get("loadThemeOverrides"); loadThemeOverrides = await db.get("loadThemeOverrides");
if (loadThemeOverrides === "Enabled") return true; if (loadThemeOverrides === "Enabled") return true;
if (loadThemeOverrides === "Disabled") return false; if (loadThemeOverrides === "Disabled") return false;
@ -23,16 +23,16 @@ const shouldLoadThemeOverrides = async (db) => {
return await isEnabled(mod.id); return await isEnabled(mod.id);
})).length; })).length;
}, },
loadThemeOverrides = async (db) => { loadThemeOverrides = async (api, db) => {
const { html, enhancerUrl } = globalThis.__enhancerApi; const { html, enhancerUrl } = api;
if (!(await shouldLoadThemeOverrides(db))) return; if (!(await shouldLoadThemeOverrides(api, db))) return;
document.head.append(html`<link document.head.append(html`<link
rel="stylesheet" rel="stylesheet"
href=${enhancerUrl("core/theme.css")} href=${enhancerUrl("core/theme.css")}
/>`); />`);
}, },
insertCustomStyles = async (db) => { insertCustomStyles = async (api, db) => {
const { html } = globalThis.__enhancerApi, const { html } = api,
customStyles = (await db.get("customStyles"))?.content; customStyles = (await db.get("customStyles"))?.content;
if (!customStyles) return; if (!customStyles) return;
return document.head.append(html`<style> return document.head.append(html`<style>
@ -40,11 +40,11 @@ const shouldLoadThemeOverrides = async (db) => {
</style>`); </style>`);
}; };
const insertMenu = async (db) => { const insertMenu = async (api, db) => {
const notionSidebar = `.notion-sidebar-container .notion-sidebar > :nth-child(3) > div > :nth-child(2)`, const notionSidebar = `.notion-sidebar-container .notion-sidebar > :nth-child(3) > div > :nth-child(2)`,
notionSettingsAndMembers = `${notionSidebar} > [role="button"]:nth-child(3)`, notionSettingsAndMembers = `${notionSidebar} > [role="button"]:nth-child(3)`,
{ html, addKeyListener, addMutationListener } = globalThis.__enhancerApi, { html, addKeyListener, addMutationListener } = api,
{ platform, enhancerUrl, onMessage } = globalThis.__enhancerApi, { platform, enhancerUrl, onMessage } = api,
menuButtonIconStyle = await db.get("menuButtonIconStyle"), menuButtonIconStyle = await db.get("menuButtonIconStyle"),
openMenuHotkey = await db.get("openMenuHotkey"), openMenuHotkey = await db.get("openMenuHotkey"),
menuPing = { menuPing = {
@ -86,7 +86,7 @@ const insertMenu = async (db) => {
$button = html`<${MenuButton} $button = html`<${MenuButton}
onclick=${$modal.open} onclick=${$modal.open}
notifications=${(await checkForUpdate()) ? 1 : 0} notifications=${(await checkForUpdate()) ? 1 : 0}
themeOverridesLoaded=${await shouldLoadThemeOverrides(db)} themeOverridesLoaded=${await shouldLoadThemeOverrides(api, db)}
icon="notion-enhancer${menuButtonIconStyle === "Monochrome" icon="notion-enhancer${menuButtonIconStyle === "Monochrome"
? "?mask" ? "?mask"
: " text-[16px]"}" : " text-[16px]"}"
@ -168,9 +168,9 @@ const insertPanel = async (api, db) => {
export default async (api, db) => export default async (api, db) =>
Promise.all([ Promise.all([
insertMenu(db), insertMenu(api, db),
insertPanel(api, db), insertPanel(api, db),
insertCustomStyles(db), insertCustomStyles(api, db),
loadThemeOverrides(db), loadThemeOverrides(api, db),
sendTelemetryPing(), sendTelemetryPing(),
]).then(() => api.sendMessage("notion-enhancer", "load-complete")); ]).then(() => api.sendMessage("notion-enhancer", "load-complete"));

View File

@ -24,11 +24,19 @@ function Modal(props, ...children) {
${children} ${children}
</div> </div>
</div>`; </div>`;
$modal.open = () => {
let _openQueued;
$modal.open = async () => {
_openQueued = true;
while (!document.contains($modal)) {
if (!_openQueued) return;
await new Promise(requestAnimationFrame);
}
$modal.setAttribute("open", ""); $modal.setAttribute("open", "");
$modal.onopen?.(); $modal.onopen?.();
}; };
$modal.close = () => { $modal.close = () => {
_openQueued = false;
$modal.onbeforeclose?.(); $modal.onbeforeclose?.();
$modal.removeAttribute("open"); $modal.removeAttribute("open");
$modal.style.pointerEvents = "auto"; $modal.style.pointerEvents = "auto";

View File

@ -27,8 +27,9 @@ function Panel({
transitionDuration = 300, transitionDuration = 300,
...props ...props
}) { }) {
const { html, ...api } = globalThis.__enhancerApi; const { html, extendProps, setState } = globalThis.__enhancerApi,
api.extendProps(props, { { addMutationListener, removeMutationListener } = globalThis.__enhancerApi;
extendProps(props, {
class: `notion-enhancer--side-panel order-2 shrink-0 class: `notion-enhancer--side-panel order-2 shrink-0
transition-[width] open:w-[var(--side\\_panel--width)] transition-[width] open:w-[var(--side\\_panel--width)]
w-0 border-l-1 border-[color:var(--theme--fg-border)] w-0 border-l-1 border-[color:var(--theme--fg-border)]
@ -51,11 +52,9 @@ function Panel({
<svg <svg
viewBox="0 0 16 16" viewBox="0 0 16 16"
class="w-[16px] h-[16px] fill-[color:var(--theme--fg-secondary)]" class="w-[16px] h-[16px] fill-[color:var(--theme--fg-secondary)]"
> ><path
<path
d="M2.25781 14.1211C2.47656 14.1211 2.66797 14.0391 2.81836 13.8887L8.14355 8.67969C8.32812 8.49512 8.41699 8.29688 8.41699 8.06445C8.41699 7.8252 8.32812 7.62012 8.14355 7.44922L2.81836 2.24023C2.66797 2.08984 2.4834 2.00781 2.25781 2.00781C1.81348 2.00781 1.46484 2.35645 1.46484 2.80078C1.46484 3.0127 1.55371 3.21777 1.7041 3.375L6.50977 8.05762L1.7041 12.7539C1.55371 12.9043 1.46484 13.1094 1.46484 13.3281C1.46484 13.7725 1.81348 14.1211 2.25781 14.1211ZM8.36914 14.1211C8.58789 14.1211 8.77246 14.0391 8.92285 13.8887L14.2549 8.67969C14.4395 8.49512 14.5283 8.29688 14.5283 8.06445C14.5283 7.8252 14.4326 7.62012 14.2549 7.44922L8.92285 2.24023C8.77246 2.08984 8.58789 2.00781 8.36914 2.00781C7.9248 2.00781 7.56934 2.35645 7.56934 2.80078C7.56934 3.0127 7.66504 3.21777 7.81543 3.375L12.6211 8.05762L7.81543 12.7539C7.66504 12.9043 7.56934 13.1094 7.56934 13.3281C7.56934 13.7725 7.9248 14.1211 8.36914 14.1211Z" d="M2.25781 14.1211C2.47656 14.1211 2.66797 14.0391 2.81836 13.8887L8.14355 8.67969C8.32812 8.49512 8.41699 8.29688 8.41699 8.06445C8.41699 7.8252 8.32812 7.62012 8.14355 7.44922L2.81836 2.24023C2.66797 2.08984 2.4834 2.00781 2.25781 2.00781C1.81348 2.00781 1.46484 2.35645 1.46484 2.80078C1.46484 3.0127 1.55371 3.21777 1.7041 3.375L6.50977 8.05762L1.7041 12.7539C1.55371 12.9043 1.46484 13.1094 1.46484 13.3281C1.46484 13.7725 1.81348 14.1211 2.25781 14.1211ZM8.36914 14.1211C8.58789 14.1211 8.77246 14.0391 8.92285 13.8887L14.2549 8.67969C14.4395 8.49512 14.5283 8.29688 14.5283 8.06445C14.5283 7.8252 14.4326 7.62012 14.2549 7.44922L8.92285 2.24023C8.77246 2.08984 8.58789 2.00781 8.36914 2.00781C7.9248 2.00781 7.56934 2.35645 7.56934 2.80078C7.56934 3.0127 7.66504 3.21777 7.81543 3.375L12.6211 8.05762L7.81543 12.7539C7.66504 12.9043 7.56934 13.1094 7.56934 13.3281C7.56934 13.7725 7.9248 14.1211 8.36914 14.1211Z"
></path> ></path></svg>
</svg>
</div>`; </div>`;
const $panel = html`<aside ...${props}> const $panel = html`<aside ...${props}>
@ -130,9 +129,9 @@ function Panel({
}; };
$notionHelp.style.setProperty("right", destination); $notionHelp.style.setProperty("right", destination);
$notionHelp.animate(keyframes, options); $notionHelp.animate(keyframes, options);
api.removeMutationListener(repositionHelp); removeMutationListener(repositionHelp);
}; };
api.addMutationListener(notionHelp, repositionHelp); addMutationListener(notionHelp, repositionHelp);
$panel.resize = async (width) => { $panel.resize = async (width) => {
$tooltip.hide(); $tooltip.hide();
@ -148,7 +147,7 @@ function Panel({
$panel.open = () => { $panel.open = () => {
$panel.setAttribute("open", true); $panel.setAttribute("open", true);
$panel.querySelectorAll("[tabindex]").forEach(($el) => ($el.tabIndex = 0)); $panel.querySelectorAll("[tabindex]").forEach(($el) => ($el.tabIndex = 0));
api.setState({ panelOpen: true }); setState({ panelOpen: true });
$panel.onopen?.(); $panel.onopen?.();
_setOpen(true); _setOpen(true);
$panel.resize(); $panel.resize();
@ -159,7 +158,7 @@ function Panel({
$panel.removeAttribute("open"); $panel.removeAttribute("open");
$panel.style.pointerEvents = "auto"; $panel.style.pointerEvents = "auto";
$panel.querySelectorAll("[tabindex]").forEach(($el) => ($el.tabIndex = -1)); $panel.querySelectorAll("[tabindex]").forEach(($el) => ($el.tabIndex = -1));
api.setState({ panelOpen: false }); setState({ panelOpen: false });
repositionHelp(); repositionHelp();
_setOpen(false); _setOpen(false);
setTimeout(() => { setTimeout(() => {

View File

@ -68,7 +68,8 @@ function Circle(rect) {
} }
function Banner({ updateAvailable, isDevelopmentBuild }) { function Banner({ updateAvailable, isDevelopmentBuild }) {
const { html, version, initDatabase, useState } = globalThis.__enhancerApi, const { html, useState } = globalThis.__enhancerApi,
{ version, initDatabase } = globalThis.__enhancerApi,
$version = html`<button $version = html`<button
class="text-[12px] py-[2px] px-[6px] mt-[2px] class="text-[12px] py-[2px] px-[6px] mt-[2px]
font-medium leading-tight tracking-wide rounded-[3px] font-medium leading-tight tracking-wide rounded-[3px]

View File

@ -6,8 +6,7 @@
function Checkbox({ _get, _set, _requireReload = true, ...props }) { function Checkbox({ _get, _set, _requireReload = true, ...props }) {
let _initialValue; let _initialValue;
const { html, extendProps } = globalThis.__enhancerApi, const { html, extendProps, setState, useState } = globalThis.__enhancerApi,
{ setState, useState } = globalThis.__enhancerApi,
$input = html`<input $input = html`<input
type="checkbox" type="checkbox"
class="hidden checked:sibling:(px-px class="hidden checked:sibling:(px-px

View File

@ -7,8 +7,7 @@
import { Button } from "./Button.mjs"; import { Button } from "./Button.mjs";
function Footer({ categories }) { function Footer({ categories }) {
const { html, reloadApp } = globalThis.__enhancerApi, const { html, setState, useState, reloadApp } = globalThis.__enhancerApi,
{ setState, useState } = globalThis.__enhancerApi,
$reload = html`<${Button} $reload = html`<${Button}
class="ml-auto" class="ml-auto"
variant="primary" variant="primary"

View File

@ -74,8 +74,7 @@ function Input({
...props ...props
}) { }) {
let $filename, $clear; let $filename, $clear;
const { html, extendProps } = globalThis.__enhancerApi, const { html, extendProps, setState, useState } = globalThis.__enhancerApi;
{ setState, useState } = globalThis.__enhancerApi;
Coloris({ format: "rgb" }); Coloris({ format: "rgb" });
type ??= "text"; type ??= "text";

View File

@ -37,7 +37,8 @@ function Search({ items, itemType }) {
} }
function List({ id, mods, description }) { function List({ id, mods, description }) {
const { html, isEnabled, setEnabled, setState } = globalThis.__enhancerApi, const { html, setState } = globalThis.__enhancerApi,
{ isEnabled, setEnabled } = globalThis.__enhancerApi,
$mods = mods.map((mod) => { $mods = mods.map((mod) => {
const _get = () => isEnabled(mod.id), const _get = () => isEnabled(mod.id),
_set = async (enabled) => { _set = async (enabled) => {

View File

@ -20,7 +20,7 @@ function Mod({
_set, _set,
_src, _src,
}) { }) {
const { html, enhancerUrl, setState } = globalThis.__enhancerApi, const { html, setState, enhancerUrl } = globalThis.__enhancerApi,
toggleId = Math.random().toString(36).slice(2, 5); toggleId = Math.random().toString(36).slice(2, 5);
return html`<label return html`<label

View File

@ -14,8 +14,8 @@ const privacyPolicy = "https://notion-enhancer.github.io/about/privacy-policy/",
tsAndCs = "https://notion-enhancer.github.io/about/terms-and-conditions/"; tsAndCs = "https://notion-enhancer.github.io/about/terms-and-conditions/";
function Onboarding() { function Onboarding() {
const { html, version, initDatabase } = globalThis.__enhancerApi, const { html, setState, useState } = globalThis.__enhancerApi,
{ setState, useState } = globalThis.__enhancerApi, { version, initDatabase } = globalThis.__enhancerApi,
$submitAgreement = html`<${Button} $submitAgreement = html`<${Button}
icon="arrow-right" icon="arrow-right"
class="ml-auto" class="ml-auto"

View File

@ -5,8 +5,7 @@
*/ */
function Popup({ trigger, ...props }, ...children) { function Popup({ trigger, ...props }, ...children) {
const { html, extendProps } = globalThis.__enhancerApi, const { html, extendProps, setState, useState } = globalThis.__enhancerApi;
{ setState, useState } = globalThis.__enhancerApi;
extendProps(props, { extendProps(props, {
class: `notion-enhancer--menu-popup class: `notion-enhancer--menu-popup
group absolute top-0 left-0 w-full h-full group absolute top-0 left-0 w-full h-full

View File

@ -12,8 +12,8 @@ import { Input } from "./Input.mjs";
import { Popup } from "./Popup.mjs"; import { Popup } from "./Popup.mjs";
function Profile({ id }) { function Profile({ id }) {
const { html, getProfile, initDatabase } = globalThis.__enhancerApi, const { html, setState } = globalThis.__enhancerApi,
{ setState, useState } = globalThis.__enhancerApi, { getProfile, initDatabase } = globalThis.__enhancerApi,
profile = initDatabase([id]), profile = initDatabase([id]),
db = initDatabase(); db = initDatabase();
@ -179,8 +179,7 @@ function Profile({ id }) {
} }
function Profiles() { function Profiles() {
const { html, initDatabase } = globalThis.__enhancerApi, const { html, setState, useState, initDatabase } = globalThis.__enhancerApi,
{ setState, useState } = globalThis.__enhancerApi,
$input = html`<${Input} icon="file-cog" />`, $input = html`<${Input} icon="file-cog" />`,
$list = html`<ul></ul>`; $list = html`<ul></ul>`;

View File

@ -7,8 +7,7 @@
import { Popup } from "./Popup.mjs"; import { Popup } from "./Popup.mjs";
function Option({ value, _get, _set }) { function Option({ value, _get, _set }) {
const { html } = globalThis.__enhancerApi, const { html, useState } = globalThis.__enhancerApi,
{ setState, useState } = globalThis.__enhancerApi,
$selected = html`<i class="ml-auto i-check w-[16px] h-[16px]"></i>`, $selected = html`<i class="ml-auto i-check w-[16px] h-[16px]"></i>`,
$option = html`<div $option = html`<div
tabindex="0" tabindex="0"
@ -35,8 +34,7 @@ function Option({ value, _get, _set }) {
function Select({ values, _get, _set, _requireReload = true, ...props }) { function Select({ values, _get, _set, _requireReload = true, ...props }) {
let _initialValue; let _initialValue;
const { html } = globalThis.__enhancerApi, const { html, setState, useState } = globalThis.__enhancerApi,
{ setState, useState } = globalThis.__enhancerApi,
// dir="rtl" overflows to the left during transition // dir="rtl" overflows to the left during transition
$select = html`<div $select = html`<div
dir="rtl" dir="rtl"

View File

@ -7,8 +7,7 @@
import { Description } from "./Description.mjs"; import { Description } from "./Description.mjs";
function SidebarHeading({}, ...children) { function SidebarHeading({}, ...children) {
const { html } = globalThis.__enhancerApi, const { html } = globalThis.__enhancerApi;
{ setState, useState } = globalThis.__enhancerApi;
return html`<h2 return html`<h2
class="flex items-center font-semibold leading-none class="flex items-center font-semibold leading-none
text-([12px] [color:var(--theme--fg-secondary)]) text-([12px] [color:var(--theme--fg-secondary)])
@ -19,8 +18,7 @@ function SidebarHeading({}, ...children) {
} }
function SidebarButton({ id, icon, ...props }, ...children) { function SidebarButton({ id, icon, ...props }, ...children) {
const { html, extendProps } = globalThis.__enhancerApi, const { html, extendProps, setState, useState } = globalThis.__enhancerApi,
{ setState, useState } = globalThis.__enhancerApi,
$btn = html`<${props["href"] ? "a" : "button"} $btn = html`<${props["href"] ? "a" : "button"}
class="flex items-center select-none text-[14px] class="flex items-center select-none text-[14px]
min-h-[27px] px-[12px] my-px last:mb-[12px] w-full min-h-[27px] px-[12px] my-px last:mb-[12px] w-full
@ -52,9 +50,8 @@ function SidebarButton({ id, icon, ...props }, ...children) {
} }
function Sidebar({ items, categories }) { function Sidebar({ items, categories }) {
const { html, version } = globalThis.__enhancerApi, const { html, useState } = globalThis.__enhancerApi,
{ initDatabase, isEnabled } = globalThis.__enhancerApi, { version, initDatabase, isEnabled } = globalThis.__enhancerApi,
{ setState, useState } = globalThis.__enhancerApi,
$agreeToUnlock = html`<span $agreeToUnlock = html`<span
class="pt-[2px] pb-[5px] px-[15px] text-[12px] class="pt-[2px] pb-[5px] px-[15px] text-[12px]
inline-block text-[color:var(--theme--fg-red)]" inline-block text-[color:var(--theme--fg-red)]"

View File

@ -9,8 +9,7 @@ import { Option } from "./Options.mjs";
const privacyPolicy = "https://notion-enhancer.github.io/about/privacy-policy/"; const privacyPolicy = "https://notion-enhancer.github.io/about/privacy-policy/";
function Telemetry() { function Telemetry() {
const { html, initDatabase } = globalThis.__enhancerApi, const { html, setState, useState, initDatabase } = globalThis.__enhancerApi,
{ setState, useState } = globalThis.__enhancerApi,
_get = async () => { _get = async () => {
// defaults to true, must be explicitly set to false to disable // defaults to true, must be explicitly set to false to disable
return (await initDatabase().get("telemetryEnabled")) ?? true; return (await initDatabase().get("telemetryEnabled")) ?? true;

View File

@ -6,8 +6,7 @@
function Toggle({ _get, _set, _requireReload = true, ...props }) { function Toggle({ _get, _set, _requireReload = true, ...props }) {
let _initialValue; let _initialValue;
const { html, extendProps } = globalThis.__enhancerApi, const { html, extendProps, setState, useState } = globalThis.__enhancerApi,
{ setState, useState } = globalThis.__enhancerApi,
$input = html`<input $input = html`<input
type="checkbox" type="checkbox"
class="hidden checked:sibling:children:( class="hidden checked:sibling:children:(

View File

@ -5,8 +5,7 @@
*/ */
function View({ id }, ...children) { function View({ id }, ...children) {
const { html } = globalThis.__enhancerApi, const { html, setState, useState } = globalThis.__enhancerApi,
{ setState, useState } = globalThis.__enhancerApi,
// set padding on last child to maintain pad on overflow // set padding on last child to maintain pad on overflow
$view = html`<article $view = html`<article
id=${id} id=${id}

View File

@ -89,13 +89,14 @@ const categories = [
]; ];
const renderMenu = async () => { const renderMenu = async () => {
const { html, ...api } = globalThis.__enhancerApi, const { html, setState, useState } = globalThis.__enhancerApi,
[theme, icon] = api.useState(["theme", "icon"]); { getMods, isEnabled, setEnabled } = globalThis.__enhancerApi,
[theme, icon] = useState(["theme", "icon"]);
if (!theme || !icon || _renderStarted) return; if (!theme || !icon || _renderStarted) return;
if (icon === "Monochrome") sidebar[1].icon += "?mask"; if (icon === "Monochrome") sidebar[1].icon += "?mask";
_renderStarted = true; _renderStarted = true;
const mods = await api.getMods(); const mods = await getMods();
for (let i = 0; i < categories.length; i++) { for (let i = 0; i < categories.length; i++) {
const { id } = categories[i]; const { id } = categories[i];
categories[i].mods = mods.filter(({ _src }) => _src.startsWith(`${id}/`)); categories[i].mods = mods.filter(({ _src }) => _src.startsWith(`${id}/`));
@ -106,10 +107,10 @@ const renderMenu = async () => {
for (let i = 0; i < mods.length; i++) { for (let i = 0; i < mods.length; i++) {
const options = mods[i].options?.filter((opt) => opt.type !== "heading"); const options = mods[i].options?.filter((opt) => opt.type !== "heading");
if (mods[i]._src === "core" || !options?.length) continue; if (mods[i]._src === "core" || !options?.length) continue;
const _get = () => api.isEnabled(mods[i].id), const _get = () => isEnabled(mods[i].id),
_set = async (enabled) => { _set = async (enabled) => {
await api.setEnabled(mods[i].id, enabled); await setEnabled(mods[i].id, enabled);
api.setState({ rerender: true }); setState({ rerender: true });
}; };
mods[i].view = html`<${View} id=${mods[i].id}> mods[i].view = html`<${View} id=${mods[i].id}>
<!-- passing an empty options array hides the settings button --> <!-- passing an empty options array hides the settings button -->
@ -147,10 +148,10 @@ const renderMenu = async () => {
<${Footer} categories=${categories} /> <${Footer} categories=${categories} />
</main> </main>
`; `;
api.useState(["footerOpen"], ([footerOpen]) => { useState(["footerOpen"], ([footerOpen]) => {
$main.style.height = footerOpen ? "100%" : "calc(100% + 33px)"; $main.style.height = footerOpen ? "100%" : "calc(100% + 33px)";
}); });
api.useState(["transitionInProgress"], ([transitionInProgress]) => { useState(["transitionInProgress"], ([transitionInProgress]) => {
$main.children[0].style.overflow = transitionInProgress ? "hidden" : ""; $main.children[0].style.overflow = transitionInProgress ? "hidden" : "";
}); });
@ -158,20 +159,20 @@ const renderMenu = async () => {
$skeleton.replaceWith($sidebar, $main); $skeleton.replaceWith($sidebar, $main);
}, },
registerHotkey = ([hotkey]) => { registerHotkey = ([hotkey]) => {
const api = globalThis.__enhancerApi; const { addKeyListener, setState, useState } = globalThis.__enhancerApi;
if (!hotkey || _hotkeyRegistered) return; if (!hotkey || _hotkeyRegistered) return;
_hotkeyRegistered = true; _hotkeyRegistered = true;
api.addKeyListener(hotkey, (event) => { addKeyListener(hotkey, (event) => {
event.preventDefault(); event.preventDefault();
const msg = { channel: "notion-enhancer", action: "open-menu" }; const msg = { channel: "notion-enhancer", action: "open-menu" };
parent?.postMessage(msg, "*"); parent?.postMessage(msg, "*");
}); });
api.addKeyListener("Escape", () => { addKeyListener("Escape", () => {
const [popupOpen] = api.useState(["popupOpen"]); const [popupOpen] = useState(["popupOpen"]);
if (!popupOpen) { if (!popupOpen) {
const msg = { channel: "notion-enhancer", action: "close-menu" }; const msg = { channel: "notion-enhancer", action: "close-menu" };
parent?.postMessage(msg, "*"); parent?.postMessage(msg, "*");
} else api.setState({ rerender: true }); } else setState({ rerender: true });
}); });
}, },
updateTheme = ([theme]) => { updateTheme = ([theme]) => {
@ -189,25 +190,25 @@ const importApi = () => {
hookIntoState = () => { hookIntoState = () => {
if (_stateHookedInto) return; if (_stateHookedInto) return;
_stateHookedInto = true; _stateHookedInto = true;
const api = globalThis.__enhancerApi; const { useState } = globalThis.__enhancerApi;
api.useState(["rerender"], renderMenu); useState(["theme"], updateTheme);
api.useState(["hotkey"], registerHotkey); useState(["hotkey"], registerHotkey);
api.useState(["theme"], updateTheme); useState(["rerender"], renderMenu);
}; };
window.addEventListener("focus", async () => { window.addEventListener("focus", async () => {
await importApi().then(hookIntoState); await importApi().then(hookIntoState);
const api = globalThis.__enhancerApi; const { setState } = globalThis.__enhancerApi;
api.setState({ focus: true, rerender: true }); setState({ focus: true, rerender: true });
}); });
window.addEventListener("message", async (event) => { window.addEventListener("message", async (event) => {
if (event.data?.channel !== "notion-enhancer") return; if (event.data?.channel !== "notion-enhancer") return;
await importApi().then(hookIntoState); await importApi().then(hookIntoState);
const api = globalThis.__enhancerApi; const { setState, useState } = globalThis.__enhancerApi;
api.setState({ setState({
rerender: true, rerender: true,
hotkey: event.data?.hotkey ?? api.useState(["hotkey"]), hotkey: event.data?.hotkey ?? useState(["hotkey"]),
theme: event.data?.theme ?? api.useState(["theme"]), theme: event.data?.theme ?? useState(["theme"]),
icon: event.data?.icon ?? api.useState(["icon"]), icon: event.data?.icon ?? useState(["icon"]),
}); });
}); });

View File

@ -9,7 +9,7 @@
// jump to // jump to
const { twind, htm, lucide } = globalThis, const { twind, htm, lucide } = globalThis,
{ readFile, iconColour, iconMonochrome } = globalThis.__enhancerApi; { iconColour, iconMonochrome } = globalThis.__enhancerApi;
const kebabToPascalCase = (string) => const kebabToPascalCase = (string) =>
string[0].toUpperCase() + string[0].toUpperCase() +