feat(menu): add reload btn to footer, move return to category btn to footer

This commit is contained in:
dragonwocky 2023-01-16 19:29:53 +11:00
parent 4456871f6d
commit 7bafbedc67
Signed by: dragonwocky
GPG Key ID: 7998D08F7D7BD7A8
3 changed files with 84 additions and 31 deletions

View File

@ -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,

View File

@ -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 {

View File

@ -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 }));