Skip to main content

dioxus_audio/components/
recorder.rs

1use dioxus::prelude::*;
2use dioxus_icons::lucide::{Mic, Pause, Play, Square, X};
3
4use crate::recorder::{AudioRecorder, RecorderStatus};
5
6#[component]
7pub fn RecorderControls(
8    recorder: AudioRecorder,
9    #[props(default)] on_cancelled: Option<EventHandler<()>>,
10) -> Element {
11    let status = recorder.status()();
12    let state_name = recorder_state_name(&status);
13    let paused = matches!(status, RecorderStatus::Paused);
14    let has_completed = recorder.completed().read().is_some();
15
16    rsx! {
17        div {
18            class: "dioxus-audio dioxus-audio__recorder-controls",
19            "data-state": state_name,
20            match status {
21                RecorderStatus::Idle | RecorderStatus::Failed(_) => rsx! {
22                    button {
23                        class: "dioxus-audio__record-action dioxus-audio__record-action--record",
24                        r#type: "button",
25                        aria_label: if has_completed { "Clear completed recording before starting" } else { "Start recording" },
26                        disabled: has_completed,
27                        onclick: move |_| { let _ = recorder.start(); },
28                        Mic { size: 24 }
29                    }
30                },
31                RecorderStatus::RequestingPermission => rsx! {
32                    button {
33                        class: "dioxus-audio__record-action",
34                        r#type: "button",
35                        aria_label: "Cancel microphone request",
36                        onclick: move |_| {
37                            if recorder.cancel().is_ok()
38                                && let Some(on_cancelled) = on_cancelled
39                            {
40                                on_cancelled.call(());
41                            }
42                        },
43                        X { size: 20 }
44                    }
45                },
46                RecorderStatus::Recording | RecorderStatus::Paused => rsx! {
47                    button {
48                        class: "dioxus-audio__record-action",
49                        r#type: "button",
50                        aria_label: "Cancel recording",
51                        onclick: move |_| {
52                            if recorder.cancel().is_ok()
53                                && let Some(on_cancelled) = on_cancelled
54                            {
55                                on_cancelled.call(());
56                            }
57                        },
58                        X { size: 20 }
59                    }
60                    button {
61                        class: "dioxus-audio__record-action",
62                        r#type: "button",
63                        aria_label: if paused { "Resume" } else { "Pause" },
64                        onclick: move |_| {
65                            if paused {
66                                let _ = recorder.resume();
67                            } else {
68                                let _ = recorder.pause();
69                            }
70                        },
71                        if paused {
72                            Play { size: 20 }
73                        } else {
74                            Pause { size: 20 }
75                        }
76                    }
77                    button {
78                        class: "dioxus-audio__record-action dioxus-audio__record-action--stop",
79                        r#type: "button",
80                        aria_label: "Stop recording",
81                        onclick: move |_| { let _ = recorder.stop(); },
82                        Square { size: 22 }
83                    }
84                },
85                RecorderStatus::Stopping => rsx! {
86                    button {
87                        class: "dioxus-audio__record-action dioxus-audio__record-action--stop",
88                        r#type: "button",
89                        aria_label: "Finishing recording",
90                        disabled: true,
91                        Square { size: 22 }
92                    }
93                },
94            }
95        }
96    }
97}
98
99fn recorder_state_name(status: &RecorderStatus) -> &'static str {
100    match status {
101        RecorderStatus::Idle => "idle",
102        RecorderStatus::RequestingPermission => "requesting",
103        RecorderStatus::Recording => "recording",
104        RecorderStatus::Paused => "paused",
105        RecorderStatus::Stopping => "stopping",
106        RecorderStatus::Failed(_) => "error",
107    }
108}