mirror of
https://github.com/notion-enhancer/notion-enhancer.git
synced 2025-04-12 00:09:03 +00:00
feat(menu): add reload btn to footer, move return to category btn to footer
This commit is contained in:
parent
4456871f6d
commit
7bafbedc67
@ -55,6 +55,17 @@ function SidebarButton({ id, icon, ...props }, ...children) {
|
|||||||
return $el;
|
return $el;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function Footer({}, ...children) {
|
||||||
|
const { html } = globalThis.__enhancerApi;
|
||||||
|
return html`<div
|
||||||
|
class="flex w-full px-[60px] py-[16px]
|
||||||
|
border-t-(& [color:var(--theme--fg-border)])
|
||||||
|
bg-[color:var(--theme--bg-primary)]"
|
||||||
|
>
|
||||||
|
${children}
|
||||||
|
</div>`;
|
||||||
|
}
|
||||||
|
|
||||||
function View({ id }, ...children) {
|
function View({ id }, ...children) {
|
||||||
const { html } = globalThis.__enhancerApi,
|
const { html } = globalThis.__enhancerApi,
|
||||||
$el = html`<article
|
$el = html`<article
|
||||||
@ -122,10 +133,10 @@ function View({ id }, ...children) {
|
|||||||
return $el;
|
return $el;
|
||||||
}
|
}
|
||||||
|
|
||||||
function List({ description }, ...children) {
|
function List({ id, description }, ...children) {
|
||||||
const { html } = globalThis.__enhancerApi;
|
const { html } = globalThis.__enhancerApi;
|
||||||
return html`<div class="flex flex-col gap-y-[14px]">
|
return html`<div class="flex flex-col gap-y-[14px]">
|
||||||
<${Search} items=${children} />
|
<${Search} type=${id} items=${children} />
|
||||||
<p
|
<p
|
||||||
class="notion-enhancer--menu-description
|
class="notion-enhancer--menu-description
|
||||||
text-([12px] [color:var(--theme--fg-secondary)])"
|
text-([12px] [color:var(--theme--fg-secondary)])"
|
||||||
@ -135,13 +146,15 @@ function List({ description }, ...children) {
|
|||||||
</div>`;
|
</div>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
function Search({ items, oninput, ...props }) {
|
function Search({ type, items, oninput, ...props }) {
|
||||||
const { html, addKeyListener } = globalThis.__enhancerApi,
|
const { html, addKeyListener } = globalThis.__enhancerApi,
|
||||||
$search = html`<${Input}
|
$search = html`<${Input}
|
||||||
size="lg"
|
size="lg"
|
||||||
type="text"
|
type="text"
|
||||||
|
placeholder="Search ${items.length} ${items.length === 1
|
||||||
|
? type.replace(/s$/, "")
|
||||||
|
: type} (Press '/' to focus)"
|
||||||
icon="search"
|
icon="search"
|
||||||
placeholder="Search ('/' to focus)"
|
|
||||||
oninput=${(event) => {
|
oninput=${(event) => {
|
||||||
oninput?.(event);
|
oninput?.(event);
|
||||||
const query = event.target.value.toLowerCase();
|
const query = event.target.value.toLowerCase();
|
||||||
@ -251,7 +264,7 @@ function Option({ type, value, description, _get, _set, ...props }) {
|
|||||||
return html`<h4
|
return html`<h4
|
||||||
class="notion-enhancer--menu-heading font-semibold
|
class="notion-enhancer--menu-heading font-semibold
|
||||||
mb-[16px] mt-[48px] first:mt-0 pb-[12px] text-[16px]
|
mb-[16px] mt-[48px] first:mt-0 pb-[12px] text-[16px]
|
||||||
border-b border-b-[color:var(--theme--fg-border)]"
|
border-b-(& [color:var(--theme--fg-border)])"
|
||||||
>
|
>
|
||||||
${label}
|
${label}
|
||||||
</h4>`;
|
</h4>`;
|
||||||
@ -296,17 +309,23 @@ function Option({ type, value, description, _get, _set, ...props }) {
|
|||||||
<//>`;
|
<//>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
function Button({ icon, ...props }, children) {
|
function Button({ primary, icon, class: cls, ...props }, children) {
|
||||||
const { html } = globalThis.__enhancerApi;
|
const { html } = globalThis.__enhancerApi,
|
||||||
|
$icon = icon
|
||||||
|
? html`<i class="i-${icon} w-[18px] h-[18px] mr-[8px]"></i>`
|
||||||
|
: "";
|
||||||
return html`<button
|
return html`<button
|
||||||
class="mt-[14px] first:mt-0 mb-[14px] last:mb-0
|
class="flex items-center h-[32px] px-[12px] ${cls}
|
||||||
flex items-center h-[32px] px-[12px] rounded-[4px]
|
rounded-[4px] transition duration-[20ms] ${primary
|
||||||
cursor-pointer border-(& [color:var(--theme--fg-border)])
|
? `text-[color:var(--theme--accent-primary_contrast)]
|
||||||
transition duration-[20ms] hover:bg-[color:var(--theme--bg-hover)]"
|
font-medium bg-[color:var(--theme--accent-primary)]
|
||||||
|
hover:bg-[color:var(--theme--accent-primary\\_hover)]`
|
||||||
|
: `border-(& [color:var(--theme--fg-border)])
|
||||||
|
hover:bg-[color:var(--theme--bg-hover)]`}"
|
||||||
...${props}
|
...${props}
|
||||||
>
|
>
|
||||||
<i class="i-${icon} w-[18px] h-[18px]"></i>
|
${$icon}
|
||||||
<span class="ml-[8px] text-[14px]">${children}</span>
|
<span class="text-[14px]">${children}</span>
|
||||||
</button>`;
|
</button>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -680,6 +699,7 @@ export {
|
|||||||
Sidebar,
|
Sidebar,
|
||||||
SidebarSection,
|
SidebarSection,
|
||||||
SidebarButton,
|
SidebarButton,
|
||||||
|
Footer,
|
||||||
View,
|
View,
|
||||||
List,
|
List,
|
||||||
Mod,
|
Mod,
|
||||||
|
@ -44,6 +44,7 @@ body {
|
|||||||
height: 100vh;
|
height: 100vh;
|
||||||
color: var(--theme--fg-primary);
|
color: var(--theme--fg-primary);
|
||||||
font-family: var(--theme--font-sans);
|
font-family: var(--theme--font-sans);
|
||||||
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
body > #skeleton {
|
body > #skeleton {
|
||||||
|
@ -9,6 +9,7 @@ import {
|
|||||||
Sidebar,
|
Sidebar,
|
||||||
SidebarSection,
|
SidebarSection,
|
||||||
SidebarButton,
|
SidebarButton,
|
||||||
|
Footer,
|
||||||
View,
|
View,
|
||||||
List,
|
List,
|
||||||
Mod,
|
Mod,
|
||||||
@ -61,18 +62,18 @@ const renderSidebar = (items, categories) => {
|
|||||||
}
|
}
|
||||||
return $sidebar;
|
return $sidebar;
|
||||||
},
|
},
|
||||||
renderList = async (mods, description) => {
|
renderList = async (id, mods, description) => {
|
||||||
const { html, getProfile, initDatabase } = globalThis.__enhancerApi,
|
const { html, getProfile, initDatabase } = globalThis.__enhancerApi,
|
||||||
enabledMods = initDatabase([await getProfile(), "enabledMods"]);
|
enabledMods = initDatabase([await getProfile(), "enabledMods"]);
|
||||||
mods = mods.map(async (mod) => {
|
mods = mods.map(async (mod) => {
|
||||||
const _get = () => enabledMods.get(mod.id),
|
const _get = () => enabledMods.get(mod.id),
|
||||||
_set = async (enabled) => {
|
_set = async (enabled) => {
|
||||||
await enabledMods.set(mod.id, enabled);
|
await enabledMods.set(mod.id, enabled);
|
||||||
setState({ rerender: true });
|
setState({ rerender: true, databaseUpdated: true });
|
||||||
};
|
};
|
||||||
return html`<${Mod} ...${{ ...mod, _get, _set }} />`;
|
return html`<${Mod} ...${{ ...mod, _get, _set }} />`;
|
||||||
});
|
});
|
||||||
return html`<${List} description=${description}>
|
return html`<${List} ...${{ id, description }}>
|
||||||
${await Promise.all(mods)}
|
${await Promise.all(mods)}
|
||||||
<//>`;
|
<//>`;
|
||||||
},
|
},
|
||||||
@ -98,7 +99,7 @@ const renderSidebar = (items, categories) => {
|
|||||||
const _get = () => db.get(opt.key),
|
const _get = () => db.get(opt.key),
|
||||||
_set = async (value) => {
|
_set = async (value) => {
|
||||||
await db.set(opt.key, value);
|
await db.set(opt.key, value);
|
||||||
setState({ rerender: true });
|
setState({ rerender: true, databaseUpdated: true });
|
||||||
};
|
};
|
||||||
return html`<${Option} ...${{ ...opt, _get, _set }} />`;
|
return html`<${Option} ...${{ ...opt, _get, _set }} />`;
|
||||||
});
|
});
|
||||||
@ -115,17 +116,9 @@ const renderSidebar = (items, categories) => {
|
|||||||
const _get = () => enabledMods.get(mod.id),
|
const _get = () => enabledMods.get(mod.id),
|
||||||
_set = async (enabled) => {
|
_set = async (enabled) => {
|
||||||
await enabledMods.set(mod.id, enabled);
|
await enabledMods.set(mod.id, enabled);
|
||||||
setState({ rerender: true });
|
setState({ rerender: true, databaseUpdated: true });
|
||||||
};
|
};
|
||||||
return html`<${View} id=${mod.id}>
|
return html`<${View} id=${mod.id}>
|
||||||
<${Button}
|
|
||||||
icon="chevron-left"
|
|
||||||
onclick=${() => {
|
|
||||||
setState({ transition: "slide-to-left", view: category.id });
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
${category.title}
|
|
||||||
<//>
|
|
||||||
<${Mod} ...${{ ...mod, options: [], _get, _set }} />
|
<${Mod} ...${{ ...mod, options: [], _get, _set }} />
|
||||||
${await renderOptions(mod)}
|
${await renderOptions(mod)}
|
||||||
<//>`;
|
<//>`;
|
||||||
@ -134,8 +127,8 @@ const renderSidebar = (items, categories) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const render = async () => {
|
const render = async () => {
|
||||||
const { html, getCore, getThemes } = globalThis.__enhancerApi,
|
const { html, reloadApp, getCore } = globalThis.__enhancerApi,
|
||||||
{ getExtensions, getIntegrations } = globalThis.__enhancerApi,
|
{ getThemes, getExtensions, getIntegrations } = globalThis.__enhancerApi,
|
||||||
[icon, renderStarted] = getState(["icon", "renderStarted"]);
|
[icon, renderStarted] = getState(["icon", "renderStarted"]);
|
||||||
if (!html || !getCore || !icon || renderStarted) return;
|
if (!html || !getCore || !icon || renderStarted) return;
|
||||||
setState({ renderStarted: true });
|
setState({ renderStarted: true });
|
||||||
@ -210,18 +203,57 @@ const render = async () => {
|
|||||||
];
|
];
|
||||||
|
|
||||||
// view wrapper necessary for transitions
|
// view wrapper necessary for transitions
|
||||||
const $views = html`<div class="relative overflow-hidden">
|
const $views = html`<div class="grow relative overflow-hidden">
|
||||||
<${View} id="welcome">welcome<//>
|
<${View} id="welcome">welcome<//>
|
||||||
<${View} id="core">${await renderOptions(await getCore())}<//>
|
<${View} id="core">${await renderOptions(await getCore())}<//>
|
||||||
</div>`;
|
</div>`;
|
||||||
for (const { id, title, description, mods } of categories) {
|
for (const { id, title, description, mods } of categories) {
|
||||||
const $list = await renderList(mods, description),
|
const $list = await renderList(id, mods, description),
|
||||||
$mods = await renderMods({ id, title }, mods);
|
$mods = await renderMods({ id, title }, mods);
|
||||||
$views.append(html`<${View} id=${id}>${$list}<//>`, ...$mods);
|
$views.append(html`<${View} id=${id}>${$list}<//>`, ...$mods);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
categories.forEach((c) => {
|
||||||
|
c.button = html`<${Button}
|
||||||
|
icon="chevron-left"
|
||||||
|
onclick=${() => setState({ transition: "slide-to-left", view: c.id })}
|
||||||
|
>
|
||||||
|
${c.title}
|
||||||
|
<//>`;
|
||||||
|
});
|
||||||
|
const $reload = html`<${Button}
|
||||||
|
primary
|
||||||
|
class="ml-auto"
|
||||||
|
icon="refresh-cw"
|
||||||
|
onclick=${() => reloadApp()}
|
||||||
|
style="display: none"
|
||||||
|
>
|
||||||
|
Reload & Apply Changes
|
||||||
|
<//>`,
|
||||||
|
$footer = html`<${Footer}>${categories.map((c) => c.button)}${$reload}<//>`,
|
||||||
|
$main = html`<div class="flex flex-col overflow-hidden transition-[height]">
|
||||||
|
${$views} ${$footer}
|
||||||
|
</div>`,
|
||||||
|
updateFooter = () => {
|
||||||
|
const buttons = [...$footer.children],
|
||||||
|
renderFooter = buttons.some(($el) => $el.style.display === "");
|
||||||
|
$main.style.height = renderFooter ? "100%" : "calc(100% + 65px)";
|
||||||
|
};
|
||||||
|
useState(["view"], ([view]) => {
|
||||||
|
for (const { mods, button } of categories) {
|
||||||
|
const renderButton = mods.some((mod) => mod.id === view);
|
||||||
|
button.style.display = renderButton ? "" : "none";
|
||||||
|
updateFooter();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
useState(["databaseUpdated"], ([databaseUpdated]) => {
|
||||||
|
if (!databaseUpdated) return;
|
||||||
|
$reload.style.display = "";
|
||||||
|
updateFooter();
|
||||||
|
});
|
||||||
|
|
||||||
const $skeleton = document.querySelector("#skeleton");
|
const $skeleton = document.querySelector("#skeleton");
|
||||||
$skeleton.replaceWith(renderSidebar(sidebar, categories), $views);
|
$skeleton.replaceWith(renderSidebar(sidebar, categories), $main);
|
||||||
};
|
};
|
||||||
|
|
||||||
window.addEventListener("focus", () => setState({ rerender: true }));
|
window.addEventListener("focus", () => setState({ rerender: true }));
|
||||||
|
Loading…
Reference in New Issue
Block a user