fix : various stuff
This commit is contained in:
@@ -265,10 +265,14 @@ async function startCapture(params: Record<string, unknown>): Promise<unknown> {
|
||||
// une fenêtre non maximisée que ne rien capturer du tout.
|
||||
fullscreenResult = await restoreFullscreen(fullscreen)
|
||||
.then((outcome) => {
|
||||
// `skipped` prime sur `confirmed` : un envoi non renvoyé n'est jamais
|
||||
// un échec de ce côté-ci, quel que soit le sort de celui qu'il a
|
||||
// réutilisé.
|
||||
const failed = !outcome.skipped && outcome.confirmed === false;
|
||||
report(
|
||||
outcome.confirmed === false ? 'warn' : 'info',
|
||||
failed ? 'warn' : 'info',
|
||||
describeFullscreen(outcome, fullscreen.key),
|
||||
outcome.confirmed === false ? 'fullscreen.failed' : 'fullscreen.restored',
|
||||
failed ? 'fullscreen.failed' : 'fullscreen.restored',
|
||||
);
|
||||
return outcome;
|
||||
})
|
||||
@@ -411,17 +415,62 @@ function driver(): FirefoxController | null {
|
||||
return browserSettings.mode === 'bidi' ? firefox : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Au-delà de ce délai depuis le dernier envoi, un nouveau rappel est à
|
||||
* nouveau autorisé. Choisi généreux face au 1200 ms que `restoreFullscreen`
|
||||
* attend en interne avant de relire l'état : le but n'est pas de couvrir
|
||||
* l'animation, mais la fenêtre où le flux public vient tout juste de démarrer
|
||||
* et peut encore vaciller (bref retour en privé, requalification du statut).
|
||||
*/
|
||||
const FULLSCREEN_COOLDOWN_MS = 10_000;
|
||||
/** Aucun rappel encore envoyé sur cette instance d'agent. */
|
||||
let lastFullscreenAt = 0;
|
||||
/** Deux appels concurrents doivent partager le même envoi, pas en déclencher deux. */
|
||||
let fullscreenInFlight: Promise<FullscreenOutcome> | null = null;
|
||||
|
||||
/**
|
||||
* Rappelle le plein écran par la voie correspondant au mode de pilotage.
|
||||
*
|
||||
* En BiDi, la demande part dans Firefox et son effet est relu dans la page. En
|
||||
* `launch`, on en reste à une touche envoyée au serveur d'affichage, sans
|
||||
* moyen de savoir ce qu'elle a produit — d'où le `confirmed` absent.
|
||||
*
|
||||
* Point de passage unique, et c'est voulu : deux mécanismes indépendants
|
||||
* peuvent réclamer ce rappel — la séquence d'ouverture ({@link startCapture})
|
||||
* et {@link StreamWatcher}, qui le redemande de lui-même après un show privé.
|
||||
* Sans coordination, un flux qui vacille juste après le démarrage (un retour
|
||||
* bref en privé pendant que la séquence d'ouverture patiente encore) fait
|
||||
* partir les deux envois à quelques secondes d'écart. La touche du lecteur
|
||||
* basculant l'affichage plutôt que le forçant, le second envoi annule le
|
||||
* premier au lieu de le confirmer — d'où une fenêtre qui, au lieu de
|
||||
* s'agrandir, finit par rétrécir. Le garde-fou vit ici et non chez l'un des
|
||||
* deux appelants : c'est le seul endroit que les deux traversent forcément.
|
||||
*/
|
||||
async function restoreFullscreen(settings: FullscreenSettings): Promise<FullscreenOutcome> {
|
||||
// Un envoi est déjà en cours : partager son résultat, pas en déclencher un
|
||||
// second. Marqué `skipped` malgré le succès qu'il rapporte — c'est cette
|
||||
// marque, et non la réussite, qui doit gouverner le message affiché à
|
||||
// l'appelant (voir describeFullscreen) : sans elle, les deux appelants
|
||||
// journalisent chacun « touche envoyée » pour un seul envoi réel, ce qui
|
||||
// se lit comme deux rappels distincts alors qu'il n'y en a eu qu'un.
|
||||
if (fullscreenInFlight) {
|
||||
const outcome = await fullscreenInFlight;
|
||||
return { ...outcome, skipped: true };
|
||||
}
|
||||
|
||||
const sinceLast = Date.now() - lastFullscreenAt;
|
||||
if (lastFullscreenAt > 0 && sinceLast < FULLSCREEN_COOLDOWN_MS) {
|
||||
return { method: 'ignoré (rappel trop rapproché)', skipped: true };
|
||||
}
|
||||
|
||||
const bidi = driver();
|
||||
if (bidi) return bidi.restoreFullscreen(settings);
|
||||
return sendHotkey({ key: settings.key, windowMatch: settings.windowMatch });
|
||||
fullscreenInFlight = (
|
||||
bidi ? bidi.restoreFullscreen(settings) : sendHotkey({ key: settings.key, windowMatch: settings.windowMatch })
|
||||
).finally(() => {
|
||||
fullscreenInFlight = null;
|
||||
lastFullscreenAt = Date.now();
|
||||
});
|
||||
return fullscreenInFlight;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user