Zero-dependency Node server + plain HTML/JS frontend. - Library is a folder tree (Manga/Book/Chapter/pages), indexed in place; page roles (cover, double, extra, rotation) are file name tags - Accounts with per-user progress, reading settings, follows and new-chapter notifications (in-app + optional webhook) - Reader with Flow, Page and Book modes, pointer-anchored page zoom, tap zones, auto-hiding controls, chapter picker, page preloading - Multiple versions per chapter with community votes - Docker image and compose file - Demo library generator (tools/make-dummy.js) - Docs: architecture, library format, import, scraper guide
27 lines
1.1 KiB
JavaScript
27 lines
1.1 KiB
JavaScript
'use strict';
|
|
(async function () {
|
|
const info = await api('api/auth').catch(() => ({}));
|
|
let signup = !!info.firstRun;
|
|
const draw = () => {
|
|
$('#heading').textContent = info.firstRun ? 'Create the admin account' : signup ? 'Create an account' : 'Sign in';
|
|
$('#submit').textContent = signup ? 'Create account' : 'Sign in';
|
|
$('#password').autocomplete = signup ? 'new-password' : 'current-password';
|
|
$('#toggle').hidden = info.firstRun || !info.signup;
|
|
$('#toggle').textContent = signup ? 'I have an account' : 'Create an account';
|
|
};
|
|
$('#toggle').onclick = e => { e.preventDefault(); signup = !signup; draw(); };
|
|
$('#form').onsubmit = async e => {
|
|
e.preventDefault();
|
|
try {
|
|
await api(signup ? 'api/signup' : 'api/login', { name: $('#name').value, password: $('#password').value });
|
|
const next = new URLSearchParams(location.search).get('next') || '';
|
|
location.href = /^\/(?!\/)/.test(next) ? next : './';
|
|
} catch (err) {
|
|
$('#msg').textContent = err.message;
|
|
$('#msg').hidden = false;
|
|
}
|
|
};
|
|
draw();
|
|
$('#name').focus();
|
|
})();
|