Everyone has the Notebooks chooser

From the development repository at 1ccf212.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
ackandClaude Fable 5.1 committed 2026-10-11 17:34:24 +02:00
1 parent ba6791455b
commit bc3c9bb886
6 files changed
+73 -25

No files matched your search

+13 -1
View File
@@ -15,6 +15,10 @@
* a Trash the entries are moved there, and the button says so;
* in the browser they are gone for good, and the button says that. The
* notebook being written in cannot be marked: its mark explains.
* Everyone has the chooser (Andy, 2026-10-11), so that a guest can see
* and clear what their notebook holds, in a browser above all; loading
* a page into the session is for the host and co-hosts, and a card says
* so to anyone else.
*/
import { discardNotebook, discardPage, listKeptPages, listNotebooks, readPage } from './notebook.js';
@@ -75,6 +79,8 @@ export class NotebookChooser {
this.notebook = '';
/** The notebook being written in, which cannot be deleted while it is. */
this.writing = '';
/** Whether this participant may load a page into the session. */
this.mayLoad = true;
/** Whether deletions go to a Trash (the local program's) or are for good. */
this.trash = false;
/** Counts openings, so that pictures fetched for an earlier one are dropped. */
@@ -99,10 +105,12 @@ export class NotebookChooser {
/**
* Show the notebooks, or the pages of the only notebook.
* @param {string} [notebook] Open on this notebook: the one being written in.
* @param {boolean} [mayLoad] Whether a page may be loaded into the session.
*/
async open(notebook) {
async open(notebook, mayLoad = true) {
this.opening += 1;
this.writing = notebook ?? '';
this.mayLoad = mayLoad;
this.clearMarks();
this.dialog.showModal();
element('chooser_message').textContent = '';
@@ -190,6 +198,10 @@ export class NotebookChooser {
title.textContent = pageTitle(pageName);
card.append(picture, title);
card.addEventListener('click', async () => {
if (!this.mayLoad) {
this.say('Only the host and co-hosts can start a page for everyone from a kept page.');
return;
}
const text = await readPage(notebook, pageName);
if (text === null) return;
this.dialog.close();
+5 -2
View File
@@ -1053,7 +1053,10 @@ async function enterSession(invitationText, name, notebook) {
// The host drives: the host starts new pages, and may let a guest do so.
function showHostTools() {
element('host_tools').hidden = !session.mayMakePages();
// New and Image are the host's; Notebooks, in the same group so that
// nothing moves for the host, is everyone's (the chooser reserves
// loading).
for (const id of ['new_page', 'load_image']) element(id).hidden = !session.mayMakePages();
// The Hide tool is for the host and co-hosts; losing the right
// while it is chosen puts the pen back in hand.
const hideTool = /** @type {HTMLElement} */ (document.querySelector('[data-tool=hide]'));
@@ -1095,7 +1098,7 @@ async function enterSession(invitationText, name, notebook) {
// A deleted notebook leaves the toolbar's list.
showNotebooks(sessionPicker).catch(() => {});
});
element('load_notebook_page').addEventListener('click', () => { chooser.open(writer.notebook); });
element('load_notebook_page').addEventListener('click', () => { chooser.open(writer.notebook, session.mayMakePages()); });
// Image files are chosen, and pictures of the page exported, through a
// chooser of our own, which begins where the notebooks are.
+15 -2
View File
@@ -9,6 +9,8 @@
* are covered too, since the listeners are on the document.
*/
import { trace } from './log.js';
const DELAY_MS = 2000;
const GAP_PX = 6;
@@ -55,6 +57,9 @@ function hide() {
}
export function enableTooltips() {
// Traced into the Session window's log (2026-10-11: Andy's Wacom pen
// hovering over a button on Hollis showed no tooltip, and the log is
// the way to see what the browser delivers for a hovering pen).
document.addEventListener('pointerover', (event) => {
const element = helpElement(event.target);
if (!element) {
@@ -63,9 +68,17 @@ export function enableTooltips() {
}
if (element === shownFor) return;
hide();
timer = setTimeout(() => { timer = null; show(element); }, DELAY_MS);
trace(`Hover: ${event.pointerType} over ${element.textContent?.trim() || element.id}`);
timer = setTimeout(() => {
timer = null;
trace(`Tooltip: ${element.textContent?.trim() || element.id}`);
show(element);
}, DELAY_MS);
});
document.addEventListener('pointerleave', (event) => {
if (timer !== null || shownFor) trace(`Hover: ${event.pointerType} left the document`);
hide();
});
document.addEventListener('pointerleave', hide);
// Focus that comes from a click brings no tooltip: the user is already
// acting on the element, and a list it opens would be covered (Andy,
// 2026-10-07, the notebook list). Focus from the keyboard does.