diff --git a/src/api/browser.js b/src/api/browser.js index 4f4d91e..e856d10 100644 --- a/src/api/browser.js +++ b/src/api/browser.js @@ -44,29 +44,32 @@ const initDatabase = (namespace, fallbacks = {}) => { const fallback = fallbacks[key]; key = key.startsWith(namespace) ? key : namespace + key; return new Promise((res, _rej) => { - chrome.storage.local.get([key], ({ [key]: value }) => - res(value ?? fallback) - ); + chrome.storage.local.get([key], ({ [key]: value }) => { + return res(value ?? fallback); + }); }); }, set: async (key, value) => { key = key.startsWith(namespace) ? key : namespace + key; return new Promise((res, _rej) => { - chrome.storage.local.set({ [key]: value }, () => res(value)); + chrome.storage.local.set({ [key]: value }, () => res(true)); }); }, - dump: async () => { + export: async () => { const obj = await new Promise((res, _rej) => { chrome.storage.local.get((value) => res(value)); }); if (!namespace) return obj; - let entries = Object.entries(obj); - entries = entries.filter(([key]) => key.startsWith(namespace)); + const entries = Object.entries(obj) + .filter(([key]) => key.startsWith(namespace)) + .map(([key, value]) => [key.slice(namespace.length), value]); return Object.fromEntries(entries); }, - populate: async (obj) => { + import: async (obj) => { + const entries = Object.entries(obj) // + .map(([key, value]) => [namespace + key, value]); return new Promise((res, _rej) => { - chrome.storage.local.set(obj, () => res(obj)); + chrome.storage.local.set(Object.fromEntries(entries), () => res(true)); }); }, }; diff --git a/src/api/electron.cjs b/src/api/electron.cjs index a8364de..479e704 100644 --- a/src/api/electron.cjs +++ b/src/api/electron.cjs @@ -51,6 +51,13 @@ const initDatabase = (namespace, fallbacks = {}) => { if (Array.isArray(namespace)) namespace = namespace.join("__"); namespace = namespace ? namespace + "__" : ""; + // schema: + // - ("profileIds") = $profileId[] + // - ("activeProfile") -> $profileId + // - $profileId: ("profileName") -> string + // - $profileId__enabledMods: ($modId) -> boolean + // - $profileId__$modId: ($optionKey) -> value + const table = "settings", sqlite = require("better-sqlite3"), db = __db ?? sqlite(path.resolve(`${os.homedir()}/.notion-enhancer.db`)), @@ -93,14 +100,19 @@ const initDatabase = (namespace, fallbacks = {}) => { } else update.run(value, key); return Promise.resolve(true); }, - dump: () => { + export: () => { const entries = dump .all() - .map(({ key, value }) => [key, value]) - .filter(([key]) => key.startsWith(namespace)); + .filter(({ key }) => key.startsWith(namespace)) + .map(({ key, value }) => [key.slice(namespace.length), value]); return Promise.resolve(Object.fromEntries(entries)); }, - populate, + import: (obj) => { + const entries = Object.entries(obj) // + .map(([key, value]) => [key.slice(namespace.length), value]); + populate(Object.fromEntries(entries)); + return Promise.resolve(true); + }, }; }; diff --git a/src/api/interface.js b/src/api/interface.js index c67db69..7bffb00 100644 --- a/src/api/interface.js +++ b/src/api/interface.js @@ -50,7 +50,6 @@ const encodeSvg = (svg) => svg = hToString(type, props, ...children); } // https://antfu.me/posts/icons-in-pure-css - if (!svg) console.log(icon); const dataUri = `url("data:image/svg+xml;utf8,${encodeSvg(svg)}")`; if (mode === "auto") mode = undefined; mode ??= svg.includes("currentColor") ? "mask" : "bg"; diff --git a/src/api/mods.js b/src/api/mods.js index 8818b51..9e1c2c4 100644 --- a/src/api/mods.js +++ b/src/api/mods.js @@ -37,8 +37,10 @@ const getMods = async () => { const getProfile = async () => { const { initDatabase } = globalThis.__enhancerApi, - currentProfile = await initDatabase().get("currentProfile"); - return currentProfile ?? "default"; + db = initDatabase(); + let activeProfile = await db.get("activeProfile"); + activeProfile ??= await db.get("profileIds")?.[0]; + return activeProfile ?? "default"; }, isEnabled = async (id) => { const { platform } = globalThis.__enhancerApi, diff --git a/src/core/menu/components.mjs b/src/core/menu/components.mjs index 6ed9401..00fa862 100644 --- a/src/core/menu/components.mjs +++ b/src/core/menu/components.mjs @@ -6,6 +6,70 @@ import { setState, useState, getState } from "./state.mjs"; +// generic + +function _Button( + { type, size, icon, primary, class: cls = "", ...props }, + ...children +) { + const { html } = globalThis.__enhancerApi, + iconSize = + size === "sm" && children.length + ? "w-[14px] h-[14px]" + : "w-[18px] h-[18px]"; + return html`<${type} + class="flex gap-[8px] items-center px-[12px] shrink-0 + rounded-[4px] ${size === "sm" ? "h-[28px]" : "h-[32px]"} + transition duration-[20ms] ${primary + ? `text-[color:var(--theme--accent-primary_contrast)] + 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)]`} ${cls}" + ...${props} + > + ${icon ? html`` : ""} + + ${children} + + />`; +} + +function Button(props, ...children) { + const { html } = globalThis.__enhancerApi; + return html`<${_Button} type="button" ...${props}>${children}/>`; +} + +function Label(props, ...children) { + const { html } = globalThis.__enhancerApi; + return html`<${_Button} type="label" ...${props}>${children}/>`; +} + +function Description({ class: cls = "", ...props }, ...children) { + const { html } = globalThis.__enhancerApi; + return html`
`; +} + +function Icon({ icon, ...props }) { + const { html } = globalThis.__enhancerApi; + return html``; +} + +// layout + function Sidebar({}, ...children) { const { html } = globalThis.__enhancerApi; return html`