UNPKG

react-select-media-devices-modal

Version:
605 lines (604 loc) 23.2 kB
import c, { useState as L, useEffect as w, useRef as Z, useMemo as K } from "react"; const y = () => { const [s, g] = L([]); return [s, () => { (async () => { const o = await navigator.mediaDevices.getUserMedia({ audio: !0, video: !0 }), r = await navigator.mediaDevices.enumerateDevices(); g(r), o.getTracks().forEach((B) => B.stop()); })(); }]; }, ae = ({ name: s, value: g, style: f }) => /* @__PURE__ */ c.createElement("option", { style: f, value: g }, s), U = ({ devices: s, label: g, selectedDevice: f, style: o, onChange: r }) => { if (s === void 0) return /* @__PURE__ */ c.createElement(c.Fragment, null); const B = (E) => { r(E.target.value); }, H = `device-select-${g.toLowerCase().replace(/\s/g, "-")}`, I = { deviceList: { paddingTop: "8px" }, label: {}, select: { marginTop: "4px", borderRadius: "4px", height: "32px", display: "flex", alignItems: "center", justifyContent: "right", width: "100%" }, deviceItems: {} }, V = { deviceList: o ? { ...I.deviceList, ...o.deviceList } : I.deviceList, label: o ? { ...I.label, ...o.label } : I.label, select: o ? { ...I.select, ...o.select } : I.select, deviceItems: o ? { ...I.deviceItems, ...o.deviceItems } : I.deviceItems }; return /* @__PURE__ */ c.createElement("div", { style: V.deviceList }, /* @__PURE__ */ c.createElement("label", { style: V.label, htmlFor: H }, g), /* @__PURE__ */ c.createElement("select", { style: V.select, id: H, onChange: B, defaultValue: f?.deviceId }, s.map((E, e) => /* @__PURE__ */ c.createElement(ae, { style: V.deviceItems, value: E.deviceId, name: E.label, key: e })))); }, J = ({ children: s, disabled: g, style: f, onClick: o }) => { const r = { borderRadius: "4px", height: "32px", paddingLeft: "16px", paddingRight: "16px", backgroundColor: "white", borderWidth: "1px" }, B = f ? { ...r, ...f } : r; return /* @__PURE__ */ c.createElement("button", { onClick: o, disabled: g, style: B }, s); }, ve = ({ isSelectAudioInput: s = !0, isSelectAudioOutput: g = !0, isSelectVideoInput: f = !0, open: o, audioInputDeviceLabel: r = "audio input device", audioOutputDeviceLabel: B = "audio output device", videoInputDeviceLabel: H = "video input device", confirmButtonText: I = "Confirm", cancelButtonText: V = "Cancel", allowOutsideClick: E = !0, style: e, onDeviceSelected: t, onDeviceSelectCanceled: $ }) => { const [k, h] = y(), [S, A] = L(), [j, M] = L(), [R, G] = L(), Q = k.filter((v) => v.kind === "audioinput"), W = k.filter((v) => v.kind === "audiooutput"), T = k.filter((v) => v.kind === "videoinput"), d = { background: { position: "fixed", top: 0, left: 0, width: "100%", height: "100%", backgroundColor: "rgba(0, 0, 0, 0.3)", display: "flex", alignItems: "center", justifyContent: "center" }, modal: { background: "white", padding: "16px", borderRadius: "8px", minWidth: "270px" }, deviceLists: { display: "grid" }, audioInputDeviceList: {}, audioOutputDeviceList: {}, videoInputDeviceList: {}, buttons: { paddingTop: "16px", display: "flex", alignItems: "center", justifyContent: "right" }, cancelButton: {}, confirmButton: { marginLeft: "4px" } }, [p, b] = L({ background: e ? { ...d.background, ...e.background } : d.background, modal: e ? { ...d.modal, ...e.modal } : d.modal, deviceLists: e ? { ...d.deviceLists, ...e.deviceLists } : d.deviceLists, audioInputDeviceList: e ? { ...d.audioInputDeviceList, ...e.audioInputDeviceList } : {}, audioOutputDeviceList: e ? { ...d.audioOutputDeviceList, ...e.audioOutputDeviceList } : {}, videoInputDeviceList: e ? { ...d.videoInputDeviceList, ...e.videoInputDeviceList } : {}, buttons: e ? { ...d.buttons, ...e.buttons } : d.buttons, cancelButton: e ? { ...d.cancelButton, ...e.cancelButton } : d.cancelButton, confirmButton: e ? { ...d.confirmButton, ...e.confirmButton } : d.confirmButton }); w(() => { b({ background: e ? { ...d.background, ...e.background } : d.background, modal: e ? { ...d.modal, ...e.modal } : d.modal, deviceLists: e ? { ...d.deviceLists, ...e.deviceLists } : d.deviceLists, audioInputDeviceList: e ? { ...d.audioInputDeviceList, ...e.audioInputDeviceList } : {}, audioOutputDeviceList: e ? { ...d.audioOutputDeviceList, ...e.audioOutputDeviceList } : {}, videoInputDeviceList: e ? { ...d.videoInputDeviceList, ...e.videoInputDeviceList } : {}, buttons: e ? { ...d.buttons, ...e.buttons } : d.buttons, cancelButton: e ? { ...d.cancelButton, ...e.cancelButton } : d.cancelButton, confirmButton: e ? { ...d.confirmButton, ...e.confirmButton } : d.confirmButton }); }, [e]), w(() => { o ? (navigator.mediaDevices.addEventListener("devicechange", h), h()) : navigator.mediaDevices.removeEventListener("devicechange", h); }, [o]); const D = () => { t({ audioInput: S !== void 0 ? S : Q[0], audioOutput: j !== void 0 ? j : W[0], videoInput: R !== void 0 ? R : T[0] }); }, _ = () => { $(); }, n = (v) => { A(Q.find((x) => x.deviceId === v)); }, l = (v) => { M(W.find((x) => x.deviceId === v)); }, F = (v) => { G(T.find((x) => x.deviceId === v)); }, q = () => { $(); }; return o ? /* @__PURE__ */ c.createElement("div", { style: p.background, ...E ? { onClick: q } : {} }, /* @__PURE__ */ c.createElement( "div", { style: p.modal, ...E ? { onClick: (v) => v.stopPropagation() } : {} }, /* @__PURE__ */ c.createElement("div", { style: p.deviceLists }, s && /* @__PURE__ */ c.createElement( U, { style: p?.audioInputDeviceList, label: r, devices: Q, selectedDevice: S, onChange: n } ), g && /* @__PURE__ */ c.createElement( U, { style: p?.audioOutputDeviceList, label: B, devices: W, selectedDevice: j, onChange: l } ), f && /* @__PURE__ */ c.createElement( U, { style: p?.videoInputDeviceList, label: H, devices: T, selectedDevice: R, onChange: F } )), /* @__PURE__ */ c.createElement("div", { style: p.buttons }, /* @__PURE__ */ c.createElement(J, { style: p.cancelButton, onClick: _ }, V), /* @__PURE__ */ c.createElement(J, { style: p.confirmButton, onClick: D }, I)) )) : /* @__PURE__ */ c.createElement(c.Fragment, null); }, P = () => { const [s, g] = L(); return w(() => () => { s !== void 0 && s.getTracks().forEach((r) => r.stop()); }, []), [s, (r) => { r.kind !== "audiooutput" && (async () => { const B = await navigator.mediaDevices.getUserMedia( r.kind === "audioinput" ? { video: !1, audio: { deviceId: r.deviceId } } : { video: { deviceId: r.deviceId }, audio: !1 } ); g(B); })(); }, () => { s !== void 0 && (s.getTracks().forEach((r) => r.stop()), g(void 0)); }]; }, re = ({ isSelectAudioInput: s = !0, isSelectAudioOutput: g = !0, isSelectVideoInput: f = !0, open: o, audioInputDeviceLabel: r = "audio input device", audioOutputDeviceLabel: B = "audio output device", videoInputDeviceLabel: H = "video input device", confirmButtonText: I = "Confirm", cancelButtonText: V = "Cancel", allowOutsideClick: E = !0, style: e, onDeviceSelected: t, onDeviceSelectCanceled: $ }) => { const [k, h] = y(), [S, A] = L(), [j, M] = L(), [R, G] = L(), [Q, W, T] = P(), d = Z(null), p = K(() => k.filter((a) => a.kind === "audioinput"), [k]), b = K(() => k.filter((a) => a.kind === "audiooutput"), [k]), D = K(() => k.filter((a) => a.kind === "videoinput"), [k]), _ = matchMedia("(max-width: 640px)"), n = { background: { position: "fixed", top: 0, left: 0, width: "100%", height: "100%", backgroundColor: "rgba(0, 0, 0, 0.3)", display: "flex", alignItems: "center", justifyContent: "center" }, modal: { background: "white", padding: "16px", borderRadius: "8px" }, deviceSelectContainer: _.matches ? { display: "grid", gridTemplateColumns: "100%" } : { display: "grid", gridTemplateColumns: "50% 50%" }, preview: { minWidth: "270px", minHeight: "180px", maxWidth: "270px", maxHeight: "180px", marginRight: "4px" }, previewVideo: { width: "270px", height: "180px" }, deviceLists: { display: "grid", minWidth: "270px", marginLeft: "8px" }, audioInputDeviceList: {}, audioOutputDeviceList: {}, videoInputDeviceList: {}, buttons: { paddingTop: "16px", display: "flex", alignItems: "center", justifyContent: "right" }, cancelButton: {}, confirmButton: { marginLeft: "4px" } }, [l, F] = L({ background: e ? { ...n.background, ...e.background } : n.background, modal: e ? { ...n.modal, ...e.modal } : n.modal, deviceSelectContainer: e ? { ...n.deviceSelectContainer, ...e.deviceSelectContainer } : n.deviceSelectContainer, preview: e ? { ...n.preview, ...e.preview } : n.preview, previewVideo: e ? { ...n.previewVideo, ...e.previewVideo } : n.previewVideo, deviceLists: e ? { ...n.deviceLists, ...e.deviceLists } : n.deviceLists, audioInputDeviceList: e ? { ...n.audioInputDeviceList, ...e.audioInputDeviceList } : n.audioInputDeviceList, audioOutputDeviceList: e ? { ...n.audioOutputDeviceList, ...e.audioOutputDeviceList } : n.audioOutputDeviceList, videoInputDeviceList: e ? { ...n.videoInputDeviceList, ...e.videoInputDeviceList } : n.videoInputDeviceList, buttons: e ? { ...n.buttons, ...e.buttons } : n.buttons, cancelButton: e ? { ...n.cancelButton, ...e.cancelButton } : n.cancelButton, confirmButton: e ? { ...n.confirmButton, ...e.confirmButton } : n.confirmButton }); w(() => { F({ background: e ? { ...n.background, ...e.background } : n.background, modal: e ? { ...n.modal, ...e.modal } : n.modal, deviceSelectContainer: e ? { ...n.deviceSelectContainer, ...e.deviceSelectContainer } : n.deviceSelectContainer, preview: e ? { ...n.preview, ...e.preview } : n.preview, previewVideo: e ? { ...n.previewVideo, ...e.previewVideo } : n.previewVideo, deviceLists: e ? { ...n.deviceLists, ...e.deviceLists } : n.deviceLists, audioInputDeviceList: e ? { ...n.audioInputDeviceList, ...e.audioInputDeviceList } : n.audioInputDeviceList, audioOutputDeviceList: e ? { ...n.audioOutputDeviceList, ...e.audioOutputDeviceList } : n.audioOutputDeviceList, videoInputDeviceList: e ? { ...n.videoInputDeviceList, ...e.videoInputDeviceList } : n.videoInputDeviceList, buttons: e ? { ...n.buttons, ...e.buttons } : n.buttons, cancelButton: e ? { ...n.cancelButton, ...e.cancelButton } : n.cancelButton, confirmButton: e ? { ...n.confirmButton, ...e.confirmButton } : n.confirmButton }); }, [e]), w(() => { const a = () => { _.matches ? F({ ...l, deviceSelectContainer: { display: "grid", gridTemplateColumns: "100%" } }) : F({ ...l, deviceSelectContainer: { display: "grid", gridTemplateColumns: "50% 50%" } }); }; return _.addEventListener("change", a), () => { _.removeEventListener("change", a); }; }, []), w(() => { o ? (navigator.mediaDevices.addEventListener("devicechange", h), h()) : navigator.mediaDevices.removeEventListener("devicechange", h); }, [o]), w(() => { if (D.length < 1) return; const a = D.find((O) => O.deviceId === R?.deviceId) ?? D[0]; W(a); }, [D]); const q = () => { T(), t({ audioInput: S !== void 0 ? S : p[0], audioOutput: j !== void 0 ? j : b[0], videoInput: R !== void 0 ? R : D[0] }); }, v = () => { T(), $(); }, x = (a) => { A(p.find((O) => O.deviceId === a)); }, i = (a) => { M(b.find((O) => O.deviceId === a)); }, m = (a) => { const O = D.find((Y) => Y.deviceId === a); G(O), W(O); }; w(() => { const { current: a } = d; a && (a.srcObject !== null && a.srcObject instanceof MediaStream && (a.srcObject.getTracks().forEach((O) => O.stop()), a.pause()), a.srcObject = Q, a.play()); }, [Q]); const N = () => { T(), $(); }; return o ? /* @__PURE__ */ c.createElement("div", { style: l.background, ...E ? { onClick: N } : {} }, /* @__PURE__ */ c.createElement( "div", { style: l.modal, ...E ? { onClick: (a) => a.stopPropagation() } : {} }, /* @__PURE__ */ c.createElement("div", { style: l.deviceSelectContainer }, /* @__PURE__ */ c.createElement("div", { style: l.preview }, /* @__PURE__ */ c.createElement("video", { style: l.previewVideo, ref: d, autoPlay: !0, muted: !0, playsInline: !0 })), /* @__PURE__ */ c.createElement("div", { style: l.deviceLists }, s && /* @__PURE__ */ c.createElement( U, { style: l.audioInputDeviceList, label: r, devices: p, selectedDevice: S, onChange: x } ), g && /* @__PURE__ */ c.createElement( U, { style: l?.audioOutputDeviceList, label: B, devices: b, selectedDevice: j, onChange: i } ), f && /* @__PURE__ */ c.createElement( U, { style: l?.videoInputDeviceList, label: H, devices: D, selectedDevice: R, onChange: m } ))), /* @__PURE__ */ c.createElement("div", { style: l.buttons }, /* @__PURE__ */ c.createElement(J, { style: l.cancelButton, onClick: v }, V), /* @__PURE__ */ c.createElement(J, { style: l.confirmButton, onClick: q }, I)) )) : /* @__PURE__ */ c.createElement(c.Fragment, null); }, se = ({ isSelectAudioInput: s = !0, isSelectAudioOutput: g = !0, isSelectVideoInput: f = !0, open: o, audioInputDeviceLabel: r = "audio input device", audioOutputDeviceLabel: B = "audio output device", videoInputDeviceLabel: H = "video input device", confirmButtonText: I = "Confirm", cancelButtonText: V = "Cancel", recordingButtonText: E = "Recording", allowOutsideClick: e = !0, style: t, onDeviceSelected: $, onDeviceSelectCanceled: k }) => { const [h, S] = y(), [A, j] = L(), [M, R] = L(), [G, Q] = L(), [W, T, d] = P(), p = Z(null), b = Z(null), [D, _] = L(), [n, l] = L(!1), F = K(() => h.filter((u) => u.kind === "audioinput"), [h]), q = K(() => h.filter((u) => u.kind === "audiooutput"), [h]), v = K(() => h.filter((u) => u.kind === "videoinput"), [h]), x = matchMedia("(max-width: 640px)"), i = { background: { position: "fixed", top: 0, left: 0, width: "100%", height: "100%", backgroundColor: "rgba(0, 0, 0, 0.3)", display: "flex", alignItems: "center", justifyContent: "center" }, modal: { background: "white", padding: "16px", borderRadius: "8px" }, deviceSelectContainer: x.matches ? { display: "grid", gridTemplateColumns: "100%" } : { display: "grid", gridTemplateColumns: "50% 50%" }, preview: { minWidth: "270px", minHeight: "180px", maxWidth: "270px", marginRight: "4px" }, previewVideo: { width: "270px", height: "180px" }, previewAudio: { width: "270px" }, deviceLists: { display: "grid", minWidth: "270px", marginLeft: "8px" }, recordingButtons: {}, recordingButton: {}, audioInputDeviceList: {}, audioOutputDeviceList: {}, videoInputDeviceList: {}, buttons: { paddingTop: "16px", display: "flex", alignItems: "center", justifyContent: "right" }, cancelButton: {}, confirmButton: { marginLeft: "4px" } }, [m, N] = L({ background: t ? { ...i.background, ...t.background } : i.background, modal: t ? { ...i.modal, ...t.modal } : i.modal, deviceSelectContainer: t ? { ...i.deviceSelectContainer, ...t.deviceSelectContainer } : i.deviceSelectContainer, preview: t ? { ...i.preview, ...t.preview } : i.preview, previewVideo: t ? { ...i.previewVideo, ...t.previewVideo } : i.previewVideo, previewAudio: t ? { ...i.previewAudio, ...t.previewAudio } : i.previewAudio, deviceLists: t ? { ...i.deviceLists, ...t.deviceLists } : i.deviceLists, recordingButtons: t ? { ...i.recordingButtons, ...t.recordingButtons } : i.recordingButtons, recordingButton: t ? { ...i.recordingButton, ...t.recordingButton } : i.recordingButton, audioInputDeviceList: t ? { ...i.audioInputDeviceList, ...t.audioInputDeviceList } : i.audioInputDeviceList, audioOutputDeviceList: t ? { ...i.audioOutputDeviceList, ...t.audioOutputDeviceList } : i.audioOutputDeviceList, videoInputDeviceList: t ? { ...i.videoInputDeviceList, ...t.videoInputDeviceList } : i.videoInputDeviceList, buttons: t ? { ...i.buttons, ...t.buttons } : i.buttons, cancelButton: t ? { ...i.cancelButton, ...t.cancelButton } : i.cancelButton, confirmButton: t ? { ...i.confirmButton, ...t.confirmButton } : i.confirmButton }); w(() => { N({ background: t ? { ...i.background, ...t.background } : i.background, modal: t ? { ...i.modal, ...t.modal } : i.modal, deviceSelectContainer: t ? { ...i.deviceSelectContainer, ...t.deviceSelectContainer } : i.deviceSelectContainer, preview: t ? { ...i.preview, ...t.preview } : i.preview, previewVideo: t ? { ...i.previewVideo, ...t.previewVideo } : i.previewVideo, previewAudio: t ? { ...i.previewAudio, ...t.previewAudio } : i.previewAudio, deviceLists: t ? { ...i.deviceLists, ...t.deviceLists } : i.deviceLists, recordingButtons: t ? { ...i.recordingButtons, ...t.recordingButtons } : i.recordingButtons, recordingButton: t ? { ...i.recordingButton, ...t.recordingButton } : i.recordingButton, audioInputDeviceList: t ? { ...i.audioInputDeviceList, ...t.audioInputDeviceList } : i.audioInputDeviceList, audioOutputDeviceList: t ? { ...i.audioOutputDeviceList, ...t.audioOutputDeviceList } : i.audioOutputDeviceList, videoInputDeviceList: t ? { ...i.videoInputDeviceList, ...t.videoInputDeviceList } : i.videoInputDeviceList, buttons: t ? { ...i.buttons, ...t.buttons } : i.buttons, cancelButton: t ? { ...i.cancelButton, ...t.cancelButton } : i.cancelButton, confirmButton: t ? { ...i.confirmButton, ...t.confirmButton } : i.confirmButton }); }, [t]), w(() => { const u = () => { x.matches ? N({ ...m, deviceSelectContainer: { display: "grid", gridTemplateColumns: "100%" } }) : N({ ...m, deviceSelectContainer: { display: "grid", gridTemplateColumns: "50% 50%" } }); }; return x.addEventListener("change", u), () => { x.removeEventListener("change", u); }; }, []), w(() => { o ? (navigator.mediaDevices.addEventListener("devicechange", S), S()) : navigator.mediaDevices.removeEventListener("devicechange", S); }, [o]), w(() => { if (v.length < 1) return; const u = v.find((C) => C.deviceId === G?.deviceId) ?? v[0]; T(u); }, [v]); const a = () => { !D || !b || (D.state === "recording" && (D.removeEventListener("dataavailable", () => { }), D.removeEventListener("stop", () => { }), D.stop(), D.stream.getTracks().forEach((u) => u.stop())), b.current.src = "", b.current.pause(), d()); }, O = () => { a(), $({ audioInput: A !== void 0 ? A : F[0], audioOutput: M !== void 0 ? M : q[0], videoInput: G !== void 0 ? G : v[0] }); }, Y = () => { a(), k(); }, ee = (u) => { j(F.find((C) => C.deviceId === u)); }, te = async (u) => { R(q.find((C) => C.deviceId === u)), await b.current.setSinkId(u); }, ie = (u) => { const C = v.find((z) => z.deviceId === u); Q(C), T(C); }, ne = async () => { const u = await navigator.mediaDevices.getUserMedia({ audio: A && A.deviceId !== "" ? { deviceId: A.deviceId } : !0, video: !1 }); let C = []; const z = new MediaRecorder(u); z.addEventListener("dataavailable", (X) => { C.push(X.data); }), z.addEventListener("stop", async (X) => { if (l(!1), !b.current) return; const de = new Blob(C, { type: "audio/ogg; codecs=opus" }); C = []; const ue = URL.createObjectURL(de); b.current.src = ue, M && M.deviceId !== "" && await b.current.setSinkId(M.deviceId); }), z.start(), _(z), l(!0), setTimeout(() => { z.stop(), u.getTracks().forEach((X) => X.stop()); }, 5e3); }; w(() => { const { current: u } = p; u && (u.srcObject !== null && u.srcObject instanceof MediaStream && (u.srcObject.getTracks().forEach((C) => C.stop()), u.pause()), u.srcObject = W, u.play()); }, [W]); const ce = () => { a(), k(); }; return o ? /* @__PURE__ */ c.createElement("div", { style: m.background, ...e ? { onClick: ce } : {} }, /* @__PURE__ */ c.createElement( "div", { style: m.modal, ...e ? { onClick: (u) => u.stopPropagation() } : {} }, /* @__PURE__ */ c.createElement("div", { style: m.deviceSelectContainer }, /* @__PURE__ */ c.createElement("div", { style: m.preview }, /* @__PURE__ */ c.createElement("video", { style: m.previewVideo, ref: p, autoPlay: !0, muted: !0, playsInline: !0 }), /* @__PURE__ */ c.createElement("audio", { style: m.previewAudio, ref: b, autoPlay: !0, playsInline: !0, controls: !0 })), /* @__PURE__ */ c.createElement("div", { style: m.deviceLists }, s && /* @__PURE__ */ c.createElement(c.Fragment, null, /* @__PURE__ */ c.createElement( U, { style: m.audioInputDeviceList, label: r, devices: F, selectedDevice: A, onChange: ee } ), /* @__PURE__ */ c.createElement("div", { style: m.recordingButtons }, /* @__PURE__ */ c.createElement( J, { style: m.recordingButton, onClick: ne, disabled: n }, E ))), g && /* @__PURE__ */ c.createElement( U, { style: m?.audioOutputDeviceList, label: B, devices: q, selectedDevice: M, onChange: te } ), f && /* @__PURE__ */ c.createElement( U, { style: m?.videoInputDeviceList, label: H, devices: v, selectedDevice: G, onChange: ie } ))), /* @__PURE__ */ c.createElement("div", { style: m.buttons }, /* @__PURE__ */ c.createElement(J, { style: m.cancelButton, onClick: Y }, V), /* @__PURE__ */ c.createElement(J, { style: m.confirmButton, onClick: O }, I)) )) : /* @__PURE__ */ c.createElement(c.Fragment, null); }; export { ve as SelectMediaDevicesModal, re as SelectMediaDevicesPreviewModal, se as SelectMediaDevicesRecordingModal };