mirror of
https://github.com/notion-enhancer/notion-enhancer.git
synced 2025-04-11 15:59:03 +00:00
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:
parent
ba98ed6412
commit
a6e9504b6f
@ -52,18 +52,17 @@ const insertMenu = async (db) => {
|
|||||||
|
|
||||||
let _contentWindow;
|
let _contentWindow;
|
||||||
const sendThemePing = () => {
|
const sendThemePing = () => {
|
||||||
if (!_contentWindow) return;
|
|
||||||
const darkMode = document.body.classList.contains("dark"),
|
const darkMode = document.body.classList.contains("dark"),
|
||||||
notionTheme = darkMode ? "dark" : "light";
|
notionTheme = darkMode ? "dark" : "light";
|
||||||
if (renderPing.theme === notionTheme) return;
|
if (renderPing.theme === notionTheme) return;
|
||||||
renderPing.theme = notionTheme;
|
renderPing.theme = notionTheme;
|
||||||
_contentWindow.postMessage(renderPing, "*");
|
_contentWindow?.postMessage?.(renderPing, "*");
|
||||||
},
|
},
|
||||||
sendRenderPing = (contentWindow) => {
|
sendRenderPing = (contentWindow) => {
|
||||||
_contentWindow ??= contentWindow;
|
_contentWindow ??= contentWindow;
|
||||||
if (!$modal.hasAttribute("open")) return;
|
if (!$modal.hasAttribute("open")) return;
|
||||||
delete renderPing.theme;
|
delete renderPing.theme;
|
||||||
_contentWindow.focus();
|
_contentWindow?.focus?.();
|
||||||
sendThemePing();
|
sendThemePing();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -4,9 +4,10 @@
|
|||||||
* (https://notion-enhancer.github.io/) under the MIT license
|
* (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,
|
const { html, extendProps } = globalThis.__enhancerApi,
|
||||||
$input = html`<input
|
$input = html`<input
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
@ -21,6 +22,10 @@ function Checkbox({ _get, _set, ...props }) {
|
|||||||
useState(["rerender"], async () => {
|
useState(["rerender"], async () => {
|
||||||
const checked = (await _get?.()) ?? $input.checked;
|
const checked = (await _get?.()) ?? $input.checked;
|
||||||
$input.checked = checked;
|
$input.checked = checked;
|
||||||
|
if (_requireReload) {
|
||||||
|
_initialValue ??= checked;
|
||||||
|
if (checked !== _initialValue) setState({ databaseUpdated: true });
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return html`<label
|
return html`<label
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
* (https://notion-enhancer.github.io/) under the MIT license
|
* (https://notion-enhancer.github.io/) under the MIT license
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { useState } from "../state.mjs";
|
import { setState, useState } from "../state.mjs";
|
||||||
|
|
||||||
const updateHotkey = (event) => {
|
const updateHotkey = (event) => {
|
||||||
const keys = [];
|
const keys = [];
|
||||||
@ -72,6 +72,7 @@ function Input({
|
|||||||
class: className,
|
class: className,
|
||||||
_get,
|
_get,
|
||||||
_set,
|
_set,
|
||||||
|
_requireReload = true,
|
||||||
...props
|
...props
|
||||||
}) {
|
}) {
|
||||||
let $filename, $clear;
|
let $filename, $clear;
|
||||||
@ -117,6 +118,7 @@ function Input({
|
|||||||
><i class="i-${icon} w-[16px] h-[16px]"></i>
|
><i class="i-${icon} w-[16px] h-[16px]"></i>
|
||||||
</span>`;
|
</span>`;
|
||||||
|
|
||||||
|
let _initialValue;
|
||||||
extendProps($input, {
|
extendProps($input, {
|
||||||
onchange: (event) => {
|
onchange: (event) => {
|
||||||
if (_set && type === "file") {
|
if (_set && type === "file") {
|
||||||
@ -128,8 +130,20 @@ function Input({
|
|||||||
if (type === "file") {
|
if (type === "file") {
|
||||||
$filename.innerText = value?.filename || "Upload a file";
|
$filename.innerText = value?.filename || "Upload a file";
|
||||||
$clear.style.display = value?.filename ? "" : "none";
|
$clear.style.display = value?.filename ? "" : "none";
|
||||||
} else if ($input.value !== value) $input.value = value;
|
if (_requireReload) {
|
||||||
if (type === "color") updateContrast($input, $icon);
|
_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,
|
onkeydown: type === "hotkey" ? updateHotkey : undefined,
|
||||||
oninput: type === "color" ? () => _set?.($input.value) : undefined,
|
oninput: type === "color" ? () => _set?.($input.value) : undefined,
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
* (https://notion-enhancer.github.io/) under the MIT license
|
* (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";
|
import { Popup } from "./Popup.mjs";
|
||||||
|
|
||||||
function Option({ value, _get, _set }) {
|
function Option({ value, _get, _set }) {
|
||||||
@ -33,7 +33,8 @@ function Option({ value, _get, _set }) {
|
|||||||
return $option;
|
return $option;
|
||||||
}
|
}
|
||||||
|
|
||||||
function Select({ values, _get, _set, ...props }) {
|
function Select({ values, _get, _set, _requireReload = true, ...props }) {
|
||||||
|
let _initialValue;
|
||||||
const { html } = globalThis.__enhancerApi,
|
const { html } = globalThis.__enhancerApi,
|
||||||
// dir="rtl" overflows to the left during transition
|
// dir="rtl" overflows to the left during transition
|
||||||
$select = html`<div
|
$select = html`<div
|
||||||
@ -45,8 +46,13 @@ function Select({ values, _get, _set, ...props }) {
|
|||||||
transition duration-[20ms] hover:bg-[color:var(--theme--bg-hover)]"
|
transition duration-[20ms] hover:bg-[color:var(--theme--bg-hover)]"
|
||||||
...${props}
|
...${props}
|
||||||
></div>`;
|
></div>`;
|
||||||
useState(["rerender"], () => {
|
useState(["rerender"], async () => {
|
||||||
_get?.().then((value) => ($select.innerText = value));
|
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">
|
return html`<div class="notion-enhancer--menu-select relative">
|
||||||
|
@ -4,9 +4,10 @@
|
|||||||
* (https://notion-enhancer.github.io/) under the MIT license
|
* (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,
|
const { html, extendProps } = globalThis.__enhancerApi,
|
||||||
$input = html`<input
|
$input = html`<input
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
@ -19,6 +20,10 @@ function Toggle({ _get, _set, ...props }) {
|
|||||||
useState(["rerender"], async () => {
|
useState(["rerender"], async () => {
|
||||||
const checked = (await _get?.()) ?? $input.checked;
|
const checked = (await _get?.()) ?? $input.checked;
|
||||||
$input.checked = checked;
|
$input.checked = checked;
|
||||||
|
if (_requireReload) {
|
||||||
|
_initialValue ??= checked;
|
||||||
|
if (checked !== _initialValue) setState({ databaseUpdated: true });
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return html`<div class="notion-enhancer--menu-toggle shrink-0">
|
return html`<div class="notion-enhancer--menu-toggle shrink-0">
|
||||||
|
@ -58,7 +58,7 @@ function List({ id, mods, description }) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
setState({ rerender: true, databaseUpdated: true });
|
setState({ rerender: true });
|
||||||
};
|
};
|
||||||
return html`<${Mod} ...${{ ...mod, _get, _set }} />`;
|
return html`<${Mod} ...${{ ...mod, _get, _set }} />`;
|
||||||
});
|
});
|
||||||
|
@ -79,7 +79,7 @@ function Options({ mod }) {
|
|||||||
const _get = async () => (await modDatabase(mod.id)).get(opt.key),
|
const _get = async () => (await modDatabase(mod.id)).get(opt.key),
|
||||||
_set = async (value) => {
|
_set = async (value) => {
|
||||||
await (await modDatabase(mod.id)).set(opt.key, value);
|
await (await modDatabase(mod.id)).set(opt.key, value);
|
||||||
setState({ rerender: true, databaseUpdated: true });
|
setState({ rerender: true });
|
||||||
};
|
};
|
||||||
return html`<${Option} ...${{ _get, _set, ...opt }} />`;
|
return html`<${Option} ...${{ _get, _set, ...opt }} />`;
|
||||||
});
|
});
|
||||||
|
@ -33,7 +33,7 @@ function Profile({ id }) {
|
|||||||
setActive = async () => {
|
setActive = async () => {
|
||||||
if (await isActive()) return;
|
if (await isActive()) return;
|
||||||
await db.set("activeProfile", id);
|
await db.set("activeProfile", id);
|
||||||
setState({ rerender: true, databaseUpdated: true });
|
setState({ rerender: true });
|
||||||
};
|
};
|
||||||
|
|
||||||
const $successName = html`<span
|
const $successName = html`<span
|
||||||
@ -64,7 +64,7 @@ function Profile({ id }) {
|
|||||||
res = JSON.parse(res);
|
res = JSON.parse(res);
|
||||||
delete res["profileName"];
|
delete res["profileName"];
|
||||||
await profile.import(res);
|
await profile.import(res);
|
||||||
setState({ rerender: true, databaseUpdated: true });
|
setState({ rerender: true });
|
||||||
$uploadSuccess.show();
|
$uploadSuccess.show();
|
||||||
setTimeout(() => $uploadSuccess.hide(), 2000);
|
setTimeout(() => $uploadSuccess.hide(), 2000);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
@ -113,10 +113,8 @@ function Profile({ id }) {
|
|||||||
const index = profileIds.indexOf(id);
|
const index = profileIds.indexOf(id);
|
||||||
if (index > -1) profileIds.splice(index, 1);
|
if (index > -1) profileIds.splice(index, 1);
|
||||||
await db.set("profileIds", profileIds);
|
await db.set("profileIds", profileIds);
|
||||||
if (await isActive()) {
|
if (await isActive()) await db.remove("activeProfile");
|
||||||
await db.remove("activeProfile");
|
setState({ rerender: true });
|
||||||
setState({ rerender: true, databaseUpdated: true });
|
|
||||||
} else setState({ rerender: true });
|
|
||||||
},
|
},
|
||||||
$delete = html`<button
|
$delete = html`<button
|
||||||
class="h-[14px] transition duration-[20ms]
|
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}>
|
return html`<li class="flex items-center my-[14px] gap-[8px]" id=${id}>
|
||||||
<${Checkbox}
|
<${Checkbox}
|
||||||
...${{ _get: isActive, _set: setActive }}
|
...${{ _get: isActive, _set: setActive, _requireReload: false }}
|
||||||
onchange=${(event) => (event.target.checked = true)}
|
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}
|
<${Button}
|
||||||
icon="import"
|
icon="import"
|
||||||
variant="sm"
|
variant="sm"
|
||||||
|
@ -9,8 +9,8 @@ import { Option } from "./Options.mjs";
|
|||||||
|
|
||||||
const privacyPolicy = "https://notion-enhancer.github.io/about/privacy-policy/";
|
const privacyPolicy = "https://notion-enhancer.github.io/about/privacy-policy/";
|
||||||
function Telemetry() {
|
function Telemetry() {
|
||||||
const { html, platform, version, getMods } = globalThis.__enhancerApi,
|
const { html, platform, version } = globalThis.__enhancerApi,
|
||||||
{ getProfile, isEnabled, initDatabase } = globalThis.__enhancerApi,
|
{ getMods, isEnabled, initDatabase } = globalThis.__enhancerApi,
|
||||||
timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
|
timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
|
||||||
|
|
||||||
const $enabledMods = html`<code></code>`;
|
const $enabledMods = html`<code></code>`;
|
||||||
@ -29,7 +29,7 @@ function Telemetry() {
|
|||||||
},
|
},
|
||||||
_set = async (value) => {
|
_set = async (value) => {
|
||||||
await initDatabase().set("telemetryEnabled", value);
|
await initDatabase().set("telemetryEnabled", value);
|
||||||
setState({ rerender: true, databaseUpdated: true });
|
setState({ rerender: true });
|
||||||
};
|
};
|
||||||
|
|
||||||
// todo: actually collect telemetry
|
// todo: actually collect telemetry
|
||||||
@ -44,7 +44,7 @@ function Telemetry() {
|
|||||||
(<code>"${version}"</code>), and enabled mods (${$enabledMods}). You can
|
(<code>"${version}"</code>), and enabled mods (${$enabledMods}). You can
|
||||||
opt in or out of telemetry at any time. This setting syncs across
|
opt in or out of telemetry at any time. This setting syncs across
|
||||||
configuration profiles. For more information, read the notion-enhancer's
|
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 }}
|
...${{ _get, _set }}
|
||||||
/>`;
|
/>`;
|
||||||
}
|
}
|
||||||
|
@ -107,7 +107,7 @@ const render = async () => {
|
|||||||
const _get = () => isEnabled(mods[i].id),
|
const _get = () => isEnabled(mods[i].id),
|
||||||
_set = async (enabled) => {
|
_set = async (enabled) => {
|
||||||
await setEnabled(mods[i].id, enabled);
|
await setEnabled(mods[i].id, enabled);
|
||||||
setState({ rerender: true, databaseUpdated: true });
|
setState({ rerender: true });
|
||||||
};
|
};
|
||||||
mods[i].view = html`<${View} id=${mods[i].id}>
|
mods[i].view = html`<${View} id=${mods[i].id}>
|
||||||
<!-- passing an empty options array hides the settings button -->
|
<!-- passing an empty options array hides the settings button -->
|
||||||
|
Loading…
Reference in New Issue
Block a user