/* * notion-enhancer core: menu * (c) 2021 dragonwocky (https://dragonwocky.me/) * (https://notion-enhancer.github.io/) under the MIT license */ 'use strict'; // initialisation and external interactions import * as api from '../../api/_.mjs'; const { env, fmt, fs, registry, web } = api, db = await registry.db('a6621988-551d-495a-97d8-3c568bca2e9e'); import { tw } from './styles.mjs'; web.addHotkeyListener(await db.get(['hotkey']), env.focusNotion); 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}`); } } const loadTheme = async () => { document.documentElement.className = (await db.get(['theme'], 'light')) === 'dark' ? 'dark' : ''; }; document.addEventListener('visibilitychange', loadTheme); loadTheme(); const notifications = { $container: web.html`
`, cache: await db.get(['notifications'], []), provider: [ env.welcomeNotification, ...(await fs.getJSON('https://notion-enhancer.github.io/notifications.json')), ], add({ icon, message, id = undefined, color = undefined, link = undefined }) { const $notification = link ? web.html`` : web.html``, resolve = async () => { if (id !== undefined) { notifications.cache.push(id); await db.set(['notifications'], notifications.cache); } $notification.remove(); }; $notification.addEventListener('click', resolve); $notification.addEventListener('keyup', (event) => { if (['Enter', ' '].includes(event.key)) resolve(); }); web.render( notifications.$container, web.render( $notification, web.html` ${fmt.md.renderInline(message)} `, web.html`${web.icon(icon, { class: 'notification-icon' })}` ) ); return $notification; }, _changes: false, changes() { if (this._changes) return; this._changes = true; const $notification = this.add({ icon: 'refresh-cw', message: 'Reload to apply changes.', }); $notification.addEventListener('click', env.reload); }, }; web.render(document.body, notifications.$container); for (const notification of notifications.provider) { if ( !notifications.cache.includes(notification.id) && notification.version === env.version && (!notification.environments || notification.environments.includes(env.name)) ) { notifications.add(notification); } } const errors = await registry.errors(); if (errors.length) { console.log('[notion-enhancer] registry errors:'); console.table(errors); notifications.add({ icon: 'alert-circle', message: 'Failed to load mods (check console).', color: 'red', }); } // mod config const components = { preview: (url) => web.html``, title: (title) => web.html`

${web.escape(title)}

`, version: (version) => web.html`v${web.escape(version)}`, tags: (tags) => { if (!tags.length) return ''; return web.render( web.html`

`, tags.map((tag) => `#${web.escape(tag)}`).join(' ') ); }, description: (description) => web.html`

${fmt.md.renderInline(description)}

`, authors: (authors) => { const author = (author) => web.html` ${web.escape(author.name)}'s avatar ${web.escape(author.name)} `; return web.render(web.html`

`, ...authors.map(author)); }, toggle: (checked) => { const $label = web.html``, $input = web.html``; $label.addEventListener('keyup', (event) => { if (['Enter', ' '].includes(event.key)) $input.checked = !$input.checked; }); return web.render( $label, $input, web.html`` ); }, }; components.mod = async (mod) => { const $toggle = components.toggle(await registry.enabled(mod.id)); $toggle.addEventListener('change', (event) => { registry.profile.set(['_mods', mod.id], event.target.checked); notifications.changes(); }); return web.render( web.html`
`, web.render( web.html`
`, mod.preview ? components.preview( mod.preview.startsWith('http') ? mod.preview : fs.localPath(`repo/${mod._dir}/${mod.preview}`) ) : '', web.render( web.html`
`, web.render(components.title(mod.name), components.version(mod.version)), components.tags(mod.tags), components.description(mod.description), components.authors(mod.authors), mod.environments.includes(env.name) && !registry.core.includes(mod.id) ? $toggle : '' ) ) ); }; components.modList = async (category) => { const $search = web.html``, $list = web.html`
`, mods = await registry.list( (mod) => mod.environments.includes(env.name) && mod.tags.includes(category) ); web.addHotkeyListener(['/'], () => $search.focus()); $search.addEventListener('input', (event) => { const query = $search.value.toLowerCase(); for (const $mod of $list.children) { const matches = !query || $mod.innerText.toLowerCase().includes(query); $mod.classList[matches ? 'remove' : 'add']('hidden'); } }); for (const mod of mods) { mod.tags = mod.tags.filter((tag) => tag !== category); web.render($list, await components.mod(mod)); mod.tags.unshift(category); } return web.render( web.html`
`, web.render(web.html`
`, $search), $list ); }; const $main = web.html`
`, $sidebar = web.html``; const $notionNavItem = web.html`

${(await fs.getText('icon/colour.svg')).replace( /width="\d+" height="\d+"/, `class="nav-notion-icon"` )} notion-enhancer

`; $notionNavItem.children[0].addEventListener('click', env.focusNotion); const $coreNavItem = web.html`core`, $extensionsNavItem = web.html`extensions`, $themesNavItem = web.html`themes`, $supportNavItem = web.html`support`; web.render( document.body, web.render( web.html`
`, web.render( web.html`
`, web.render( web.html``, $notionNavItem, $coreNavItem, $extensionsNavItem, $themesNavItem, $supportNavItem ), $main ), $sidebar ) ); function selectNavItem($item) { for (const $selected of document.querySelectorAll('.nav-item-selected')) { $selected.className = 'nav-item'; } $item.className = 'nav-item-selected'; } import * as router from './router.mjs'; router.addView('core', async () => { web.empty($main); selectNavItem($coreNavItem); return web.render($main, await components.modList('core')); }); router.addView('extensions', async () => { web.empty($main); selectNavItem($extensionsNavItem); return web.render($main, await components.modList('extension')); }); router.addView('themes', async () => { web.empty($main); selectNavItem($themesNavItem); return web.render($main, await components.modList('theme')); }); router.loadView('extensions', $main);