dioxus-audio 0.1.1

Audio recording, playback, analysis, and UI components for Dioxus
Documentation
use dioxus::prelude::*;
use dioxus_icons::lucide::{Mic, Pause, Play, Square, X};

use crate::recorder::{AudioRecorder, RecorderStatus};

#[component]
pub fn RecorderControls(
    recorder: AudioRecorder,
    #[props(default)] on_cancelled: Option<EventHandler<()>>,
) -> Element {
    let status = recorder.status()();
    let state_name = recorder_state_name(&status);
    let paused = matches!(status, RecorderStatus::Paused);
    let has_completed = recorder.completed().read().is_some();

    rsx! {
        div {
            class: "dioxus-audio dioxus-audio__recorder-controls",
            "data-state": state_name,
            match status {
                RecorderStatus::Idle | RecorderStatus::Failed(_) => rsx! {
                    button {
                        class: "dioxus-audio__record-action dioxus-audio__record-action--record",
                        r#type: "button",
                        aria_label: if has_completed { "Clear completed recording before starting" } else { "Start recording" },
                        disabled: has_completed,
                        onclick: move |_| { let _ = recorder.start(); },
                        Mic { size: 24 }
                    }
                },
                RecorderStatus::RequestingPermission => rsx! {
                    button {
                        class: "dioxus-audio__record-action",
                        r#type: "button",
                        aria_label: "Cancel microphone request",
                        onclick: move |_| {
                            if recorder.cancel().is_ok()
                                && let Some(on_cancelled) = on_cancelled
                            {
                                on_cancelled.call(());
                            }
                        },
                        X { size: 20 }
                    }
                },
                RecorderStatus::Recording | RecorderStatus::Paused => rsx! {
                    button {
                        class: "dioxus-audio__record-action",
                        r#type: "button",
                        aria_label: "Cancel recording",
                        onclick: move |_| {
                            if recorder.cancel().is_ok()
                                && let Some(on_cancelled) = on_cancelled
                            {
                                on_cancelled.call(());
                            }
                        },
                        X { size: 20 }
                    }
                    button {
                        class: "dioxus-audio__record-action",
                        r#type: "button",
                        aria_label: if paused { "Resume" } else { "Pause" },
                        onclick: move |_| {
                            if paused {
                                let _ = recorder.resume();
                            } else {
                                let _ = recorder.pause();
                            }
                        },
                        if paused {
                            Play { size: 20 }
                        } else {
                            Pause { size: 20 }
                        }
                    }
                    button {
                        class: "dioxus-audio__record-action dioxus-audio__record-action--stop",
                        r#type: "button",
                        aria_label: "Stop recording",
                        onclick: move |_| { let _ = recorder.stop(); },
                        Square { size: 22 }
                    }
                },
                RecorderStatus::Stopping => rsx! {
                    button {
                        class: "dioxus-audio__record-action dioxus-audio__record-action--stop",
                        r#type: "button",
                        aria_label: "Finishing recording",
                        disabled: true,
                        Square { size: 22 }
                    }
                },
            }
        }
    }
}

fn recorder_state_name(status: &RecorderStatus) -> &'static str {
    match status {
        RecorderStatus::Idle => "idle",
        RecorderStatus::RequestingPermission => "requesting",
        RecorderStatus::Recording => "recording",
        RecorderStatus::Paused => "paused",
        RecorderStatus::Stopping => "stopping",
        RecorderStatus::Failed(_) => "error",
    }
}