UNPKG

react-select-media-devices-modal

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