Passando a un'altra app sul telefono musica e voce si fermano e la partita va in pausa
Nascosta la pagina il browser non disegna più fotogrammi, e la musica (che sfuma a ogni fotogramma) restava accesa. Ora Music.setAway ferma subito tutti i brani; voce e musichetta del cartello si fermano, la partita va in pausa e riparte con Riprendi. Nello stato: Campomigliaio si collega dal bivio, dopo La Luna. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ApqNBvNbNCwXqR2RLo8QJh
This commit is contained in:
+5
-1
@@ -100,7 +100,11 @@ I prompt fissi (stile, scene, foglio sprite) sono in `prompts/STILE.md`, escluso
|
|||||||
schermata sul desktop; sul telefono si scorre in verticale.
|
schermata sul desktop; sul telefono si scorre in verticale.
|
||||||
- **Campomigliaio**: tre foto dell'Arcu (Marco Arcuri, ora nei crediti) trasformate da Codex: il ponte a due arcate sul
|
- **Campomigliaio**: tre foto dell'Arcu (Marco Arcuri, ora nei crediti) trasformate da Codex: il ponte a due arcate sul
|
||||||
torrente, il Circolo SMS, la strada principale. Pronte in `assets/scenes/campomigliaio-{ponte,circolo,strada}.png`,
|
torrente, il Circolo SMS, la strada principale. Pronte in `assets/scenes/campomigliaio-{ponte,circolo,strada}.png`,
|
||||||
**ancora da collegare** (camminata, hotspot, uscite, posto sulla mappa).
|
**ancora da collegare** (camminata, hotspot, uscite, posto sulla mappa). Andrea, 24 ottobre: ci si arriva dal bivio
|
||||||
|
della Via Provinciale (verso stazione e forno), andando a sinistra; ma prima viene **La Luna**, che Andrea deve
|
||||||
|
ancora fotografare: si collega bivio → La Luna → Campomigliaio.
|
||||||
|
- **Audio sul telefono**: passando a un'altra app (pagina nascosta) musica, voce e musichetta si fermano subito e la
|
||||||
|
partita va in pausa; la musica riparte con Riprendi.
|
||||||
- **Pronuncia** (`tools/pronuncia.json`): le parole che XTTS legge male, scritte come vanno lette; vale solo per la voce.
|
- **Pronuncia** (`tools/pronuncia.json`): le parole che XTTS legge male, scritte come vanno lette; vale solo per la voce.
|
||||||
Per ora «celo» → «ce l'ho». Le 32 voci nuove del 24 ottobre non sono state controllate con Whisper (qui non installato).
|
Per ora «celo» → «ce l'ho». Le 32 voci nuove del 24 ottobre non sono state controllate con Whisper (qui non installato).
|
||||||
- **Sessione del 23-24 ottobre**: il paese è quasi tutto in gioco (circa 40 scene, sfondi di Codex dalle foto di
|
- **Sessione del 23-24 ottobre**: il paese è quasi tutto in gioco (circa 40 scene, sfondi di Codex dalle foto di
|
||||||
|
|||||||
+9
-1
@@ -24,6 +24,14 @@ export class Music {
|
|||||||
this.old = [];
|
this.old = [];
|
||||||
this.duck = 1; // 1 = pieno; meno di 1 mentre parla qualcuno
|
this.duck = 1; // 1 = pieno; meno di 1 mentre parla qualcuno
|
||||||
this.hold = false; // in pausa: il brano sfuma e si ferma, poi riprende da dov'era
|
this.hold = false; // in pausa: il brano sfuma e si ferma, poi riprende da dov'era
|
||||||
|
this.away = false; // pagina nascosta (sul telefono si è passati a un'altra app): tutto fermo subito
|
||||||
|
}
|
||||||
|
|
||||||
|
// Nascosta la pagina il browser non chiama più update (niente fotogrammi): i brani si fermano qui, di colpo.
|
||||||
|
// Tornati, update li fa ripartire da dov'erano (se non c'è la pausa).
|
||||||
|
setAway(away) {
|
||||||
|
this.away = away;
|
||||||
|
if (away) for (const a of [this.current?.audio, ...this.old]) a?.pause();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Chiamata a ogni fotogramma con il brano voluto: avvia, cambia e sfuma.
|
// Chiamata a ogni fotogramma con il brano voluto: avvia, cambia e sfuma.
|
||||||
@@ -39,7 +47,7 @@ export class Music {
|
|||||||
const a = this.current.audio;
|
const a = this.current.audio;
|
||||||
a.volume = a.volume < target ? Math.min(target, a.volume + step) : Math.max(target, a.volume - step);
|
a.volume = a.volume < target ? Math.min(target, a.volume + step) : Math.max(target, a.volume - step);
|
||||||
if (this.hold && a.volume === 0 && !a.paused) a.pause();
|
if (this.hold && a.volume === 0 && !a.paused) a.pause();
|
||||||
else if (!this.hold && a.paused && a !== this.blocked) a.play().catch(() => { this.blocked = a; });
|
else if (!this.hold && !this.away && a.paused && a !== this.blocked) a.play().catch(() => { this.blocked = a; });
|
||||||
}
|
}
|
||||||
for (const a of this.old) a.volume = Math.max(0, a.volume - step);
|
for (const a of this.old) a.volume = Math.max(0, a.volume - step);
|
||||||
this.old = this.old.filter(a => a.volume > 0 || (a.pause(), false));
|
this.old = this.old.filter(a => a.volume > 0 || (a.pause(), false));
|
||||||
|
|||||||
+13
@@ -164,6 +164,19 @@ function closePause() {
|
|||||||
running = true;
|
running = true;
|
||||||
}
|
}
|
||||||
$('pause-button').addEventListener('click', openPause);
|
$('pause-button').addEventListener('click', openPause);
|
||||||
|
// Sul telefono, passando a un'altra app (o cambiando scheda), si ferma tutto: musica, voce, musichetta del cartello;
|
||||||
|
// la partita va in pausa e aspetta. Tornando riparte la musica; la voce solo se non c'è la pausa (riparte con Riprendi).
|
||||||
|
function leave(hidden) {
|
||||||
|
music.setAway(hidden);
|
||||||
|
if (hidden) {
|
||||||
|
voices.pause();
|
||||||
|
window.jingle?.pause();
|
||||||
|
if (running) openPause();
|
||||||
|
} else if ($('pause').hidden) voices.resume();
|
||||||
|
}
|
||||||
|
document.addEventListener('visibilitychange', () => leave(document.hidden));
|
||||||
|
addEventListener('pagehide', () => leave(true));
|
||||||
|
addEventListener('pageshow', () => leave(document.hidden));
|
||||||
$('resume').addEventListener('click', closePause);
|
$('resume').addEventListener('click', closePause);
|
||||||
$('pause-map').addEventListener('click', () => { closePause(); openMap(); });
|
$('pause-map').addEventListener('click', () => { closePause(); openMap(); });
|
||||||
$('to-title').addEventListener('click', () => {
|
$('to-title').addEventListener('click', () => {
|
||||||
|
|||||||
@@ -157,6 +157,15 @@ try {
|
|||||||
await page.locator('#voice-volume').fill('70');
|
await page.locator('#voice-volume').fill('70');
|
||||||
assert.deepEqual(await page.evaluate(() => JSON.parse(localStorage.getItem('leggenda-regolo-audio'))), { volume: 0.3, muted: false, voices: 0.7 });
|
assert.deepEqual(await page.evaluate(() => JSON.parse(localStorage.getItem('leggenda-regolo-audio'))), { volume: 0.3, muted: false, voices: 0.7 });
|
||||||
assert.equal(await page.evaluate(() => voices.volume), 0.7);
|
assert.equal(await page.evaluate(() => voices.volume), 0.7);
|
||||||
|
// Sul telefono si passa a un'altra app: la pagina diventa nascosta, la musica si ferma subito e la partita va in
|
||||||
|
// pausa; tornando la musica riparte solo con Riprendi (la pausa la tiene ferma).
|
||||||
|
const hide = hidden => page.evaluate(h => { Object.defineProperty(document, 'hidden', { value: h, configurable: true }); document.dispatchEvent(new Event('visibilitychange')); }, hidden);
|
||||||
|
await hide(true);
|
||||||
|
assert.ok(await page.evaluate(() => music.current.audio.paused), 'nascosta la pagina, la musica è ferma');
|
||||||
|
assert.ok(await page.isVisible('#pause'), 'e la partita è in pausa');
|
||||||
|
await hide(false);
|
||||||
|
await page.click('#resume');
|
||||||
|
await page.waitForFunction(() => !music.current.audio.paused, null, { timeout: 5000 });
|
||||||
|
|
||||||
for (const [verb, target, item] of solution) {
|
for (const [verb, target, item] of solution) {
|
||||||
if (verb === 'choose') {
|
if (verb === 'choose') {
|
||||||
|
|||||||
@@ -58,3 +58,23 @@ test('in pausa la musica sfuma fino a zero e si ferma', () => {
|
|||||||
assert.ok(!m.current.audio.paused && played.length === 2, 'riprende lo stesso brano');
|
assert.ok(!m.current.audio.paused && played.length === 2, 'riprende lo stesso brano');
|
||||||
delete globalThis.Audio;
|
delete globalThis.Audio;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('passando a un\'altra app la musica si ferma subito, e tornando riparte', () => {
|
||||||
|
globalThis.Audio ??= class { constructor(src) { this.src = src; this.volume = 0; this.paused = true; } play() { this.paused = false; return Promise.resolve(); } pause() { this.paused = true; } };
|
||||||
|
const m = new Music({ volume: 0.6 });
|
||||||
|
for (let i = 0; i < 20; i++) m.update('a.mp3', 0.1);
|
||||||
|
m.update('b.mp3', 0.1); // a.mp3 sta ancora sfumando
|
||||||
|
const [old, now] = [m.old[0], m.current.audio];
|
||||||
|
assert.ok(!now.paused && !old.paused);
|
||||||
|
m.setAway(true);
|
||||||
|
assert.ok(now.paused && old.paused, 'ferma subito, senza aspettare i fotogrammi');
|
||||||
|
m.update('b.mp3', 0.1);
|
||||||
|
assert.ok(now.paused, 'finché la pagina è nascosta non riparte');
|
||||||
|
m.setAway(false);
|
||||||
|
m.update('b.mp3', 0.1);
|
||||||
|
assert.ok(!now.paused, 'tornati, riparte');
|
||||||
|
m.hold = true;
|
||||||
|
m.setAway(true); m.setAway(false);
|
||||||
|
m.update('b.mp3', 0.1);
|
||||||
|
assert.ok(now.paused, 'con la pausa aperta resta ferma');
|
||||||
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user