mirror of
https://github.com/notion-enhancer/notion-enhancer.git
synced 2025-04-11 15:59:03 +00:00
chore(menu): add telemetry toggle
This commit is contained in:
parent
f999969c13
commit
567e678a6f
@ -71,12 +71,14 @@ const initDatabase = (namespace, fallbacks = {}) => {
|
|||||||
)`);
|
)`);
|
||||||
init.run();
|
init.run();
|
||||||
|
|
||||||
// schema:
|
// schema:
|
||||||
// - ("profileIds") = $profileId[]
|
// - ("profileIds") -> $profileId[]
|
||||||
// - ("activeProfile") -> $profileId
|
// - ("activeProfile") -> $profileId
|
||||||
// - $profileId: ("profileName") -> string
|
// - $profileId: ("profileName") -> string
|
||||||
|
// - $profileId: ("telemetryEnabled") -> boolean
|
||||||
// - $profileId__enabledMods: ($modId) -> boolean
|
// - $profileId__enabledMods: ($modId) -> boolean
|
||||||
// - $profileId__$modId: ($optionKey) -> value
|
// - $profileId__$modId: ($optionKey) -> value
|
||||||
|
|
||||||
__statements = {
|
__statements = {
|
||||||
insert: db.prepare(`INSERT INTO ${table} (key, value) VALUES (?, ?)`),
|
insert: db.prepare(`INSERT INTO ${table} (key, value) VALUES (?, ?)`),
|
||||||
update: db.prepare(`UPDATE ${table} SET value = ? WHERE key = ?`),
|
update: db.prepare(`UPDATE ${table} SET value = ? WHERE key = ?`),
|
||||||
|
@ -9,8 +9,8 @@ import { extendProps } from "../state.mjs";
|
|||||||
function Description(props, ...children) {
|
function Description(props, ...children) {
|
||||||
const { html } = globalThis.__enhancerApi;
|
const { html } = globalThis.__enhancerApi;
|
||||||
extendProps(props, {
|
extendProps(props, {
|
||||||
class: `notion-enhancer--menu-description leading-[16px]
|
class: `notion-enhancer--menu-description typography
|
||||||
text-([12px] [color:var(--theme--fg-secondary)])`,
|
leading-[16px] text-([12px] [color:var(--theme--fg-secondary)])`,
|
||||||
});
|
});
|
||||||
return html`<p ...${props}>${children}</p>`;
|
return html`<p ...${props}>${children}</p>`;
|
||||||
}
|
}
|
||||||
|
@ -6,11 +6,11 @@
|
|||||||
|
|
||||||
import { extendProps } from "../state.mjs";
|
import { extendProps } from "../state.mjs";
|
||||||
|
|
||||||
function Heading(props, children) {
|
function Heading(props, ...children) {
|
||||||
const { html } = globalThis.__enhancerApi;
|
const { html } = globalThis.__enhancerApi;
|
||||||
extendProps(props, {
|
extendProps(props, {
|
||||||
class: `notion-enhancer--menu-heading font-semibold
|
class: `notion-enhancer--menu-heading flex items-center gap-[4px]
|
||||||
mb-[16px] mt-[48px] first:mt-0 pb-[12px] text-[16px]
|
text-[16px] font-semibold mb-[16px] mt-[48px] first:mt-0 pb-[12px]
|
||||||
border-b-(& [color:var(--theme--fg-border)])`,
|
border-b-(& [color:var(--theme--fg-border)])`,
|
||||||
});
|
});
|
||||||
return html`<h4 ...${props}>${children}</h4>`;
|
return html`<h4 ...${props}>${children}</h4>`;
|
||||||
|
@ -62,8 +62,9 @@ function Circle(rect) {
|
|||||||
></div>`;
|
></div>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
function Banner({ version }) {
|
function Banner() {
|
||||||
const { html } = globalThis.__enhancerApi;
|
const { html, enhancerVersion } = globalThis.__enhancerApi;
|
||||||
|
// todo: show popup if update available
|
||||||
return html`<section class="notion-enhancer--menu-banner">
|
return html`<section class="notion-enhancer--menu-banner">
|
||||||
<div
|
<div
|
||||||
class="relative flex overflow-hidden h-[192px] rounded-t-[4px]
|
class="relative flex overflow-hidden h-[192px] rounded-t-[4px]
|
||||||
@ -94,7 +95,7 @@ function Banner({ version }) {
|
|||||||
<span
|
<span
|
||||||
class="text-[12px] py-[2px] px-[6px]
|
class="text-[12px] py-[2px] px-[6px]
|
||||||
font-medium leading-tight tracking-wide"
|
font-medium leading-tight tracking-wide"
|
||||||
>v${version}
|
>v${enhancerVersion}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
40
src/core/menu/islands/GetStarted.mjs
Normal file
40
src/core/menu/islands/GetStarted.mjs
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
/**
|
||||||
|
* notion-enhancer
|
||||||
|
* (c) 2023 dragonwocky <thedragonring.bod@gmail.com> (https://dragonwocky.me/)
|
||||||
|
* (https://notion-enhancer.github.io/) under the MIT license
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { Heading } from "../components/Heading.mjs";
|
||||||
|
import { Description } from "../components/Description.mjs";
|
||||||
|
import { Checkbox } from "../components/Checkbox.mjs";
|
||||||
|
import { Option } from "./Options.mjs";
|
||||||
|
|
||||||
|
const privacyPolicy = "https://notion-enhancer.github.io/about/privacy-policy/",
|
||||||
|
tsAndCs = "https://notion-enhancer.github.io/about/terms-and-conditions/";
|
||||||
|
|
||||||
|
function GetStarted() {
|
||||||
|
const { html } = globalThis.__enhancerApi;
|
||||||
|
|
||||||
|
return html`
|
||||||
|
<${Heading}>Get Started <i class="i-arrow-right"></i><//>
|
||||||
|
|
||||||
|
<div class="flex items-center my-[14px] gap-[8px]">
|
||||||
|
<${Checkbox}
|
||||||
|
...${{ _get: () => Promise.resolve(true), _set: () => {} }}
|
||||||
|
onchange=${(event) => (event.target.checked = true)}
|
||||||
|
/>
|
||||||
|
<p class="typography text-[14px]">
|
||||||
|
I have read and agreed to the
|
||||||
|
<a class="mx-[4px]" href=${privacyPolicy}>Privacy Policy</a>
|
||||||
|
and <a href=${tsAndCs}>Terms & Conditions</a>.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
export { GetStarted };
|
||||||
|
|
||||||
|
// - deidentified / anonymous
|
||||||
|
// - once a week
|
||||||
|
// - privacy policy
|
||||||
|
// - learn how the notion-enhancer is used and what parts need focusing on
|
@ -47,7 +47,9 @@ function Option({ _get, _set, ...opt }) {
|
|||||||
...${{ _get, _set }}
|
...${{ _get, _set }}
|
||||||
/>`
|
/>`
|
||||||
: ""}
|
: ""}
|
||||||
<${Description} innerHTML=${opt.description} />
|
${["string", "undefined"].includes(typeof opt.description)
|
||||||
|
? html`<${Description} innerHTML=${opt.description} />`
|
||||||
|
: html`<${Description}>${opt.description}<//>`}
|
||||||
</div>
|
</div>
|
||||||
${["number", "hotkey", "color"].includes(opt.type)
|
${["number", "hotkey", "color"].includes(opt.type)
|
||||||
? html`<${Input}
|
? html`<${Input}
|
||||||
@ -83,4 +85,4 @@ function Options({ mod }) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export { Options };
|
export { Options, Option };
|
||||||
|
50
src/core/menu/islands/Telemetry.mjs
Normal file
50
src/core/menu/islands/Telemetry.mjs
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
/**
|
||||||
|
* notion-enhancer
|
||||||
|
* (c) 2023 dragonwocky <thedragonring.bod@gmail.com> (https://dragonwocky.me/)
|
||||||
|
* (https://notion-enhancer.github.io/) under the MIT license
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { useState, setState } from "../state.mjs";
|
||||||
|
import { Option } from "./Options.mjs";
|
||||||
|
|
||||||
|
const privacyPolicy = "https://notion-enhancer.github.io/about/privacy-policy/";
|
||||||
|
function Telemetry() {
|
||||||
|
const { html, platform, getMods } = globalThis.__enhancerApi,
|
||||||
|
{ getProfile, isEnabled, initDatabase } = globalThis.__enhancerApi,
|
||||||
|
timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
|
||||||
|
|
||||||
|
const $enabledMods = html`<code></code>`;
|
||||||
|
useState(["rerender"], async () => {
|
||||||
|
let enabledMods = [];
|
||||||
|
for (const mod of await getMods()) {
|
||||||
|
if (mod._src === "core") continue;
|
||||||
|
if (await isEnabled(mod.id)) enabledMods.push(mod.id);
|
||||||
|
}
|
||||||
|
$enabledMods.innerText = JSON.stringify(enabledMods);
|
||||||
|
});
|
||||||
|
|
||||||
|
const _get = async () => {
|
||||||
|
// defaults to true, must be explicitly set to false to disable
|
||||||
|
return initDatabase([await getProfile()]).get("telemetryEnabled") ?? true;
|
||||||
|
},
|
||||||
|
_set = async (value) => {
|
||||||
|
await initDatabase([await getProfile()]).set("telemetryEnabled", value);
|
||||||
|
setState({ rerender: true, databaseUpdated: true });
|
||||||
|
};
|
||||||
|
|
||||||
|
// todo: actually collect telemetry
|
||||||
|
return html`<${Option}
|
||||||
|
type="toggle"
|
||||||
|
label="Telemetry"
|
||||||
|
description=${html`If telemetry is enabled, basic usage data will be
|
||||||
|
collected at a regular interval from your device in order to better
|
||||||
|
understand how and where the notion-enhancer is used. This data is
|
||||||
|
anonymous and includes only your platform (<code>"${platform}"</code>),
|
||||||
|
timezone (<code>"${timezone}"</code>) and enabled mods (${$enabledMods}).
|
||||||
|
You can opt in or out of telemetry at any time. For more information,
|
||||||
|
please read the <a href=${privacyPolicy}>privacy policy</a>.`}
|
||||||
|
...${{ _get, _set }}
|
||||||
|
/>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
export { Telemetry };
|
@ -94,17 +94,23 @@ body > #skeleton .row-group .shimmer {
|
|||||||
height: 11px;
|
height: 11px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.notion-enhancer--menu-description mark {
|
.typography mark {
|
||||||
color: inherit;
|
|
||||||
padding: 0 4px;
|
padding: 0 4px;
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
background-color: var(--theme--bg-hover);
|
background-color: var(--theme--bg-hover);
|
||||||
|
color: inherit;
|
||||||
}
|
}
|
||||||
.notion-enhancer--menu-description a {
|
.typography code {
|
||||||
|
padding: 0 4px;
|
||||||
|
border-radius: 3px;
|
||||||
|
background-color: var(--theme--code-inline_bg);
|
||||||
|
color: var(--theme--code-inline_fg);
|
||||||
|
}
|
||||||
|
.typography a {
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
transition: 100ms ease-in;
|
transition: 100ms ease-in;
|
||||||
}
|
}
|
||||||
.notion-enhancer--menu-description a:hover {
|
.typography a:hover {
|
||||||
color: var(--theme--accent-secondary);
|
color: var(--theme--accent-secondary);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,6 +8,7 @@ import { setState, useState } from "./state.mjs";
|
|||||||
import { Sidebar } from "./islands/Sidebar.mjs";
|
import { Sidebar } from "./islands/Sidebar.mjs";
|
||||||
import { Footer } from "./islands/Footer.mjs";
|
import { Footer } from "./islands/Footer.mjs";
|
||||||
import { Banner } from "./islands/Banner.mjs";
|
import { Banner } from "./islands/Banner.mjs";
|
||||||
|
import { Telemetry } from "./islands/Telemetry.mjs";
|
||||||
import { View } from "./islands/View.mjs";
|
import { View } from "./islands/View.mjs";
|
||||||
import { List } from "./islands/List.mjs";
|
import { List } from "./islands/List.mjs";
|
||||||
import { Mod } from "./islands/Mod.mjs";
|
import { Mod } from "./islands/Mod.mjs";
|
||||||
@ -77,7 +78,7 @@ const categories = [
|
|||||||
];
|
];
|
||||||
|
|
||||||
const render = async () => {
|
const render = async () => {
|
||||||
const { html, enhancerVersion } = globalThis.__enhancerApi,
|
const { html, platform } = globalThis.__enhancerApi,
|
||||||
{ getMods, isEnabled, setEnabled } = globalThis.__enhancerApi,
|
{ getMods, isEnabled, setEnabled } = globalThis.__enhancerApi,
|
||||||
[icon, renderStarted] = useState(["icon", "renderStarted"]);
|
[icon, renderStarted] = useState(["icon", "renderStarted"]);
|
||||||
if (!html || !getMods || !icon || renderStarted) return;
|
if (!html || !getMods || !icon || renderStarted) return;
|
||||||
@ -116,9 +117,10 @@ const render = async () => {
|
|||||||
<!-- wrappers necessary for transitions and breakpoints -->
|
<!-- wrappers necessary for transitions and breakpoints -->
|
||||||
<div class="grow overflow-auto">
|
<div class="grow overflow-auto">
|
||||||
<div class="relative h-full w-full">
|
<div class="relative h-full w-full">
|
||||||
<${View} id="welcome"><${Banner} version=${enhancerVersion} /><//>
|
<${View} id="welcome"><${Banner} /><//>
|
||||||
<${View} id="core">
|
<${View} id="core">
|
||||||
<${Options} mod=${mods.find(({ _src }) => _src === "core")} />
|
<${Options} mod=${mods.find(({ _src }) => _src === "core")} />
|
||||||
|
<${Telemetry} />
|
||||||
<${Profiles} />
|
<${Profiles} />
|
||||||
<//>
|
<//>
|
||||||
${[...categories, ...mods]
|
${[...categories, ...mods]
|
||||||
|
Loading…
Reference in New Issue
Block a user