From 1ac78b64e83569fc1821fa8641d8523c5f262e99 Mon Sep 17 00:00:00 2001 From: dragonwocky Date: Sun, 31 Oct 2021 18:36:01 +1100 Subject: [PATCH] added welcome/changelog/license acceptance modal --- repo/LICENSE | 21 +++++ repo/font-chooser/fonts.css | 2 +- repo/font-chooser/fonts.mjs | 2 +- repo/font-chooser/mod.json | 2 +- repo/menu/client.mjs | 4 +- repo/menu/components.mjs | 2 +- repo/menu/launcher.mjs | 90 ---------------------- repo/menu/markdown.css | 12 ++- repo/menu/menu.mjs | 40 ++++++++-- repo/menu/notifications.mjs | 150 ++++++++++++++++++++++++++++++++++++ repo/menu/styles.mjs | 45 +++++++++-- repo/menu/whats-new.md | 77 ++++++++++++++++++ 12 files changed, 339 insertions(+), 108 deletions(-) create mode 100644 repo/LICENSE delete mode 100644 repo/menu/launcher.mjs create mode 100644 repo/menu/notifications.mjs create mode 100644 repo/menu/whats-new.md diff --git a/repo/LICENSE b/repo/LICENSE new file mode 100644 index 0000000..b503961 --- /dev/null +++ b/repo/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2021 dragonwocky (https://dragonwocky.me/) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/repo/font-chooser/fonts.css b/repo/font-chooser/fonts.css index e3141ff..f46c4fb 100644 --- a/repo/font-chooser/fonts.css +++ b/repo/font-chooser/fonts.css @@ -1,6 +1,6 @@ /* * notion-enhancer: font chooser - * (c) 2021 TorchAtlas (https://torchatlas.netlify.app/) + * (c) 2021 TorchAtlas (https://bit.ly/torchatlas/) * (c) 2021 admiraldus (https://github.com/admiraldus) * (c) 2021 dragonwocky (https://dragonwocky.me/) * (https://notion-enhancer.github.io/) under the MIT license diff --git a/repo/font-chooser/fonts.mjs b/repo/font-chooser/fonts.mjs index 47d27da..d6e0668 100644 --- a/repo/font-chooser/fonts.mjs +++ b/repo/font-chooser/fonts.mjs @@ -1,6 +1,6 @@ /* * notion-enhancer: font chooser - * (c) 2021 TorchAtlas (https://torchatlas.netlify.app/) + * (c) 2021 TorchAtlas (https://bit.ly/torchatlas/) * (c) 2021 admiraldus (https://github.com/admiraldus * (c) 2021 dragonwocky (https://dragonwocky.me/) * (https://notion-enhancer.github.io/) under the MIT license diff --git a/repo/font-chooser/mod.json b/repo/font-chooser/mod.json index 8fdef7a..f1fe6fe 100644 --- a/repo/font-chooser/mod.json +++ b/repo/font-chooser/mod.json @@ -7,7 +7,7 @@ "authors": [ { "name": "TorchAtlas", - "homepage": "https://torchatlas.netlify.app/", + "homepage": "https://bit.ly/torchatlas/", "avatar": "https://avatars.githubusercontent.com/u/12666855" } ], diff --git a/repo/menu/client.mjs b/repo/menu/client.mjs index dfcfeab..5002f0d 100644 --- a/repo/menu/client.mjs +++ b/repo/menu/client.mjs @@ -6,6 +6,8 @@ 'use strict'; +const notificationsURL = 'https://notion-enhancer.github.io/notifications.json'; + export default async function ({ env, fs, storage, registry, web }, db) { web.addHotkeyListener(await db.get(['hotkey']), env.focusMenu); @@ -30,7 +32,7 @@ export default async function ({ env, fs, storage, registry, web }, db) { const notifications = { cache: await storage.get(['notifications'], []), - provider: [registry.welcomeNotification, ...(await fs.getJSON(registry.notificationsURL))], + provider: await fs.getJSON(notificationsURL), count: (await registry.errors()).length, }; for (const notification of notifications.provider) { diff --git a/repo/menu/components.mjs b/repo/menu/components.mjs index 7990ee5..9b2dec0 100644 --- a/repo/menu/components.mjs +++ b/repo/menu/components.mjs @@ -7,7 +7,7 @@ 'use strict'; import { fmt, web, registry, components } from '../../api/_.mjs'; -import { notifications } from './launcher.mjs'; +import { notifications } from './notifications.mjs'; const profileDB = await registry.profileDB(); export const modComponents = { diff --git a/repo/menu/launcher.mjs b/repo/menu/launcher.mjs deleted file mode 100644 index 4c1fe2f..0000000 --- a/repo/menu/launcher.mjs +++ /dev/null @@ -1,90 +0,0 @@ -/* - * notion-enhancer core: menu - * (c) 2021 dragonwocky (https://dragonwocky.me/) - * (https://notion-enhancer.github.io/) under the MIT license - */ - -import * as api from '../../api/_.mjs'; -const { env, fs, storage, fmt, registry, web, components } = api; -import { tw } from './styles.mjs'; - -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}`); - } - for (let script of mod.js?.menu || []) { - 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) { - console.log('[notion-enhancer] registry errors:'); - console.table(errors); -} - -export const notifications = { - $container: web.html`
`, - cache: await storage.get(['notifications'], []), - provider: [registry.welcomeNotification, ...(await fs.getJSON(registry.notificationsURL))], - async 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 storage.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`${await components.feather(icon, { class: 'notification-icon' })}` - ) - ); - return $notification; - }, - _onChange: false, - async onChange() { - if (this._onChange) return; - this._onChange = true; - const $notification = await 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) { - 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); -} -if (errors.length) { - notifications.add({ - icon: 'alert-circle', - message: 'Failed to load mods (check console).', - color: 'red', - }); -} diff --git a/repo/menu/markdown.css b/repo/menu/markdown.css index ce74a81..9f7ffb0 100644 --- a/repo/menu/markdown.css +++ b/repo/menu/markdown.css @@ -28,12 +28,22 @@ font-size: 1.25rem; margin: 1rem 0 0.5rem 0; } +.markdown h4 { + font-weight: bold; + margin: 0.5rem 0; +} .markdown ul, .markdown ol { padding-left: 1.25rem; } +.markdown ul { + list-style: disc; +} +.markdown ol { + list-style: decimal; +} .markdown li { - margin: 0.4rem 0; + margin: 1px 0; } .markdown ol li { padding-left: 0.25rem; diff --git a/repo/menu/menu.mjs b/repo/menu/menu.mjs index 9bc72e6..216c550 100644 --- a/repo/menu/menu.mjs +++ b/repo/menu/menu.mjs @@ -6,13 +6,33 @@ 'use strict'; -import './launcher.mjs'; -import './styles.mjs'; +import * as api from '../../api/_.mjs'; +import { notifications, $welcomeModal } from './notifications.mjs'; +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}`); + } + for (let script of mod.js?.menu || []) { + 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) { + console.log('[notion-enhancer] registry errors:'); + console.table(errors); + notifications.add({ + icon: 'alert-circle', + message: 'Failed to load mods (check console).', + color: 'red', + }); +} -import { env, fs, storage, registry, web, components } from '../../api/_.mjs'; -import { notifications } from './launcher.mjs'; 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'), profileName = await registry.profileName(), @@ -323,7 +343,14 @@ $notionNavItem.addEventListener('click', env.focusNotion); const $coreNavItem = web.html`core`, $extensionsNavItem = web.html`extensions`, $themesNavItem = web.html`themes`, - $integrationsNavItem = web.html`integrations`; + $integrationsNavItem = web.html`integrations`, + $changelogNavItem = web.html``; +$changelogNavItem.addEventListener('click', () => { + $welcomeModal.scrollTop = 0; + $welcomeModal.classList.add('modal-visible'); +}); web.render( document.body, @@ -339,7 +366,8 @@ web.render( $themesNavItem, $integrationsNavItem, web.html`docs`, - web.html`community` + web.html`community`, + $changelogNavItem ), $main ), diff --git a/repo/menu/notifications.mjs b/repo/menu/notifications.mjs new file mode 100644 index 0000000..1d5d4eb --- /dev/null +++ b/repo/menu/notifications.mjs @@ -0,0 +1,150 @@ +/* + * notion-enhancer core: menu + * (c) 2021 dragonwocky (https://dragonwocky.me/) + * (https://notion-enhancer.github.io/) under the MIT license + */ + +import { env, fs, storage, fmt, web, components } from '../../api/_.mjs'; +import { tw } from './styles.mjs'; + +const notificationsURL = 'https://notion-enhancer.github.io/notifications.json'; +export const notifications = { + $container: web.html`
`, + 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`` + : web.html``, + resolve = async () => { + if (id !== undefined) { + notifications.cache.push(id); + await storage.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`${await components.feather(icon, { class: 'notification-icon' })}` + ) + ); + return $notification; + }, + _onChange: false, + async onChange() { + if (this._onChange) return; + this._onChange = true; + const $notification = await 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) { + 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 $welcomeModalButton = web.html``; +export const $welcomeModal = web.render( + web.html``, + web.render( + web.html``, + web.html``, + web.render(web.html``, $welcomeModalButton) + ) +); +web.render(document.body, $welcomeModal); + +const lastAcceptedWelcome = await storage.get(['last_accepted_welcome']); +if (lastAcceptedWelcome !== env.version) { + $welcomeModal.classList.add('modal-visible'); +} +$welcomeModalButton.addEventListener('click', async () => { + $welcomeModal.classList.remove('modal-visible'); + await storage.set(['last_accepted_welcome'], env.version); +}); diff --git a/repo/menu/styles.mjs b/repo/menu/styles.mjs index ad4cb64..9b50c85 100644 --- a/repo/menu/styles.mjs +++ b/repo/menu/styles.mjs @@ -38,12 +38,16 @@ const customClasses = { 'sidebar': apply`h-full w-96 max-w-3/7 flex-shrink-0 px-4 pt-3 pb-16 overflow-y-auto flex flex-col bg-notion-secondary border-l border-divider`, 'content-container': apply`h-full flex flex-col`, - 'nav': apply`px-4 py-3 flex flex-wrap items-center border-b border-divider`, + 'nav': apply`pr-4 pl-2 py-3 flex flex-wrap items-center border-b border-divider`, 'nav-notion': apply`flex items-center font-semibold text-xl cursor-pointer select-none mr-4 - ml-4 sm:mb-4 md:w-full lg:(w-auto ml-0 mb-0)`, - 'nav-notion-icon': apply`h-12 w-12 mr-5 sm:(h-6 w-6 mr-3)`, - 'nav-item': apply`ml-4 px-3 py-2 rounded-md text-sm font-medium hover:bg-interactive-hover focus:bg-interactive-active`, - 'nav-item-selected': apply`ml-4 px-3 py-2 rounded-md text-sm font-medium ring-1 ring-divider bg-notion-secondary`, + ml-4 my-4 w-full lg:w-auto`, + 'nav-notion-icon': apply`h-6 w-6 mr-3`, + 'nav-item': apply`ml-4 px-3 py-2 rounded-md text-sm font-medium hover:bg-interactive-hover focus:bg-interactive-active + mb-2 lg:mb-0`, + 'nav-item-selected': apply`ml-4 px-3 py-2 rounded-md text-sm font-medium ring-1 ring-divider bg-notion-secondary + mb-2 lg:mb-0`, + 'nav-changelog': apply`lg:ml-auto focus:outline-none`, + 'nav-changelog-icon': apply`w-4 h-4`, 'main': apply`transition px-4 py-3 overflow-y-auto flex-grow`, 'main-message': apply`mx-2.5 my-2.5 px-px text-sm text-foreground-secondary text-justify`, 'mods-list': apply`flex flex-wrap`, @@ -88,6 +92,34 @@ const customClasses = { 'search-container': apply`block mx-2.5 my-2.5 relative`, 'search': apply`input pr-12`, 'danger': apply`bg-red-paragraph text-red-paragraph-text`, + 'link': apply`no-underline border-b border-foreground-secondary opacity-70 hover:opacity-90`, + 'modal': apply`fixed z-10 inset-0 overflow-y-auto min-h-screen text-center + ease-out duration-300 transition-opacity opacity-0 pointer-events-none`, + 'modal-visible': { + '@apply': apply`ease-in duration-200 opacity-100 pointer-events-auto`, + '& .modal-box': apply`ease-out duration-300 opacity-100 scale-100`, + }, + 'modal-overlay': apply`fixed inset-0 bg-black bg-opacity-50 transition-opacity`, + 'modal-box': apply`inline-block rounded-lg text-left overflow-hidden shadow-xl + transform transition-all m-8 align-middle + ease-in duration-200 opacity-0 scale-95`, + 'modal-body': apply`bg-notion-secondary p-6 pt-4 max-w-xl w-full`, + 'modal-actions': apply`bg-notion py-3 px-6 flex flex-row-reverse`, + 'modal-title': apply`flex`, + 'modal-title-icon': apply`w-20 mr-6`, + 'modal-title-heading': apply`text-xl leading-6 font-medium`, + 'modal-title-description': apply`mt-2 text-sm text-foreground-secondary`, + 'modal-content': { + '@apply': apply`mt-4 text-sm`, + '& .markdown h4': apply`px-2 py-1 inline-block rounded-md bg-tag text-tag-text`, + }, + 'modal-content-heading': apply`mt-2 text-lg font-bold`, + 'modal-content-list': { + '@apply': apply`list-disc pl-5`, + '& li': apply`my-px`, + }, + 'modal-button': apply`w-full inline-flex justify-center rounded-md text-base font-medium shadow-sm px-4 py-2 + not-focus:hover:bg-interactive-hover focus:bg-interactive-active focus:outline-none`, }; setup({ @@ -101,9 +133,10 @@ setup({ mono: ['var(--theme--font_code)'], }, colors: { + 'black': 'rgba(0,0,0,var(--tw-bg-opacity));', 'notion': 'var(--theme--bg)', 'notion-secondary': 'var(--theme--bg_secondary)', - 'notion-popup': 'var(--theme--bg_card)', + 'notion-card': 'var(--theme--bg_card)', 'divider': 'var(--theme--ui_divider)', 'input': 'var(--theme--ui_input)', 'icon': 'var(--theme--icon)', diff --git a/repo/menu/whats-new.md b/repo/menu/whats-new.md new file mode 100644 index 0000000..65467d3 --- /dev/null +++ b/repo/menu/whats-new.md @@ -0,0 +1,77 @@ +a complete rework of the enhancer, with new features and a port to the browser as a chrome extension. + +#### new + +- cross-environment and properly documented api to replace helpers. +- cross-environment mod loader structure. +- "integrations", a category of mods that can access/use an unofficial notion api. +- notifications sourced from an online endpoint for sending global user alerts. +- simplify user installations by depending on the chrome web store and [notion-repackaged](https://github.com/notion-enhancer/notion-repackaged). +- separate menu profiles for mod configurations. +- a hotkey option type that allows typing in/pressing a hotkey to enter it, instead of typing. +- a rainbow indentation lines style. +- border & background style options for the code line numbers extension. + +#### improved + +- split the core mod into separate mods for specific features. +- theming variables that are applied more specifically, less laggy, and less complicated. +- merged bracketed-links into tweaks. +- a redesigned menu with nicer ui, separate categories for mods and a sidebar for configuration. +- simplified and smoothened the side panel + moved it to the core so any mod can hook into it. +- font chooser option for heading fonts. +- renamed "property-layout" to "collapsible properties", added per-page memory of collapse state. +- chevron icon instead of arrow for scroll to top. +- moved word counter to display in the side panel instead of within the page, + implemented a more accurate word counter method. +- the topbar icons extension defaults to the notion default topbar icons for comment/updates/favorite/more, + but can revert them to text (it still adds a custom icon for the share button). +- relative indenting in outliner. +- rtl support for toggles, indentation lines, table of contents and databases + force inline math to ltr. +- replaced the "truncated table titles" extension with a "truncated titles" extension + with an option to truncate timeline item titles. +- renamed "notion icons" to "icon sets" with new support for uploading/reusing custom icons + directly within the icon picker. + +#### removed + +- integrated scrollbar tweak (notion now includes by default). +- js insert. css insert moved to tweaks mod. +- majority of layout and font size variables - better to leave former to notion and use `ctrl +`/`ctrl -` for latter. +- the "panel sites" extension, due to it's limited/buggy functionality and incompatibility with reimplementation. + +#### fixed + +- bypass csp restrictions. +- many. like many many. all the bugfixes. (mostly a side effect of completely rewriting everything, + but reported extension-specific bugs were all intentionally fixed.) + +#### themes + +- "nord" = an arctic, north-bluish color palette. +- "gruvbox light" = a sepia, 'retro groove' palette based on the vim theme of the same name. +- "gruvbox dark" = a gray, 'retro groove' palette based on the vim theme of the same name. +- "light+" = a simple white theme that brightens coloured text and blocks, + with configurable accents (formerly littlepig light). +- "playful purple" = a purple-shaded theme with bright highlights (formerly littlepig dark and gameish). +- "pinky boom" = pinkify your life. + +#### extensions + +- "calendar scroll" = add a button to jump down to the current week in fullpage/infinite-scroll calendars. +- "global block links" = easily copy the global link of a page or block. +- "collapsible headers" = adds toggles to collapse header sections of pages. +- "simpler databases" = adds a menu to inline databases to toggle ui elements. + +#### tweaks + +- wrap tables to page width. - hide "Type '/' for commands". +- quote block quotation marks. +- responsive columns breakpoint (%). +- accented links. +- full width pages. +- image alignment (center/left/right). + +#### integrations + +- "quick note" = adds a hotkey & a button in the bottom right corner to jump to a new page in a notes database (target database id must be set).