* feat(web): Ingo UX — proactivity signals, Oo face richness, soft audio Priority S: Heute Brief buckets (Needs you ≤3 / Doing / Done), roster doing-verbs and Braucht-dich chips, sidebar badge on Heute, need-you ping on waiting states. Priority A/B: Web Audio cues (app-start shimmer, interact tick, success-resolve, need-you ouh), reaction vocals with cooldown, optional eOo cold-open voice mark. Oo eyes gain iris/specular detail and asymmetric blink; hands reduced to rest except punctuation poses; speaking mouth animates. Co-authored-by: cynarAI <cynarAI@users.noreply.github.com> * fix(web): biome format and unused import in HeuteBrief Co-authored-by: cynarAI <cynarAI@users.noreply.github.com> * fix(web): a11y and import order for Heute badge Co-authored-by: cynarAI <cynarAI@users.noreply.github.com> * docs+motion: Motion God craft — pose stagger, audio bus, ducking Add MOTION-EVOO-CHARACTER.md (Brand Soul brief): eyes lead, mouth ~80%, hands punctuation, 40–80 ms eye→mouth lag, 220–320 ms springs, SFX LUFS and duck-under-TTS/PTT, nod mh/Mhh, reduced-motion rules. Implement motion-tokens, staggered mouthPose in EvooMascot, shared oo-audio-bus with voice-lane ducking, mint→gold success, hm nod vocal. Co-authored-by: cynarAI <cynarAI@users.noreply.github.com> * fix(web): align conversation roster with bot-only sidebar groups after rebase Co-authored-by: cynarAI <cynarAI@users.noreply.github.com> --------- Co-authored-by: Cursor Agent <cursoragent@cursor.com> Co-authored-by: cynarAI <cynarAI@users.noreply.github.com>
22 lines
676 B
TypeScript
22 lines
676 B
TypeScript
import { dictation } from "./dictation";
|
|
import { ooAudioBus } from "./oo-audio-bus";
|
|
import { speaker } from "./tts";
|
|
|
|
/** Duck procedural SFX under TTS playback and PTT/listening wash. */
|
|
export function wireOoAudioVoiceDucking(): () => void {
|
|
const unsubSpeaker = speaker.subscribe((snapshot) => {
|
|
ooAudioBus.setVoiceLaneActive(
|
|
snapshot.status === "preparing" || snapshot.status === "speaking",
|
|
);
|
|
});
|
|
const unsubDictation = dictation.subscribe((snapshot) => {
|
|
ooAudioBus.setVoiceLaneActive(
|
|
snapshot.status === "listening" || snapshot.status === "transcribing",
|
|
);
|
|
});
|
|
return () => {
|
|
unsubSpeaker();
|
|
unsubDictation();
|
|
};
|
|
}
|