from static method

VoiceButtonPhase from({
  1. required SessionStatus status,
  2. required AudioState audio,
  3. required bool open,
})

Derives the phase from the coarse SessionStatus + AudioState.

Connection status dominates (connecting/reconnecting → connecting); when ready, the audio state decides listening vs speaking. Text-only / muted sessions stay idle visually since there is no mic activity to show.

Implementation

static VoiceButtonPhase from({
  required SessionStatus status,
  required AudioState audio,
  required bool open,
}) {
  switch (status) {
    case SessionStatus.connecting:
    case SessionStatus.reconnecting:
      return VoiceButtonPhase.connecting;
    case SessionStatus.ended:
    case SessionStatus.failed:
      return VoiceButtonPhase.idle;
    case SessionStatus.ready:
      break;
  }
  return switch (audio) {
    AudioState.speaking => VoiceButtonPhase.speaking,
    AudioState.capturing => VoiceButtonPhase.listening,
    AudioState.muted || AudioState.inactive => VoiceButtonPhase.idle,
  };
}