add alerts (inc. update checker) to menu

This commit is contained in:
dragonwocky 2020-08-02 16:26:28 +10:00
parent 060b1ffbe9
commit 933ee3d3b1
Signed by: dragonwocky
GPG Key ID: C7A48B7846AA706D
8 changed files with 286 additions and 67 deletions

View File

@ -60,6 +60,7 @@ module.exports = (defaults) =>
allWindows().some((win) => win.isVisible() && win.id != window.id) allWindows().some((win) => win.isVisible() && win.id != window.id)
) { ) {
window.show(); window.show();
window.focus();
if (settings.maximized) window.maximize(); if (settings.maximized) window.maximize();
if ( if (
(focused_window && focused_window.isFullScreen()) || (focused_window && focused_window.isFullScreen()) ||

View File

@ -7,6 +7,15 @@
@import './buttons.css'; @import './buttons.css';
@import './scrollbars.css'; @import './scrollbars.css';
@keyframes spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
* { * {
box-sizing: border-box; box-sizing: border-box;
word-break: break-word; word-break: break-word;
@ -21,12 +30,31 @@ body {
padding: 0; padding: 0;
} }
body:not([style]) > * {
display: none !important;
}
body:not([style])::after {
content: '';
position: absolute;
left: 44vw;
top: calc(50% - 7.5vw);
width: 10vw;
height: 10vw;
border: 4px solid rgb(34, 34, 34);
border-top-color: transparent;
border-radius: 50%;
animation: spin 0.8s linear infinite;
}
.notion-dark-theme * { .notion-dark-theme * {
outline-color: var(--theme_dark--card-border); outline-color: var(--theme_dark--card-border);
} }
.notion-light-theme * { .notion-light-theme * {
outline-color: var(--theme_light--card-border); outline-color: var(--theme_light--card-border);
} }
*:active {
outline: none;
}
.notion-dark-theme { .notion-dark-theme {
background: var(--theme_dark--main); background: var(--theme_dark--main);
@ -67,3 +95,102 @@ body {
main { main {
padding: 1em; padding: 1em;
} }
#alerts [role='alert'] {
padding: 0.25em;
display: flex;
margin-bottom: 0.75em;
}
#alerts [role='alert']::before {
content: '!';
display: block;
/* margin: auto 0; */
font-weight: bold;
font-size: 1.2em;
padding: 0.5rem;
}
#alerts [role='alert'] p {
font-size: 1rem;
margin: auto 0;
padding: 0.5em;
}
.notion-dark-theme #alerts [role='alert'] p {
color: var(--theme_dark--text_ui);
}
.notion-light-theme #alerts [role='alert'] p {
color: var(--theme_light--text_ui);
}
.notion-light-theme #alerts [role='alert']::before {
color: rgba(0, 0, 0, 0.2);
}
.notion-light-theme #alerts [role='alert'] {
border: 1px solid rgba(0, 0, 0, 0.1);
}
.notion-dark-theme #alerts .error {
border: 1px solid var(--theme_dark--bg_red);
background: var(--theme_dark--line_red);
}
.notion-dark-theme #alerts .error::before {
color: var(--theme_dark--bg_red);
}
.notion-light-theme #alerts .error {
background: var(--theme_light--line_red);
}
.notion-dark-theme #alerts .warning {
border: 1px solid var(--theme_dark--bg_yellow);
background: var(--theme_dark--line_yellow);
}
.notion-dark-theme #alerts .warning::before {
color: var(--theme_dark--bg_yellow);
}
.notion-light-theme #alerts .warning {
background: var(--theme_light--line_yellow);
}
.notion-dark-theme #alerts .info {
border: 1px solid var(--theme_dark--bg_blue);
background: var(--theme_dark--line_blue);
}
.notion-dark-theme #alerts .info::before {
color: var(--theme_dark--bg_blue);
}
.notion-light-theme #alerts .info {
background: var(--theme_light--line_blue);
}
#alerts .success::before {
content: '✓';
}
.notion-dark-theme #alerts .success {
border: 1px solid var(--theme_dark--bg_green);
background: var(--theme_dark--line_green);
}
.notion-dark-theme #alerts .success::before {
color: var(--theme_dark--bg_green);
}
.notion-light-theme #alerts .success {
background: var(--theme_light--line_green);
}
code {
border-radius: 0.1em;
padding: 0.2em 0.4em;
}
.notion-dark-theme code {
font: 0.85em var(--theme_dark--font_code);
/* color: var(--theme_dark--code_inline-text); */
background: var(--theme_dark--code_inline-background);
}
.notion-light-theme code {
font: 0.85em var(--theme_light--font_code);
/* color: var(--theme_light--code_inline-text); */
background: var(--theme_light--code_inline-background);
}
u {
text-decoration: underline;
}

View File

@ -4,16 +4,13 @@
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>notion-enhancer menu</title> <title>notion-enhancer menu</title>
<script
src="https://cdn.jsdelivr.net/gh/alpinejs/alpine@v2.5.0/dist/alpine.min.js"
defer
></script>
<link rel="stylesheet" href="./css/menu.css" /> <link rel="stylesheet" href="./css/menu.css" />
</head> </head>
<body> <body>
<div id="menu-titlebar"></div> <header id="menu-titlebar"></header>
<main> <main>
hi <div id="alerts"></div>
<div id="modules"></div>
</main> </main>
<script> <script>
window['__start'](); window['__start']();

View File

@ -8,7 +8,7 @@
const __mod = require('./mod.js'), const __mod = require('./mod.js'),
store = require('../../pkg/store.js'), store = require('../../pkg/store.js'),
settings = store(__mod.id, __mod.defaults), helpers = require('../../pkg/helpers.js'),
electron = require('electron'); electron = require('electron');
window['__start'] = async () => { window['__start'] = async () => {
@ -20,4 +20,84 @@ window['__start'] = async () => {
for (const style of theme.rules) for (const style of theme.rules)
document.body.style.setProperty(style[0], style[1]); document.body.style.setProperty(style[0], style[1]);
}); });
function createElement(html) {
const template = document.createElement('template');
template.innerHTML = html.trim();
return template.content.firstElementChild;
}
function createAlert(type, message) {
if (!type) throw Error('<notion-enhancer>: no alert type specified');
const el = createElement(`
<section class="${type}" role="alert">
<p>${message}</p>
</section>
`);
return {
el,
resolve() {
el.outerHTML = '';
},
prepend() {
document.querySelector('#alerts').prepend(el);
return this;
},
append() {
document.querySelector('#alerts').appendChild(el);
return this;
},
};
}
// update checker
fetch(
`https://api.github.com/repos/dragonwocky/notion-enhancer/releases/latest`
)
.then((res) => res.json())
.then((res) => {
const version = {
local: __mod.version.split(/[~-]/g)[0],
repo: res.tag_name.slice(1),
};
if (version.local == version.repo) return;
// compare func from https://github.com/substack/semver-compare
version.sorted = [version.local, version.repo].sort((a, b) => {
var pa = a.split('.');
var pb = b.split('.');
for (var i = 0; i < 3; i++) {
var na = Number(pa[i]);
var nb = Number(pb[i]);
if (na > nb) return 1;
if (nb > na) return -1;
if (!isNaN(na) && isNaN(nb)) return 1;
if (isNaN(na) && !isNaN(nb)) return -1;
}
return 0;
});
createAlert(
'warning',
version.sorted[0] == version.local
? `update <b>v${version.repo}</b> available!<br>
run <code>npm i -g notion-enhancer</code><br>
(or <code>yarn global add notion-enhancer</code>),<br>
<u>and</u> <code>notion-enhancer apply</code>.`
: `local build <b>v${__mod.version}</b> is unstable.`
).prepend();
});
const modules = helpers.getEnhancements();
if (modules.loaded.length)
console.info(
`<notion-enhancer> enhancements loaded: ${modules.loaded
.map((mod) => mod.name)
.join(', ')}.`
);
if (modules.invalid.length) {
createAlert(
'error',
`invalid mods found: ${modules.invalid
.map((mod) => `<b>${mod}</b>`)
.join(', ')}.`
).append();
}
}; };

View File

@ -119,7 +119,6 @@ module.exports = (defaults) =>
enhancer_menu = new electron.BrowserWindow({ enhancer_menu = new electron.BrowserWindow({
show: true, show: true,
frame: false, frame: false,
backgroundColor: '#ffffff',
titleBarStyle: 'hiddenInset', titleBarStyle: 'hiddenInset',
x: x:
window_state.x || window_state.x ||

View File

@ -109,6 +109,40 @@ function getNotion() {
return folder; return folder;
} }
// lists/fetches all available extensions + themes
function getEnhancements() {
const modules = {
loaded: [],
invalid: [],
dirs: fs
.readdirSync(path.resolve(`${__dirname}/../mods`))
.filter((dir) => !dir.startsWith('.')),
IDs: [],
};
for (let dir of modules.dirs) {
try {
const mod = require(`../mods/${dir}/mod.js`);
if (
!mod.id ||
modules.IDs.includes(mod.id) ||
!mod.name ||
!mod.version ||
!mod.author ||
!['extension', 'theme', 'core'].includes(mod.type)
)
throw Error;
modules.loaded.push({
...mod,
dir,
});
} catch (err) {
// console.error(err);
modules.invalid.push(dir);
}
}
return modules;
}
// attempts to read a JSON file, falls back to empty object. // attempts to read a JSON file, falls back to empty object.
function getJSON(from) { function getJSON(from) {
try { try {
@ -137,6 +171,7 @@ module.exports = {
data_folder, data_folder,
realpath, realpath,
getNotion, getNotion,
getEnhancements,
getJSON, getJSON,
readline, readline,
}; };

View File

@ -62,12 +62,24 @@ function getNotion() {
} }
``` ```
use `await helpers.getNotion()` to get the notion app parent folder path use `await helpers.getNotion()` to get the notion app parent folder path.
primarily used for internal modding of the app (e.g. to apply the modloader and patch launch scripts). primarily used for internal modding of the app (e.g. to apply the modloader and patch launch scripts).
--- ---
```js
function getEnhancements() {
return { loaded, invalid, dirs, IDs };
}
```
use `helpers.getEnhancements()` to list all available extensions/themes.
primarily used for internal moadloading/configuration of the app (e.g. in the menu).
---
```js ```js
function getJSON(from) { function getJSON(from) {
return data; return data;

View File

@ -17,55 +17,6 @@ module.exports = function (__file, __exports) {
.slice(path.resolve(`${__notion}/app`).length + 1) .slice(path.resolve(`${__notion}/app`).length + 1)
.replace(/\\/g, '/'); .replace(/\\/g, '/');
const modules = {
source: fs
.readdirSync(path.resolve(`${__dirname}/../mods`))
.filter((dir) => !dir.startsWith('.')),
invalid: [],
loaded: [],
};
for (let dir of modules.source) {
try {
const mod = require(`../mods/${dir}/mod.js`);
if (
!mod.id ||
!mod.name ||
!mod.version ||
!mod.author ||
!['extension', 'theme', 'core'].includes(mod.type)
)
throw Error;
if (mod.type === 'core' || store('mods', { [mod.id]: false })[mod.id]) {
if (mod.hacks && mod.hacks[__file])
mod.hacks[__file](
(...args) =>
args.length === 1
? store(mod.id, args[0])
: store(args[0], args[1]),
__exports
);
if (
__file === 'renderer/preload.js' &&
fs.pathExistsSync(
path.resolve(`${__dirname}/../mods/${dir}/styles.css`)
)
) {
document.addEventListener('readystatechange', (event) => {
if (document.readyState !== 'complete') return false;
const style = document.createElement('link');
style.rel = 'stylesheet';
style.href = `enhancement://${dir}/styles.css`;
document.querySelector('head').appendChild(style);
});
}
}
modules.loaded.push(mod.name);
} catch (err) {
// console.error(err);
modules.invalid.push(dir);
}
}
if (__file === 'main/main.js') { if (__file === 'main/main.js') {
const electron = require('electron'); const electron = require('electron');
electron.app.whenReady().then(() => { electron.app.whenReady().then(() => {
@ -81,14 +32,31 @@ module.exports = function (__file, __exports) {
}); });
} }
if (__file === 'renderer/preload.js') { const modules = helpers.getEnhancements();
if (modules.loaded.length) for (let mod of modules.loaded) {
console.info( if (
`<notion-enhancer> enhancements loaded: ${modules.loaded.join(', ')}.` __file === 'renderer/preload.js' &&
); fs.pathExistsSync(
if (modules.invalid.length) path.resolve(`${__dirname}/../mods/${mod.dir}/styles.css`)
console.error( )
`<notion-enhancer> invalid mods found: ${modules.invalid.join(', ')}.` ) {
document.addEventListener('readystatechange', (event) => {
if (document.readyState !== 'complete') return false;
const style = document.createElement('link');
style.rel = 'stylesheet';
style.href = `enhancement://${mod.dir}/styles.css`;
document.querySelector('head').appendChild(style);
});
}
if (mod.type === 'core' || store('mods', { [mod.id]: false })[mod.id]) {
if (mod.hacks && mod.hacks[__file])
mod.hacks[__file](
(...args) =>
args.length === 1
? store(mod.id, args[0])
: store(args[0], args[1]),
__exports
); );
} }
}
}; };