Fix : FS after off status
All checks were successful
release / build (push) Successful in 23s
release / verify-windows (push) Successful in 1m27s

This commit is contained in:
jeanotx32
2026-08-12 22:40:58 +02:00
parent d44a7c4fb6
commit 449a6d917f
2 changed files with 62 additions and 8 deletions

View File

@@ -550,6 +550,18 @@ Quand le statut brut passe à `off`, deux temps distincts :
Le décompte s'affiche sur la fiche de l'agent. La clôture ferme aussi la fenêtre du
navigateur si son pilotage est activé, contrairement à une simple pause.
**Le plein écran est rappelé au retour, comme après un show privé.** Le lecteur en sort aussi
bien sur l'écran d'attente d'un flux coupé que sur l'overlay d'un show privé. Le cas manquait
initialement — seul le show privé armait le rappel — et il ne se limite pourtant pas à une fin
de diffusion : une coupure plus courte que le délai de clôture reprend le **même**
enregistrement, dans la **même** fenêtre, qui a entre-temps perdu son plein écran sans que
rien ne le lui rende.
Le rappel ne part que si une capture tourne réellement. Le surveillant, lui, tourne en
permanence : sans ce garde-fou, n'importe quel profil surveillé qui passe hors-ligne puis en
direct enverrait une touche à une fenêtre que personne ne filme — et en mode BiDi, irait
jusqu'à lancer Firefox pour l'occasion.
Régler le délai à `0` clôt dès la première lecture hors-ligne ; décocher « Clore
l'enregistrement quand le flux passe hors-ligne » désactive les deux temps, y compris la
pause.

View File

@@ -186,9 +186,18 @@ export class StreamWatcher extends EventEmitter {
// Le retour du flux, public ou privé, annule toute clôture programmée.
if (next !== 'offline') this.cancelOfflineStop();
if (next === 'private') {
// Le lecteur quitte le plein écran dès que l'overlay de show privé apparaît.
// Toute interruption du flux public appelle un rappel du plein écran au
// retour : le lecteur en sort aussi bien sur l'overlay de show privé que sur
// l'écran d'attente d'un flux coupé. Le hors-ligne était initialement
// absent d'ici — le cas ne se limite pourtant pas à une fin de diffusion,
// puisqu'une coupure plus courte que `offlineStopDelayMs` reprend le même
// enregistrement, dans la même fenêtre, qui a entre-temps perdu son plein
// écran sans que rien ne le lui rende.
if (next === 'private' || next === 'offline') {
this.fullscreenPending = true;
}
if (next === 'private') {
await this.handlePrivate();
return;
}
@@ -325,9 +334,37 @@ export class StreamWatcher extends EventEmitter {
}
private async handlePublic(): Promise<void> {
if (this.state.autoPaused && this.settings.resumeOnPublic) {
const resuming = this.state.autoPaused && this.settings.resumeOnPublic;
const recalling = this.fullscreenPending && this.settings.fullscreen.enabled;
// Un rappel armé alors que le réglage est désactivé n'a plus lieu d'être :
// le désarmer tout de suite évite qu'il parte bien plus tard, au premier
// réglage réactivé, pour une interruption depuis longtemps oubliée.
if (!recalling) this.fullscreenPending = false;
if (!resuming && !recalling) return;
// Une seule lecture pour les deux décisions qui suivent : reprendre une
// capture en pause, et rappeler le plein écran — qui n'a de sens que s'il y
// a justement une capture à cadrer.
let record: { active: boolean; paused: boolean };
try {
record = await this.actions.recordState();
} catch (err) {
this.emit(
'log',
'error',
`État de l'enregistrement illisible : ${err instanceof Error ? err.message : String(err)}`,
'command.failed',
);
// `autoPaused` est relâché quoi qu'il arrive : s'obstiner à reprendre une
// capture dont on ne sait rien reviendrait à réessayer à chaque sonde. Le
// rappel de plein écran, lui, reste armé — le différer ne coûte rien, et
// la sonde suivante retentera.
this.state.autoPaused = false;
return;
}
if (resuming) {
try {
const record = await this.actions.recordState();
if (record.active && record.paused) {
await this.actions.resumeRecording();
this.emit('log', 'info', 'Flux public rétabli : enregistrement repris', 'record.resumed');
@@ -344,11 +381,16 @@ export class StreamWatcher extends EventEmitter {
}
}
if (this.fullscreenPending && this.settings.fullscreen.enabled) {
this.fullscreenPending = false;
this.scheduleFullscreen();
} else {
if (recalling) {
this.fullscreenPending = false;
// Seulement s'il y a une fenêtre à cadrer. Le surveillant tourne en
// permanence, pas seulement pendant une capture : hors enregistrement, le
// rappel s'adresserait à une fenêtre que personne ne filme — et en mode
// BiDi il irait jusqu'à lancer Firefox pour l'occasion. Le cas est
// courant depuis que le hors-ligne arme lui aussi le rappel : un profil
// surveillé sans être enregistré passe hors-ligne puis en direct comme
// n'importe quel autre.
if (record.active) this.scheduleFullscreen();
}
}