Reprend le design demande par Ralph, d'apres une capture : barre sombre arrondie posee en bas de l'ecran, et dedans, de gauche a droite, un bouton stop rond rouge-orange a carre blanc, une forme d'onde en barres verticales dont la traine retombe en pointilles, une icone de micro. Au-dessus, une bulle sombre a pointe. La forme d'onde demandait un HISTORIQUE de niveaux, la ou l'ancien cercle ne lisait que le niveau courant : push_level et bar_heights sont ajoutes a audio_level.py comme unites pures (le plus recent a gauche, les positions vides ou silencieuses retombent sur un plancher — c'est lui qui donne les pointilles). La bulle ne peut pas afficher le texte en direct comme la reference : Zonza transcrit APRES l'arret, il n'y a pas de flux continu. Elle porte donc l'etape en cours, et la fenetre reste affichee jusqu'au collage au lieu de disparaitre pendant les secondes de calcul — l'ecran ne se vide plus sans explication. Rendu verifie par capture d'ecran, pas seulement par les tests : le micro a ete redessine apres coup (il sortait en tache blanche) et une marge basse ajoutee, l'arrondi de la barre etant rogne par le bord de la fenetre. 45 tests passent. Le cdhash du stub est inchange, donc les autorisations d'Accessibilite survivent a cette mise a jour (verifie : accordee = True). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
73 lines
1.9 KiB
Python
73 lines
1.9 KiB
Python
"""La bulle de l'overlay porte l'etat en cours.
|
|
|
|
Zonza ne transcrit pas en continu : le texte n'existe qu'apres l'arret. La bulle
|
|
affiche donc l'etape ou l'on en est — « Je vous ecoute… » pendant la capture,
|
|
« Transcription… » pendant le calcul — et la fenetre reste visible jusqu'au
|
|
collage, au lieu de disparaitre en laissant l'utilisateur sans retour.
|
|
"""
|
|
import numpy as np
|
|
|
|
from controller import ZonzaController
|
|
from core import CONFIG
|
|
|
|
|
|
class FauxPulse:
|
|
def __init__(self):
|
|
self.statuts = []
|
|
self.visible = False
|
|
|
|
def show(self):
|
|
self.visible = True
|
|
|
|
def hide(self):
|
|
self.visible = False
|
|
|
|
def set_level(self, level):
|
|
pass
|
|
|
|
def set_status(self, text):
|
|
self.statuts.append(text)
|
|
|
|
|
|
class FauxRecorder:
|
|
def __init__(self, audio):
|
|
self.audio = audio
|
|
|
|
def start(self):
|
|
pass
|
|
|
|
def stop(self):
|
|
return self.audio
|
|
|
|
|
|
def _ctrl(audio):
|
|
pulse = FauxPulse()
|
|
c = ZonzaController(CONFIG, pulse)
|
|
c.recorder = FauxRecorder(audio)
|
|
c.transcriber = type("T", (), {"transcribe": staticmethod(lambda a: "bonjour")})()
|
|
return c, pulse
|
|
|
|
|
|
def test_la_bulle_annonce_l_ecoute_au_demarrage():
|
|
c, pulse = _ctrl(np.zeros(16000, dtype="float32"))
|
|
c.toggle()
|
|
assert pulse.visible
|
|
assert any("écoute" in s.lower() for s in pulse.statuts)
|
|
|
|
|
|
def test_la_fenetre_reste_visible_pendant_la_transcription():
|
|
audio = np.ones(16000, dtype="float32") * 0.1 # 1 s : au-dessus du seuil
|
|
c, pulse = _ctrl(audio)
|
|
c.toggle()
|
|
pulse.statuts.clear()
|
|
c._stop_and_process()
|
|
assert pulse.visible, "la fenetre ne doit pas disparaitre avant la transcription"
|
|
assert any("transcription" in s.lower() for s in pulse.statuts)
|
|
|
|
|
|
def test_un_enregistrement_trop_court_referme_tout_de_suite():
|
|
c, pulse = _ctrl(np.zeros(10, dtype="float32")) # bien sous min_duration_s
|
|
c.toggle()
|
|
c._stop_and_process()
|
|
assert not pulse.visible
|