mirror of
https://github.com/notion-enhancer/notion-enhancer.git
synced 2025-04-03 12:19:02 +00:00
chore: update onboarding disclaimer, unify telemetry handling, detect firefox vs chromium
This commit is contained in:
parent
374efd3458
commit
809b59ebb1
@ -5,4 +5,4 @@ version=$(node -p "require('./package.json').version")
|
||||
cd src
|
||||
mkdir -p ../dist
|
||||
rm -f "../dist/notion-enhancer-$version.zip"
|
||||
zip -r9 "../dist/notion-enhancer-$version.zip" . -x electron/\*
|
||||
zip -r9 "../dist/notion-enhancer-$version.zip" .
|
@ -6,7 +6,9 @@
|
||||
|
||||
"use strict";
|
||||
|
||||
const platform = "browser",
|
||||
const platform = navigator.userAgent.includes("Firefox")
|
||||
? "firefox"
|
||||
: "chromium",
|
||||
version = chrome.runtime.getManifest().version,
|
||||
enhancerUrl = (target) => chrome.runtime.getURL(target);
|
||||
|
||||
|
@ -25,18 +25,17 @@ const _isManifestValid = (modManifest) => {
|
||||
};
|
||||
|
||||
let _mods;
|
||||
const getMods = async (category) => {
|
||||
const getMods = async (asyncFilter) => {
|
||||
const { readJson } = globalThis.__enhancerApi;
|
||||
// prettier-ignore
|
||||
_mods ??= (await Promise.all((await readJson("registry.json")).map(async (_src) => {
|
||||
const modManifest = { ...(await readJson(`${_src}/mod.json`)), _src };
|
||||
return _isManifestValid(modManifest) ? modManifest : undefined;
|
||||
}))).filter((mod) => mod);
|
||||
return category
|
||||
? _mods.filter(({ _src }) => {
|
||||
return _src === category || _src.startsWith(`${category}/`);
|
||||
})
|
||||
: _mods;
|
||||
// prettier-ignore
|
||||
return (await Promise.all(_mods.map(async (mod) => {
|
||||
return !asyncFilter || (await asyncFilter(mod)) ? mod : undefined;
|
||||
}))).filter((mod) => mod);
|
||||
},
|
||||
getProfile = async () => {
|
||||
const db = globalThis.__enhancerApi.initDatabase();
|
||||
@ -49,10 +48,10 @@ const isEnabled = async (id) => {
|
||||
const { version, initDatabase } = globalThis.__enhancerApi,
|
||||
mod = (await getMods()).find((mod) => mod.id === id);
|
||||
if (mod._src === "core") return true;
|
||||
// prettier-ignore
|
||||
const agreedToTerms = await initDatabase().get("agreedToTerms"),
|
||||
enabledInProfile = await initDatabase([
|
||||
await getProfile(), "enabledMods",
|
||||
await getProfile(),
|
||||
"enabledMods",
|
||||
]).get(id);
|
||||
return agreedToTerms === version && enabledInProfile;
|
||||
},
|
||||
@ -63,10 +62,9 @@ const isEnabled = async (id) => {
|
||||
};
|
||||
|
||||
const modDatabase = async (id) => {
|
||||
// prettier-ignore
|
||||
const optionDefaults = (await getMods())
|
||||
.find((mod) => mod.id === id)?.options
|
||||
.map((opt) => [opt.key, opt.value ?? opt.values?.[0]])
|
||||
.find((mod) => mod.id === id)
|
||||
?.options.map((opt) => [opt.key, opt.value ?? opt.values?.[0]])
|
||||
.filter(([, value]) => typeof value !== "undefined");
|
||||
return globalThis.__enhancerApi.initDatabase(
|
||||
[await getProfile(), id],
|
||||
|
@ -5,21 +5,20 @@
|
||||
*/
|
||||
|
||||
import { checkForUpdate } from "./update.mjs";
|
||||
import { sendTelemetryPing } from "./telemetry.mjs";
|
||||
import { Frame, Modal, Button } from "./components.mjs";
|
||||
|
||||
// prettier-ignore
|
||||
const asyncFilter = async (arr, predicate) => Promise.all(arr.map(predicate))
|
||||
.then((results) => arr.filter((_v, index) => results[index]));
|
||||
|
||||
const doThemeOverride = async (db) => {
|
||||
const { getMods, isEnabled } = globalThis.__enhancerApi,
|
||||
enabledFilter = (theme) => isEnabled(theme.id),
|
||||
overrideThemes = await db.get("loadThemeOverrides"),
|
||||
enabledThemes = await asyncFilter(await getMods("themes"), enabledFilter);
|
||||
return (
|
||||
overrideThemes === "Enabled" ||
|
||||
(overrideThemes === "Auto" && enabledThemes.length)
|
||||
);
|
||||
loadThemeOverrides = await db.get("loadThemeOverrides");
|
||||
if (loadThemeOverrides === "Enabled") return true;
|
||||
if (loadThemeOverrides === "Disabled") return false;
|
||||
// prettier-ignore
|
||||
return (await getMods(async (mod) => {
|
||||
// loadThemeOverrides === "Auto"
|
||||
if (!mod._src.startsWith("themes/")) return false;
|
||||
return await isEnabled(mod.id);
|
||||
})).length;
|
||||
},
|
||||
overrideThemes = async (db) => {
|
||||
const { html, enhancerUrl } = globalThis.__enhancerApi;
|
||||
@ -39,86 +38,78 @@ const doThemeOverride = async (db) => {
|
||||
};
|
||||
|
||||
const insertMenu = async (db) => {
|
||||
const notionSidebar = `.notion-sidebar-container .notion-sidebar > :nth-child(3) > div > :nth-child(2)`,
|
||||
{ html, addKeyListener, addMutationListener } = globalThis.__enhancerApi,
|
||||
{ platform, enhancerUrl, onMessage } = globalThis.__enhancerApi,
|
||||
menuButtonIconStyle = await db.get("menuButtonIconStyle"),
|
||||
openMenuHotkey = await db.get("openMenuHotkey"),
|
||||
renderPing = {
|
||||
namespace: "notion-enhancer",
|
||||
hotkey: openMenuHotkey,
|
||||
icon: menuButtonIconStyle,
|
||||
};
|
||||
const notionSidebar = `.notion-sidebar-container .notion-sidebar > :nth-child(3) > div > :nth-child(2)`,
|
||||
{ html, addKeyListener, addMutationListener } = globalThis.__enhancerApi,
|
||||
{ platform, enhancerUrl, onMessage } = globalThis.__enhancerApi,
|
||||
menuButtonIconStyle = await db.get("menuButtonIconStyle"),
|
||||
openMenuHotkey = await db.get("openMenuHotkey"),
|
||||
renderPing = {
|
||||
namespace: "notion-enhancer",
|
||||
hotkey: openMenuHotkey,
|
||||
icon: menuButtonIconStyle,
|
||||
};
|
||||
|
||||
let _contentWindow;
|
||||
const sendThemePing = () => {
|
||||
const darkMode = document.body.classList.contains("dark"),
|
||||
notionTheme = darkMode ? "dark" : "light";
|
||||
if (renderPing.theme === notionTheme) return;
|
||||
renderPing.theme = notionTheme;
|
||||
_contentWindow?.postMessage?.(renderPing, "*");
|
||||
},
|
||||
sendRenderPing = (contentWindow) => {
|
||||
_contentWindow ??= contentWindow;
|
||||
if (!$modal.hasAttribute("open")) return;
|
||||
delete renderPing.theme;
|
||||
_contentWindow?.focus?.();
|
||||
sendThemePing();
|
||||
};
|
||||
let _contentWindow;
|
||||
const sendThemePing = () => {
|
||||
const darkMode = document.body.classList.contains("dark"),
|
||||
notionTheme = darkMode ? "dark" : "light";
|
||||
if (renderPing.theme === notionTheme) return;
|
||||
renderPing.theme = notionTheme;
|
||||
_contentWindow?.postMessage?.(renderPing, "*");
|
||||
},
|
||||
sendRenderPing = (contentWindow) => {
|
||||
_contentWindow ??= contentWindow;
|
||||
if (!$modal.hasAttribute("open")) return;
|
||||
delete renderPing.theme;
|
||||
_contentWindow?.focus?.();
|
||||
sendThemePing();
|
||||
};
|
||||
|
||||
const $modal = html`<${Modal} onopen=${sendRenderPing}>
|
||||
<${Frame}
|
||||
title="notion-enhancer menu"
|
||||
src="${enhancerUrl("core/menu/index.html")}"
|
||||
onload=${function () {
|
||||
// pass notion-enhancer api to electron menu process
|
||||
if (platform !== "browser") {
|
||||
const apiKey = "__enhancerApi";
|
||||
this.contentWindow[apiKey] = globalThis[apiKey];
|
||||
}
|
||||
sendRenderPing(this.contentWindow);
|
||||
}}
|
||||
/>
|
||||
<//>`,
|
||||
$button = html`<${Button}
|
||||
onclick=${$modal.open}
|
||||
notifications=${(await checkForUpdate()) ? 1 : 0}
|
||||
themeOverridesLoaded=${await doThemeOverride(db)}
|
||||
icon="notion-enhancer${menuButtonIconStyle === "Monochrome"
|
||||
? "?mask"
|
||||
: " text-[16px]"}"
|
||||
>notion-enhancer
|
||||
<//>`;
|
||||
document.body.append($modal);
|
||||
addMutationListener(notionSidebar, () => {
|
||||
if (document.contains($button)) return;
|
||||
document.querySelector(notionSidebar)?.append($button);
|
||||
});
|
||||
const $modal = html`<${Modal} onopen=${sendRenderPing}>
|
||||
<${Frame}
|
||||
title="notion-enhancer menu"
|
||||
src="${enhancerUrl("core/menu/index.html")}"
|
||||
onload=${function () {
|
||||
// pass notion-enhancer api to electron menu process
|
||||
if (["darwin", "win32", "linux"].includes(platform)) {
|
||||
const apiKey = "__enhancerApi";
|
||||
this.contentWindow[apiKey] = globalThis[apiKey];
|
||||
}
|
||||
sendRenderPing(this.contentWindow);
|
||||
}}
|
||||
/>
|
||||
<//>`,
|
||||
$button = html`<${Button}
|
||||
onclick=${$modal.open}
|
||||
notifications=${(await checkForUpdate()) ? 1 : 0}
|
||||
themeOverridesLoaded=${await doThemeOverride(db)}
|
||||
icon="notion-enhancer${menuButtonIconStyle === "Monochrome"
|
||||
? "?mask"
|
||||
: " text-[16px]"}"
|
||||
>notion-enhancer
|
||||
<//>`;
|
||||
document.body.append($modal);
|
||||
addMutationListener(notionSidebar, () => {
|
||||
if (document.contains($button)) return;
|
||||
document.querySelector(notionSidebar)?.append($button);
|
||||
addMutationListener("body", sendThemePing);
|
||||
window.addEventListener("focus", sendRenderPing);
|
||||
});
|
||||
document.querySelector(notionSidebar)?.append($button);
|
||||
addMutationListener("body", sendThemePing);
|
||||
window.addEventListener("focus", sendRenderPing);
|
||||
|
||||
addKeyListener(openMenuHotkey, (event) => {
|
||||
event.preventDefault();
|
||||
$modal.open();
|
||||
});
|
||||
window.addEventListener("message", (event) => {
|
||||
if (event.data?.namespace !== "notion-enhancer") return;
|
||||
if (event.data?.action === "close-menu") $modal.close();
|
||||
if (event.data?.action === "open-menu") $modal.open();
|
||||
});
|
||||
onMessage("notion-enhancer", (message) => {
|
||||
if (message === "open-menu") $modal.open();
|
||||
});
|
||||
},
|
||||
sendTelemetryPing = async () => {
|
||||
const { version } = globalThis.__enhancerApi,
|
||||
db = globalThis.__enhancerApi.initDatabase(),
|
||||
agreedToTerms = await db.get("agreedToTerms"),
|
||||
telemetryEnabled = await db.get("telemetryEnabled");
|
||||
if (!telemetryEnabled || agreedToTerms !== version) return;
|
||||
// telemetry
|
||||
};
|
||||
addKeyListener(openMenuHotkey, (event) => {
|
||||
event.preventDefault();
|
||||
$modal.open();
|
||||
});
|
||||
window.addEventListener("message", (event) => {
|
||||
if (event.data?.namespace !== "notion-enhancer") return;
|
||||
if (event.data?.action === "close-menu") $modal.close();
|
||||
if (event.data?.action === "open-menu") $modal.open();
|
||||
});
|
||||
onMessage("notion-enhancer", (message) => {
|
||||
if (message === "open-menu") $modal.open();
|
||||
});
|
||||
};
|
||||
|
||||
export default async (api, db) => {
|
||||
await Promise.all([
|
||||
|
@ -23,16 +23,23 @@ function Onboarding() {
|
||||
>Continue
|
||||
<//>`,
|
||||
$agreeToTerms = html`<div class="mt-[32px]">
|
||||
<${Heading} class="mb-[8px]">
|
||||
Thanks for installing the notion-enhancer!
|
||||
<//>
|
||||
<${Description}>
|
||||
Thanks for installing the notion-enhancer! It's been absolutely
|
||||
incredible to see how the notion-enhancer has grown from small
|
||||
beginnings to something used today by over 11,000 people around the
|
||||
world, now including you. Before you begin, please read the privacy
|
||||
policy to learn how the notion-enhancer uses your data and the terms &
|
||||
conditions to understand what the notion-enhancer does and does not
|
||||
offer. Ticking the box below and pressing <mark>Continue</mark> will
|
||||
unlock the notion-enhancer's full functionality, accessible through the
|
||||
sidebar.
|
||||
In order for the notion-enhancer to function, it may access, collect,
|
||||
process and/or store data on your device (including workspace content,
|
||||
device metadata, and notion-enhancer configuration) according to its
|
||||
privacy policy. Unless otherwise stated for telemetry purposes, the
|
||||
notion-enhancer will never transmit any of your data from your device.
|
||||
Telemetry can be disabled at any time through the menu.
|
||||
<br />
|
||||
<br />
|
||||
The notion-enhancer is free and open-source software distributed under
|
||||
the <a href="${tsAndCs}#license">MIT License</a> without warranty of any
|
||||
kind. In no event shall the authors be liable for any consequences of
|
||||
the software's use. Before continuing, you must read and agree to the
|
||||
notion-enhancer's privacy policy and terms & conditions.
|
||||
<//>
|
||||
<div class="flex items-center my-[14px] gap-[8px]">
|
||||
<${Checkbox}
|
||||
@ -77,7 +84,7 @@ function Onboarding() {
|
||||
</div>`,
|
||||
$featuredSponsors = html`
|
||||
<div class="mt-[32px]">
|
||||
<${Heading} class="mt-[32px] mb-[8px]">Featured Sponsors<//>
|
||||
<${Heading} class="mb-[8px]">Featured Sponsors<//>
|
||||
<${Description}>
|
||||
A few awesome companies out there have teamed up with me to provide
|
||||
you with the notion-enhancer, free forever. Check them out!
|
||||
|
@ -53,7 +53,7 @@ function Sidebar({ items, categories }) {
|
||||
const { html, version } = globalThis.__enhancerApi,
|
||||
{ initDatabase, isEnabled } = globalThis.__enhancerApi,
|
||||
$agreeToUnlock = html`<span
|
||||
class="pt-[2px] pb-[5px] px-[15px]
|
||||
class="pt-[2px] pb-[5px] px-[15px] text-[12px]
|
||||
inline-block text-[color:var(--theme--fg-red)]"
|
||||
>To unlock the notion-enhancer's full functionality, agree to the privacy
|
||||
policy and terms & conditions on the welcome page.
|
||||
|
@ -4,26 +4,14 @@
|
||||
* (https://notion-enhancer.github.io/) under the MIT license
|
||||
*/
|
||||
|
||||
import { collectTelemetryData } from "../../telemetry.mjs";
|
||||
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, version } = globalThis.__enhancerApi,
|
||||
{ getMods, 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 () => {
|
||||
const { html, initDatabase } = globalThis.__enhancerApi,
|
||||
_get = async () => {
|
||||
// defaults to true, must be explicitly set to false to disable
|
||||
return initDatabase().get("telemetryEnabled") ?? true;
|
||||
},
|
||||
@ -32,6 +20,19 @@ function Telemetry() {
|
||||
setState({ rerender: true });
|
||||
};
|
||||
|
||||
const $ = {
|
||||
platform: html`<code></code>`,
|
||||
version: html`<code></code>`,
|
||||
timezone: html`<code></code>`,
|
||||
enabledMods: html`<code></code>`,
|
||||
};
|
||||
useState(["rerender"], async () => {
|
||||
const telemetryData = await collectTelemetryData();
|
||||
for (const key in telemetryData) {
|
||||
$[key].innerText = JSON.stringify(telemetryData[key]);
|
||||
}
|
||||
});
|
||||
|
||||
// todo: actually collect telemetry
|
||||
return html`<${Option}
|
||||
type="toggle"
|
||||
@ -39,11 +40,10 @@ function Telemetry() {
|
||||
description=${html`If telemetry is enabled, usage data will be collected
|
||||
once a week 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>), notion-enhancer version
|
||||
(<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
|
||||
platform (${$.platform}), notion-enhancer version (${$.version}), timezone
|
||||
(${$.timezone}), 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} class="ml-[3px]">privacy policy</a>.`}
|
||||
...${{ _get, _set }}
|
||||
/>`;
|
||||
|
27
src/core/telemetry.mjs
Normal file
27
src/core/telemetry.mjs
Normal file
@ -0,0 +1,27 @@
|
||||
/**
|
||||
* notion-enhancer
|
||||
* (c) 2023 dragonwocky <thedragonring.bod@gmail.com> (https://dragonwocky.me/)
|
||||
* (https://notion-enhancer.github.io/) under the MIT license
|
||||
*/
|
||||
|
||||
const collectTelemetryData = async () => {
|
||||
const { platform, version } = globalThis.__enhancerApi,
|
||||
{ getMods, isEnabled } = globalThis.__enhancerApi,
|
||||
timezone = Intl.DateTimeFormat().resolvedOptions().timeZone,
|
||||
// prettier-ignore
|
||||
enabledMods = (await getMods(async (mod) => {
|
||||
if (mod._src === "core") return false;
|
||||
return await isEnabled(mod.id);
|
||||
})).map(mod => mod.id);
|
||||
return { platform, version, timezone, enabledMods };
|
||||
},
|
||||
sendTelemetryPing = async () => {
|
||||
const db = globalThis.__enhancerApi.initDatabase(),
|
||||
agreedToTerms = await db.get("agreedToTerms"),
|
||||
telemetryEnabled = await db.get("telemetryEnabled");
|
||||
if (!telemetryEnabled || agreedToTerms !== version) return;
|
||||
// telemetry
|
||||
const telemetryData = await collectTelemetryData();
|
||||
};
|
||||
|
||||
export { collectTelemetryData, sendTelemetryPing };
|
@ -8,8 +8,11 @@ let _release;
|
||||
const repo = "notion-enhancer/notion-enhancer",
|
||||
endpoint = `https://api.github.com/repos/${repo}/releases/latest`,
|
||||
getRelease = async () => {
|
||||
const { readJson } = globalThis.__enhancerApi;
|
||||
_release ??= (await readJson(endpoint))?.tag_name.replace(/^v/, "");
|
||||
const { version, readJson } = globalThis.__enhancerApi;
|
||||
try {
|
||||
_release ??= (await readJson(endpoint))?.tag_name.replace(/^v/, "");
|
||||
} catch {}
|
||||
_release ??= version;
|
||||
return _release;
|
||||
};
|
||||
|
||||
|
@ -45,7 +45,10 @@ if (isElectron()) {
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} else {
|
||||
// clientStyles
|
||||
// clientScripts
|
||||
} else import("./api/browser.js").then(() => import("./load.mjs"));
|
||||
import(chrome.runtime.getURL("/api/browser.js")).then(() => {
|
||||
import(chrome.runtime.getURL("/load.mjs"));
|
||||
});
|
||||
}
|
||||
|
16
src/load.mjs
16
src/load.mjs
@ -9,21 +9,21 @@
|
||||
export default (async () => {
|
||||
// prettier-ignore
|
||||
const { enhancerUrl } = globalThis.__enhancerApi,
|
||||
isMenu = location.href.startsWith(enhancerUrl("/core/menu/index.html")),
|
||||
isMenu = location.href.startsWith(enhancerUrl("core/menu/index.html")),
|
||||
pageLoaded = /(^\/$)|((-|\/)[0-9a-f]{32}((\?.+)|$))/.test(location.pathname),
|
||||
signedIn = localStorage["LRU:KeyValueStore2:current-user-id"];
|
||||
if (!isMenu && (!signedIn || !pageLoaded)) return;
|
||||
if (!isMenu) console.log("notion-enhancer: loading...");
|
||||
|
||||
await Promise.all([
|
||||
import("./assets/icons.svg.js"),
|
||||
import("./vendor/twind.min.js"),
|
||||
import("./vendor/lucide.min.js"),
|
||||
import("./vendor/htm.min.js"),
|
||||
import("./api/events.js"),
|
||||
import("./api/mods.js"),
|
||||
import(enhancerUrl("assets/icons.svg.js")),
|
||||
import(enhancerUrl("vendor/twind.min.js")),
|
||||
import(enhancerUrl("vendor/lucide.min.js")),
|
||||
import(enhancerUrl("vendor/htm.min.js")),
|
||||
import(enhancerUrl("api/events.js")),
|
||||
import(enhancerUrl("api/mods.js")),
|
||||
]);
|
||||
await import("./api/interface.js");
|
||||
await import(enhancerUrl("api/interface.js"));
|
||||
const { getMods, isEnabled, modDatabase } = globalThis.__enhancerApi;
|
||||
|
||||
for (const mod of await getMods()) {
|
||||
|
@ -7,7 +7,6 @@
|
||||
"homepage_url": "https://notion-enhancer.github.io",
|
||||
"content_scripts": [{ "matches": ["*://*.notion.so/*"], "js": ["/init.js"] }],
|
||||
"background": { "service_worker": "/worker.js" },
|
||||
"options_page": "/core/menu/index.html",
|
||||
"action": {},
|
||||
"icons": {
|
||||
"16": "/assets/colour-x16.png",
|
||||
|
Loading…
Reference in New Issue
Block a user