diff --git a/src/api/mods.js b/src/api/mods.js
index 9e1c2c4..8434a91 100644
--- a/src/api/mods.js
+++ b/src/api/mods.js
@@ -39,7 +39,7 @@ const getProfile = async () => {
const { initDatabase } = globalThis.__enhancerApi,
db = initDatabase();
let activeProfile = await db.get("activeProfile");
- activeProfile ??= await db.get("profileIds")?.[0];
+ activeProfile ??= (await db.get("profileIds"))?.[0];
return activeProfile ?? "default";
},
isEnabled = async (id) => {
diff --git a/src/core/menu/components.mjs b/src/core/menu/components.mjs
index 00fa862..8134eb5 100644
--- a/src/core/menu/components.mjs
+++ b/src/core/menu/components.mjs
@@ -21,7 +21,7 @@ function _Button(
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)]
+ ? `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)])
@@ -776,8 +776,8 @@ function Profile({
setName,
isActive,
setActive,
- exportData,
- importData,
+ exportJson,
+ importJson,
...props
}) {
const { html } = globalThis.__enhancerApi,
@@ -785,12 +785,8 @@ function Profile({
const file = event.target.files[0],
reader = new FileReader();
reader.onload = async (progress) => {
- try {
- const res = JSON.parse(progress.currentTarget.result);
- importData(res);
- } catch {
- // throw error
- }
+ const res = progress.currentTarget.result;
+ importJson(res);
};
reader.readAsText(file);
},
@@ -807,8 +803,8 @@ function Profile({
const $a = html``;
document.body.append($a);
@@ -818,18 +814,16 @@ function Profile({
return html`
<${Checkbox}
- checked=${isActive}
- disabled=${isActive}
- ...${{ _set: setActive }}
+ ...${{ _get: isActive, _set: setActive }}
+ onchange=${(event) => (event.target.checked = true)}
/>
<${Input}
size="md"
type="text"
icon="file-cog"
onchange=${(event) => setName(event.target.value)}
- onrerender=${($input) => {
- getName().then((value) => ($input.value = value));
- }}
+ onrerender=${($input) =>
+ getName().then((value) => ($input.value = value))}
/>
<${Label} size="sm" icon="import">
{
return $sidebar;
},
renderList = async (id, mods, description) => {
- const { html, getProfile, initDatabase } = globalThis.__enhancerApi,
- enabledMods = initDatabase([await getProfile(), "enabledMods"]);
+ const { html, isEnabled } = globalThis.__enhancerApi;
mods = mods.map(async (mod) => {
- const _get = () => enabledMods.get(mod.id),
+ const _get = () => isEnabled(mod.id),
_set = async (enabled) => {
- await enabledMods.set(mod.id, enabled);
+ await setEnabled(mod.id, enabled);
setState({ rerender: true, databaseUpdated: true });
};
return html`<${Mod} ...${{ ...mod, _get, _set }} />`;
@@ -81,11 +86,8 @@ const renderSidebar = (items, categories) => {
/>`;
},
renderOptions = async (mod) => {
- const { html, platform, getProfile } = globalThis.__enhancerApi,
- { optionDefaults, initDatabase } = globalThis.__enhancerApi,
- profile = await getProfile(),
- db = initDatabase([profile, mod.id], await optionDefaults(mod.id));
- let options = mod.options.reduce((options, opt, i) => {
+ const { html, platform, getProfile } = globalThis.__enhancerApi;
+ let options = mod.options.reduce((options, opt) => {
if (!opt.key && (opt.type !== "heading" || !opt.label)) return options;
if (opt.platforms && !opt.platforms.includes(platform)) return options;
const prevOpt = options[options.length - 1];
@@ -99,9 +101,9 @@ const renderSidebar = (items, categories) => {
if (options[options.length - 1]?.type === "heading") options.pop();
options = options.map(async (opt) => {
if (opt.type === "heading") return html`<${Option} ...${opt} />`;
- const _get = () => db.get(opt.key),
+ const _get = async () => (await modDatabase(mod.id)).get(opt.key),
_set = async (value) => {
- await db.set(opt.key, value);
+ await (await modDatabase(mod.id)).set(opt.key, value);
setState({ rerender: true, databaseUpdated: true });
};
return html`<${Option} ...${{ ...opt, _get, _set }} />`;
@@ -109,37 +111,49 @@ const renderSidebar = (items, categories) => {
return Promise.all(options);
},
renderProfiles = async () => {
- const { html, getProfile, initDatabase, reloadApp } =
- globalThis.__enhancerApi,
- db = initDatabase();
-
let profileIds;
- const $list = html``,
- activeProfile = await getProfile(),
+ const { html, initDatabase, getProfile } = globalThis.__enhancerApi,
+ db = initDatabase(),
+ $list = html``,
renderProfile = (id) => {
const profile = initDatabase([id]);
return html`<${Profile}
+ id=${id}
getName=${async () =>
(await profile.get("profileName")) ??
(id === "default" ? "default" : "")}
setName=${(name) => profile.set("profileName", name)}
- isActive=${id === activeProfile}
- setActive=${async (active) => {
- if (!active) return;
+ isActive=${async () => id === (await getProfile())}
+ setActive=${async () => {
await db.set("activeProfile", id);
- reloadApp();
- }}
- exportData=${profile.export}
- importData=${async (data) => {
- await profile.import(data);
setState({ rerender: true, databaseUpdated: true });
}}
+ exportJson=${async () => JSON.stringify(await profile.export())}
+ importJson=${async (json) => {
+ try {
+ await profile.import(JSON.parse(json));
+ setState({ rerender: true, databaseUpdated: true });
+ } catch {
+ // error
+ }
+ }}
/>`;
},
refreshProfiles = async () => {
- profileIds = (await db.get("profileIds")) ?? ["default"];
- const profiles = await Promise.all(profileIds.map(renderProfile));
- $list.replaceChildren(...profiles);
+ profileIds = await db.get("profileIds");
+ if (!profileIds?.length) profileIds = ["default"];
+ for (const $profile of $list.children) {
+ const exists = profileIds.includes($profile.id);
+ if (!exists) $profile.remove();
+ }
+ for (let i = 0; i < profileIds.length; i++) {
+ const id = profileIds[i];
+ if (document.getElementById(id)) continue;
+ const $profile = await renderProfile(id),
+ $next = document.getElementById(profileIds[i + 1]);
+ if ($next) $list.insertBefore($profile, $next);
+ else $list.append($profile);
+ }
},
addProfile = async (name) => {
const id = crypto.randomUUID();
@@ -148,9 +162,7 @@ const renderSidebar = (items, categories) => {
await profile.set("profileName", name);
refreshProfiles();
};
- useState(["rerender"], () => {
- refreshProfiles();
- });
+ useState(["rerender"], () => refreshProfiles());
// todo: deleting profiles inc. clearing db keys,
// throwing errors on invalid json upload
@@ -186,16 +198,15 @@ const renderSidebar = (items, categories) => {
`;
},
renderMods = async (mods) => {
- const { html, getProfile, initDatabase } = globalThis.__enhancerApi,
- enabledMods = initDatabase([await getProfile(), "enabledMods"]);
+ const { html, isEnabled } = globalThis.__enhancerApi;
mods = mods
.filter((mod) => {
return mod.options?.filter((opt) => opt.type !== "heading").length;
})
.map(async (mod) => {
- const _get = () => enabledMods.get(mod.id),
+ const _get = () => isEnabled(mod.id),
_set = async (enabled) => {
- await enabledMods.set(mod.id, enabled);
+ await setEnabled(mod.id, enabled);
setState({ rerender: true, databaseUpdated: true });
};
return html`<${View} id=${mod.id}>
@@ -218,9 +229,10 @@ const render = async () => {
icon: "palette",
id: "themes",
title: "Themes",
- description: `Themes override Notion's colour schemes. To switch between
- dark mode and light mode, go to Settings & members → My notifications
- & settings → My settings → Appearance.`,
+ description: `Themes override Notion's colour schemes. Dark themes require
+ Notion to be in dark mode and light themes require Notion to be in light
+ mode. To switch between dark mode and light mode, go to Settings &
+ members → My notifications & settings → My settings → Appearance.`,
mods: compatibleMods(await getThemes()),
},
{
diff --git a/src/core/menu/state.mjs b/src/core/menu/state.mjs
index 6c08fb5..e8e81d3 100644
--- a/src/core/menu/state.mjs
+++ b/src/core/menu/state.mjs
@@ -21,4 +21,18 @@ const _state = {},
callback(getState(keys));
};
-export { setState, useState, getState };
+const setEnabled = async (id, enabled) => {
+ const { getProfile, initDatabase } = globalThis.__enhancerApi;
+ // prettier-ignore
+ return await initDatabase([
+ await getProfile(),
+ "enabledMods"
+ ]).set(id, enabled);
+ },
+ modDatabase = async (id) => {
+ const { getProfile, initDatabase } = globalThis.__enhancerApi,
+ { optionDefaults } = globalThis.__enhancerApi;
+ return initDatabase([await getProfile(), id], await optionDefaults(id));
+ };
+
+export { setState, useState, getState, setEnabled, modDatabase };