scope all await statements

This commit is contained in:
dragonwocky 2021-11-07 18:53:18 +11:00
parent 496305597a
commit a72441ee86
4 changed files with 415 additions and 383 deletions

View File

@ -8,7 +8,6 @@
import { fmt, web, registry, components } from '../../api/_.mjs';
import { notifications } from './notifications.mjs';
const profileDB = await registry.profileDB();
export const modComponents = {
preview: (url) => web.html`<img
@ -56,7 +55,8 @@ export const modComponents = {
export const options = {
toggle: async (mod, opt) => {
const checked = await profileDB.get([mod.id, opt.key], opt.value),
const profileDB = await registry.profileDB(),
checked = await profileDB.get([mod.id, opt.key], opt.value),
$toggle = modComponents.toggle(opt.label, checked),
$tooltip = web.html`${await components.feather('info', { class: 'input-tooltip' })}`,
$label = $toggle.children[0],
@ -71,8 +71,10 @@ export const options = {
});
return $toggle;
},
select: async (mod, opt) => {
const value = await profileDB.get([mod.id, opt.key], opt.values[0]),
const profileDB = await registry.profileDB(),
value = await profileDB.get([mod.id, opt.key], opt.values[0]),
$tooltip = web.html`${await components.feather('info', { class: 'input-tooltip' })}`,
$label = web.render(
web.html`<label class="input-label"></label>`,
@ -96,8 +98,10 @@ export const options = {
});
return web.render($label, $select, $icon);
},
text: async (mod, opt) => {
const value = await profileDB.get([mod.id, opt.key], opt.value),
const profileDB = await registry.profileDB(),
value = await profileDB.get([mod.id, opt.key], opt.value),
$tooltip = web.html`${await components.feather('info', { class: 'input-tooltip' })}`,
$label = web.render(
web.html`<label class="input-label"></label>`,
@ -112,8 +116,10 @@ export const options = {
});
return web.render($label, $input, $icon);
},
number: async (mod, opt) => {
const value = await profileDB.get([mod.id, opt.key], opt.value),
const profileDB = await registry.profileDB(),
value = await profileDB.get([mod.id, opt.key], opt.value),
$tooltip = web.html`${await components.feather('info', { class: 'input-tooltip' })}`,
$label = web.render(
web.html`<label class="input-label"></label>`,
@ -128,8 +134,10 @@ export const options = {
});
return web.render($label, $input, $icon);
},
color: async (mod, opt) => {
const value = await profileDB.get([mod.id, opt.key], opt.value),
const profileDB = await registry.profileDB(),
value = await profileDB.get([mod.id, opt.key], opt.value),
$tooltip = web.html`${await components.feather('info', { class: 'input-tooltip' })}`,
$label = web.render(
web.html`<label class="input-label"></label>`,
@ -166,8 +174,10 @@ export const options = {
paint();
return web.render($label, $input, $icon);
},
file: async (mod, opt) => {
const { filename } = (await profileDB.get([mod.id, opt.key], {})) || {},
const profileDB = await registry.profileDB(),
{ filename } = (await profileDB.get([mod.id, opt.key], {})) || {},
$tooltip = web.html`${await components.feather('info', { class: 'input-tooltip' })}`,
$label = web.render(
web.html`<label class="input-label"></label>`,
@ -204,8 +214,10 @@ export const options = {
$latest
);
},
hotkey: async (mod, opt) => {
const value = await profileDB.get([mod.id, opt.key], opt.value),
const profileDB = await registry.profileDB(),
value = await profileDB.get([mod.id, opt.key], opt.value),
$tooltip = web.html`${await components.feather('info', { class: 'input-tooltip' })}`,
$label = web.render(
web.html`<label class="input-label"></label>`,

View File

@ -8,9 +8,14 @@
import * as api from '../../api/_.mjs';
import { notifications, $changelogModal } from './notifications.mjs';
const { env, fs, storage, registry, web, components } = api;
import { modComponents, options } from './components.mjs';
import * as router from './router.mjs';
import './styles.mjs';
for (const mod of await registry.list((mod) => registry.enabled(mod.id))) {
(async () => {
const { env, fs, storage, registry, web, components } = api;
for (const mod of await registry.list((mod) => registry.enabled(mod.id))) {
for (const sheet of mod.css?.menu || []) {
web.loadStylesheet(`repo/${mod._dir}/${sheet}`);
}
@ -18,9 +23,9 @@ for (const mod of await registry.list((mod) => registry.enabled(mod.id))) {
script = await import(fs.localPath(`repo/${mod._dir}/${script}`));
script.default(api, await registry.db(mod.id));
}
}
const errors = await registry.errors();
if (errors.length) {
}
const errors = await registry.errors();
if (errors.length) {
console.log('[notion-enhancer] registry errors:');
console.table(errors);
notifications.add({
@ -28,31 +33,27 @@ if (errors.length) {
message: 'Failed to load mods (check console).',
color: 'red',
});
}
}
import { modComponents, options } from './components.mjs';
import * as router from './router.mjs';
import './styles.mjs';
const db = await registry.db('a6621988-551d-495a-97d8-3c568bca2e9e'),
const db = await registry.db('a6621988-551d-495a-97d8-3c568bca2e9e'),
profileName = await registry.profileName(),
profileDB = await registry.profileDB();
web.addHotkeyListener(await db.get(['hotkey']), env.focusNotion);
web.addHotkeyListener(await db.get(['hotkey']), env.focusNotion);
const loadTheme = async () => {
const loadTheme = async () => {
document.documentElement.className =
(await storage.get(['theme'], 'light')) === 'dark' ? 'dark' : '';
};
document.addEventListener('visibilitychange', loadTheme);
loadTheme();
};
document.addEventListener('visibilitychange', loadTheme);
loadTheme();
window.addEventListener('beforeunload', (event) => {
window.addEventListener('beforeunload', (event) => {
// trigger input save
document.activeElement.blur();
});
});
const $main = web.html`<main class="main"></main>`,
const $main = web.html`<main class="main"></main>`,
$sidebar = web.html`<article class="sidebar"></article>`,
$options = web.html`<div class="options-container">
<p class="options-placeholder">Select a mod to view and configure its options.</p>
@ -61,10 +62,10 @@ const $main = web.html`<main class="main"></main>`,
Profile: ${web.escape(profileName)}
</button>`;
// profile
// profile
let _$profileConfig;
const openProfileMenu = async () => {
let _$profileConfig;
const openProfileMenu = async () => {
if (!_$profileConfig) {
const profileNames = [
...new Set([
@ -203,17 +204,23 @@ const openProfileMenu = async () => {
$edit,
web.html`${await components.feather('type', { class: 'input-icon' })}`
),
web.render(web.html`<p class="profile-actions"></p>`, $export, $import, $save, $delete),
web.render(
web.html`<p class="profile-actions"></p>`,
$export,
$import,
$save,
$delete
),
$error
);
}
web.render(web.empty($options), _$profileConfig);
};
$profile.addEventListener('click', () => openSidebarMenu('profile'));
};
$profile.addEventListener('click', () => openSidebarMenu('profile'));
// mods
// mods
const $modLists = {},
const $modLists = {},
generators = {
options: async (mod) => {
const $fragment = document.createDocumentFragment();
@ -311,7 +318,7 @@ const $modLists = {},
},
};
async function openModMenu(id) {
async function openModMenu(id) {
let $mod;
for (const $list of Object.values($modLists)) {
$mod = $list.querySelector(`[data-id="${web.escape(id)}"]`);
@ -327,32 +334,32 @@ async function openModMenu(id) {
await generators.options(mod),
];
web.render(web.empty($options), ...fragment);
}
}
// views
// views
const $notionNavItem = web.html`<h1 class="nav-notion">
const $notionNavItem = web.html`<h1 class="nav-notion">
${(await fs.getText('media/colour.svg')).replace(
/width="\d+" height="\d+"/,
`class="nav-notion-icon"`
)}
<span>notion-enhancer</span>
</h1>`;
$notionNavItem.addEventListener('click', env.focusNotion);
$notionNavItem.addEventListener('click', env.focusNotion);
const $coreNavItem = web.html`<a href="?view=core" class="nav-item">core</a>`,
const $coreNavItem = web.html`<a href="?view=core" class="nav-item">core</a>`,
$extensionsNavItem = web.html`<a href="?view=extensions" class="nav-item">extensions</a>`,
$themesNavItem = web.html`<a href="?view=themes" class="nav-item">themes</a>`,
$integrationsNavItem = web.html`<a href="?view=integrations" class="nav-item">integrations</a>`,
$changelogNavItem = web.html`<button class="nav-item nav-changelog">
${await components.feather('clock', { class: 'nav-changelog-icon' })}
</button>`;
$changelogNavItem.addEventListener('click', () => {
$changelogNavItem.addEventListener('click', () => {
$changelogModal.scrollTop = 0;
$changelogModal.classList.add('modal-visible');
});
});
web.render(
web.render(
document.body,
web.render(
web.html`<div class="body-container"></div>`,
@ -373,69 +380,69 @@ web.render(
),
web.render($sidebar, $profile, $options)
)
);
);
function selectNavItem($item) {
function selectNavItem($item) {
for (const $selected of document.querySelectorAll('.nav-item-selected')) {
$selected.className = 'nav-item';
}
$item.className = 'nav-item-selected';
}
}
await generators.modList(
await generators.modList(
'core',
`Core mods provide the basics required for
all other extensions and themes to work. They
can't be disabled, but they can be configured
- just click on a mod to access its options.`
);
router.addView('core', async () => {
);
router.addView('core', async () => {
web.empty($main);
selectNavItem($coreNavItem);
return web.render($main, await generators.modList('core'));
});
});
await generators.modList(
await generators.modList(
'extension',
`Extensions build on the functionality and layout of
the Notion client, modifying and interacting with
existing interfaces.`
);
router.addView('extensions', async () => {
);
router.addView('extensions', async () => {
web.empty($main);
selectNavItem($extensionsNavItem);
return web.render($main, await generators.modList('extension'));
});
});
await generators.modList(
await generators.modList(
'theme',
`Themes change Notion's colour scheme.
Dark themes will only work when Notion is in dark mode,
and light themes will only work when Notion is in light mode.
Only one theme of each mode can be enabled at a time.`
);
router.addView('themes', async () => {
);
router.addView('themes', async () => {
web.empty($main);
selectNavItem($themesNavItem);
return web.render($main, await generators.modList('theme'));
});
});
await generators.modList(
await generators.modList(
'integration',
web.html`<span class="danger">Integrations are extensions that use an unofficial API
to access and modify content. They are used just like
normal extensions, but may be more dangerous to use.</span>`
);
router.addView('integrations', async () => {
);
router.addView('integrations', async () => {
web.empty($main);
selectNavItem($integrationsNavItem);
return web.render($main, await generators.modList('integration'));
});
});
router.setDefaultView('extensions');
router.setDefaultView('extensions');
router.addQueryListener('id', openSidebarMenu);
async function openSidebarMenu(id) {
router.addQueryListener('id', openSidebarMenu);
async function openSidebarMenu(id) {
if (!id) return;
id = web.escape(id);
@ -450,4 +457,5 @@ async function openSidebarMenu(id) {
if (id === 'profile') {
openProfileMenu();
} else openModMenu(id);
}
}
})();

View File

@ -10,8 +10,6 @@ import { tw } from './styles.mjs';
const notificationsURL = 'https://notion-enhancer.github.io/notifications.json';
export const notifications = {
$container: web.html`<div class="notifications-container"></div>`,
cache: await storage.get(['notifications'], []),
provider: await fs.getJSON(notificationsURL),
async add({ icon, message, id = undefined, color = undefined, link = undefined }) {
const $notification = link
? web.html`<a
@ -59,22 +57,37 @@ export const notifications = {
$notification.addEventListener('click', env.reload);
},
};
web.render(document.body, notifications.$container);
for (const notification of notifications.provider) {
(async () => {
notifications.cache = await storage.get(['notifications'], []);
notifications.provider = await fs.getJSON(notificationsURL);
web.render(document.body, notifications.$container);
for (const notification of notifications.provider) {
const cached = notifications.cache.includes(notification.id),
versionMatches = notification.version === env.version,
envMatches = !notification.environments || notification.environments.includes(env.name);
if (!cached && versionMatches && envMatches) notifications.add(notification);
}
}
})();
const lastReadChangelog = await storage.get(['last_read_changelog']),
$changelogModalButton = web.html`<button type="button" class="modal-button">
Accept & Continue
</button>`;
export const $changelogModal = web.render(
web.html`<div class="modal" role="dialog" aria-modal="true">
<div class="modal-overlay" aria-hidden="true"></div>
</div>`,
</div>`
);
(async () => {
const $changelogModalButton = web.html`<button type="button" class="modal-button">
Accept & Continue
</button>`;
$changelogModalButton.addEventListener('click', async () => {
$changelogModal.classList.remove('modal-visible');
await storage.set(['last_read_changelog'], env.version);
});
web.render(
$changelogModal,
web.render(
web.html`<div class="modal-box"></div>`,
web.html`<div class="modal-body">
@ -151,12 +164,11 @@ export const $changelogModal = web.render(
</div>`,
web.render(web.html`<div class="modal-actions"></div>`, $changelogModalButton)
)
);
web.render(document.body, $changelogModal);
if (lastReadChangelog !== env.version) {
);
const lastReadChangelog = await storage.get(['last_read_changelog']);
web.render(document.body, $changelogModal);
if (lastReadChangelog !== env.version) {
$changelogModal.classList.add('modal-visible');
}
$changelogModalButton.addEventListener('click', async () => {
$changelogModal.classList.remove('modal-visible');
await storage.set(['last_read_changelog'], env.version);
});
}
})();

View File

@ -165,7 +165,7 @@ body,
.notion-body.dark
.notion-default-overlay-container
[style*='grid-template-columns: [boolean-start] 60px [boolean-end property-start] 120px [property-end opererator-start] 110px [operator-end value-start] auto [value-end menu-start] 32px [menu-end];'],
.notion-focusable[style*='background: rgb(80, 85, 88);'],
.notion-focusable[style*='background: rgb(80, 85, 88);']:not(.notion-help-button):not(.onboarding-checklist-button),
.notion-body:not(.dark)
.notion-default-overlay-container
[style*='grid-template-columns: [boolean-start] 60px [boolean-end property-start] 120px [property-end opererator-start] 110px [operator-end value-start] auto [value-end menu-start] 32px [menu-end];']