chore(menu): detect db update by comparing against prev value

- syncs reload btn visibility b/w tabs
- doesn't trigger when switching profiles if identical
This commit is contained in:
dragonwocky 2023-02-03 13:04:12 +11:00
parent ba98ed6412
commit a6e9504b6f
Signed by: dragonwocky
GPG Key ID: 7998D08F7D7BD7A8
10 changed files with 59 additions and 29 deletions

View File

@ -52,18 +52,17 @@ const insertMenu = async (db) => {
let _contentWindow;
const sendThemePing = () => {
if (!_contentWindow) return;
const darkMode = document.body.classList.contains("dark"),
notionTheme = darkMode ? "dark" : "light";
if (renderPing.theme === notionTheme) return;
renderPing.theme = notionTheme;
_contentWindow.postMessage(renderPing, "*");
_contentWindow?.postMessage?.(renderPing, "*");
},
sendRenderPing = (contentWindow) => {
_contentWindow ??= contentWindow;
if (!$modal.hasAttribute("open")) return;
delete renderPing.theme;
_contentWindow.focus();
_contentWindow?.focus?.();
sendThemePing();
};

View File

@ -4,9 +4,10 @@
* (https://notion-enhancer.github.io/) under the MIT license
*/
import { useState } from "../state.mjs";
import { setState, useState } from "../state.mjs";
function Checkbox({ _get, _set, ...props }) {
function Checkbox({ _get, _set, _requireReload = true, ...props }) {
let _initialValue;
const { html, extendProps } = globalThis.__enhancerApi,
$input = html`<input
type="checkbox"
@ -21,6 +22,10 @@ function Checkbox({ _get, _set, ...props }) {
useState(["rerender"], async () => {
const checked = (await _get?.()) ?? $input.checked;
$input.checked = checked;
if (_requireReload) {
_initialValue ??= checked;
if (checked !== _initialValue) setState({ databaseUpdated: true });
}
});
return html`<label

View File

@ -4,7 +4,7 @@
* (https://notion-enhancer.github.io/) under the MIT license
*/
import { useState } from "../state.mjs";
import { setState, useState } from "../state.mjs";
const updateHotkey = (event) => {
const keys = [];
@ -72,6 +72,7 @@ function Input({
class: className,
_get,
_set,
_requireReload = true,
...props
}) {
let $filename, $clear;
@ -117,6 +118,7 @@ function Input({
><i class="i-${icon} w-[16px] h-[16px]"></i>
</span>`;
let _initialValue;
extendProps($input, {
onchange: (event) => {
if (_set && type === "file") {
@ -128,8 +130,20 @@ function Input({
if (type === "file") {
$filename.innerText = value?.filename || "Upload a file";
$clear.style.display = value?.filename ? "" : "none";
} else if ($input.value !== value) $input.value = value;
if (type === "color") updateContrast($input, $icon);
if (_requireReload) {
_initialValue ??= value?.content || "";
if ((value?.content || "") !== _initialValue) {
setState({ databaseUpdated: true });
}
}
} else {
if ($input.value !== value) $input.value = value;
if (_requireReload) {
_initialValue ??= value;
if (value !== _initialValue) setState({ databaseUpdated: true });
}
if (type === "color") updateContrast($input, $icon);
}
},
onkeydown: type === "hotkey" ? updateHotkey : undefined,
oninput: type === "color" ? () => _set?.($input.value) : undefined,

View File

@ -4,7 +4,7 @@
* (https://notion-enhancer.github.io/) under the MIT license
*/
import { useState } from "../state.mjs";
import { setState, useState } from "../state.mjs";
import { Popup } from "./Popup.mjs";
function Option({ value, _get, _set }) {
@ -33,7 +33,8 @@ function Option({ value, _get, _set }) {
return $option;
}
function Select({ values, _get, _set, ...props }) {
function Select({ values, _get, _set, _requireReload = true, ...props }) {
let _initialValue;
const { html } = globalThis.__enhancerApi,
// dir="rtl" overflows to the left during transition
$select = html`<div
@ -45,8 +46,13 @@ function Select({ values, _get, _set, ...props }) {
transition duration-[20ms] hover:bg-[color:var(--theme--bg-hover)]"
...${props}
></div>`;
useState(["rerender"], () => {
_get?.().then((value) => ($select.innerText = value));
useState(["rerender"], async () => {
const value = (await _get?.()) ?? $select.innerText;
$select.innerText = value;
if (_requireReload) {
_initialValue ??= value;
if (value !== _initialValue) setState({ databaseUpdated: true });
}
});
return html`<div class="notion-enhancer--menu-select relative">

View File

@ -4,9 +4,10 @@
* (https://notion-enhancer.github.io/) under the MIT license
*/
import { useState } from "../state.mjs";
import { setState, useState } from "../state.mjs";
function Toggle({ _get, _set, ...props }) {
function Toggle({ _get, _set, _requireReload = true, ...props }) {
let _initialValue;
const { html, extendProps } = globalThis.__enhancerApi,
$input = html`<input
type="checkbox"
@ -19,6 +20,10 @@ function Toggle({ _get, _set, ...props }) {
useState(["rerender"], async () => {
const checked = (await _get?.()) ?? $input.checked;
$input.checked = checked;
if (_requireReload) {
_initialValue ??= checked;
if (checked !== _initialValue) setState({ databaseUpdated: true });
}
});
return html`<div class="notion-enhancer--menu-toggle shrink-0">

View File

@ -58,7 +58,7 @@ function List({ id, mods, description }) {
}
}
}
setState({ rerender: true, databaseUpdated: true });
setState({ rerender: true });
};
return html`<${Mod} ...${{ ...mod, _get, _set }} />`;
});

View File

@ -79,7 +79,7 @@ function Options({ mod }) {
const _get = async () => (await modDatabase(mod.id)).get(opt.key),
_set = async (value) => {
await (await modDatabase(mod.id)).set(opt.key, value);
setState({ rerender: true, databaseUpdated: true });
setState({ rerender: true });
};
return html`<${Option} ...${{ _get, _set, ...opt }} />`;
});

View File

@ -33,7 +33,7 @@ function Profile({ id }) {
setActive = async () => {
if (await isActive()) return;
await db.set("activeProfile", id);
setState({ rerender: true, databaseUpdated: true });
setState({ rerender: true });
};
const $successName = html`<span
@ -64,7 +64,7 @@ function Profile({ id }) {
res = JSON.parse(res);
delete res["profileName"];
await profile.import(res);
setState({ rerender: true, databaseUpdated: true });
setState({ rerender: true });
$uploadSuccess.show();
setTimeout(() => $uploadSuccess.hide(), 2000);
} catch (err) {
@ -113,10 +113,8 @@ function Profile({ id }) {
const index = profileIds.indexOf(id);
if (index > -1) profileIds.splice(index, 1);
await db.set("profileIds", profileIds);
if (await isActive()) {
await db.remove("activeProfile");
setState({ rerender: true, databaseUpdated: true });
} else setState({ rerender: true });
if (await isActive()) await db.remove("activeProfile");
setState({ rerender: true });
},
$delete = html`<button
class="h-[14px] transition duration-[20ms]
@ -155,10 +153,13 @@ function Profile({ id }) {
return html`<li class="flex items-center my-[14px] gap-[8px]" id=${id}>
<${Checkbox}
...${{ _get: isActive, _set: setActive }}
...${{ _get: isActive, _set: setActive, _requireReload: false }}
onchange=${(event) => (event.target.checked = true)}
/>
<${Input} icon="file-cog" ...${{ _get: getName, _set: setName }} />
<${Input}
icon="file-cog"
...${{ _get: getName, _set: setName, _requireReload: false }}
/>
<${Button}
icon="import"
variant="sm"

View File

@ -9,8 +9,8 @@ import { Option } from "./Options.mjs";
const privacyPolicy = "https://notion-enhancer.github.io/about/privacy-policy/";
function Telemetry() {
const { html, platform, version, getMods } = globalThis.__enhancerApi,
{ getProfile, isEnabled, initDatabase } = globalThis.__enhancerApi,
const { html, platform, version } = globalThis.__enhancerApi,
{ getMods, isEnabled, initDatabase } = globalThis.__enhancerApi,
timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
const $enabledMods = html`<code></code>`;
@ -29,7 +29,7 @@ function Telemetry() {
},
_set = async (value) => {
await initDatabase().set("telemetryEnabled", value);
setState({ rerender: true, databaseUpdated: true });
setState({ rerender: true });
};
// todo: actually collect telemetry
@ -44,7 +44,7 @@ function Telemetry() {
(<code>"${version}"</code>), and enabled mods (${$enabledMods}). You can
opt in or out of telemetry at any time. This setting syncs across
configuration profiles. For more information, read the notion-enhancer's
<a href=${privacyPolicy}>privacy policy</a>.`}
<a href=${privacyPolicy} class="ml-[3px]">privacy policy</a>.`}
...${{ _get, _set }}
/>`;
}

View File

@ -107,7 +107,7 @@ const render = async () => {
const _get = () => isEnabled(mods[i].id),
_set = async (enabled) => {
await setEnabled(mods[i].id, enabled);
setState({ rerender: true, databaseUpdated: true });
setState({ rerender: true });
};
mods[i].view = html`<${View} id=${mods[i].id}>
<!-- passing an empty options array hides the settings button -->