Fixes
This commit is contained in:
1 parent
9407c26d2d
commit
bfb3c87558
5 files changed
+204
-129
No files matched your search
+64
-2
@@ -12,6 +12,7 @@
|
||||
// GET /api/bookmark the navbar slot
|
||||
// POST /api/bookmark set the bookmark, and return the slot
|
||||
// GET /api/reference the navbar's chapter and verse picker
|
||||
// GET /api/verse the dialog for one verse
|
||||
//
|
||||
// Anything with a dot in its last segment is a file, not a route, and is
|
||||
// served from the cache or the network without going near the router. Pages
|
||||
@@ -371,6 +372,40 @@ async function referenceOf(code, anchor) {
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------- verse
|
||||
|
||||
// The verse dialog's model: what to call this verse, and the two addresses for
|
||||
// it. Null for anything that is not a verse of the book on screen.
|
||||
//
|
||||
// Checked against verses.json rather than taken at its word. at arrives from
|
||||
// the page, and a dialog offering to bookmark an anchor the corpus does not
|
||||
// have is a dialog offering a bookmark that lands nowhere -- so it is read
|
||||
// back through the same map the options were built from, and the label comes
|
||||
// out of that map rather than out of the id. Which is what makes a verse
|
||||
// written "19-27" read as 26:19-27 and not as whatever splitting an id on an
|
||||
// underscore would produce.
|
||||
//
|
||||
// href is relative, so a bookmark survives a change of host or port; url is
|
||||
// absolute, because the only thing anyone does with it is paste it somewhere
|
||||
// else. Both are spelled from the address bar, which is the only record of
|
||||
// which book is on screen.
|
||||
async function verseOf(page, at) {
|
||||
const code = bookOf(page);
|
||||
const anchor = parseAnchor(at);
|
||||
if (!page || !code || !anchor || !anchor.verse) return null;
|
||||
|
||||
const reference = await referenceOf(code, at);
|
||||
if (!reference) return null;
|
||||
const option = reference.verses.find((verse) => verse.id === at);
|
||||
if (!option) return null;
|
||||
|
||||
return {
|
||||
ref: code + ' ' + anchor.chapter + ':' + option.label,
|
||||
href: code + '#' + at,
|
||||
url: page.origin + page.pathname + '#' + at
|
||||
};
|
||||
}
|
||||
|
||||
const OFFLINE_NOTICE = ['Not available offline',
|
||||
'This page has not been opened on this device, so there is no copy stored ' +
|
||||
'here. Reconnect and try again, or open one you have read before.'];
|
||||
@@ -516,6 +551,24 @@ router.get('/api/reference', async (call) => {
|
||||
});
|
||||
});
|
||||
|
||||
// The dialog for one verse.
|
||||
//
|
||||
// at=v1_3 which verse, by the id of the element that is it -- the same
|
||||
// spelling the picker's options use, read back the same way.
|
||||
//
|
||||
// The book is not in the URL, for the reason it is not in the picker's: this
|
||||
// is chrome, it outlives the page under it, and HX-Current-URL is the address
|
||||
// the page is actually showing.
|
||||
//
|
||||
// 204 for anything it cannot place. htmx swaps nothing on a 204, and the
|
||||
// dialog opens on the swap, so a bad anchor is a click that does nothing
|
||||
// rather than an empty dialog asking to bookmark it.
|
||||
router.get('/api/verse', async (call) => {
|
||||
const verse = await verseOf(call.currentUrl(), call.url.searchParams.get('at'));
|
||||
if (!verse) return new Response('', { status: 204 });
|
||||
return view.render('verse.njk', { verse: verse });
|
||||
});
|
||||
|
||||
router.post('/api/bookmark', async (call) => {
|
||||
try {
|
||||
const form = await call.form();
|
||||
@@ -524,7 +577,16 @@ router.post('/api/bookmark', async (call) => {
|
||||
if (!ref || !href) return new Response('', { status: 400 });
|
||||
await withStore('readwrite',
|
||||
(s) => s.put({ ref: ref, href: href, savedAt: Date.now() }, BOOKMARK_KEY));
|
||||
return bookmarkFragment('Bookmark set.');
|
||||
// Only on the way out of a write that committed. base.njk closes the
|
||||
// dialog on this, and a dialog that closed itself on a failure would take
|
||||
// the line explaining the failure with it.
|
||||
return new Response(await bookmarkFragment('Bookmark set.'), {
|
||||
headers: {
|
||||
'Content-Type': 'text/html; charset=utf-8',
|
||||
'Cache-Control': 'no-store',
|
||||
'HX-Trigger-After-Settle': 'bookmark-saved'
|
||||
}
|
||||
});
|
||||
} catch (err) {
|
||||
return bookmarkFragment('Could not save: storage unavailable.');
|
||||
}
|
||||
@@ -596,7 +658,7 @@ const BOOKMARK_KEY = 'bookmark';
|
||||
// who has never set one is treated as being at the beginning. Everything
|
||||
// downstream can assume a mark -- bookmark.njk's empty branch is for the boot
|
||||
// page, which has no worker to ask, not for a reader without one.
|
||||
const DEFAULT_BOOKMARK = { ref: 'Genesis 1:1', href: 'GEN#v1_1' };
|
||||
const DEFAULT_BOOKMARK = { ref: 'GEN 1:1', href: 'GEN#v1_1' };
|
||||
|
||||
function openDb() {
|
||||
return new Promise((resolve, reject) => {
|
||||
|
||||
Reference in new issue
Block a user