@apirtc/react-lib 1.0.8 → 1.0.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/esm/hooks/index.d.ts +1 -1
- package/dist/esm/hooks/useUserMediaDevices.d.ts +1 -1
- package/dist/esm/index.js +1 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/hooks/index.d.ts +1 -1
- package/dist/hooks/useUserMediaDevices.d.ts +1 -1
- package/dist/react-lib.production.min.js +1 -1
- package/dist/react-lib.production.min.js.map +1 -1
- package/package.json +1 -1
|
@@ -6,4 +6,4 @@ export { default as useConversationStreams } from "./useConversationStreams";
|
|
|
6
6
|
export { default as usePresence } from "./usePresence";
|
|
7
7
|
export { ApiKey, Credentials, default as useSession, LoginPassword, Token } from "./useSession";
|
|
8
8
|
export { default as useStreamApplyVideoProcessor } from './useStreamApplyVideoProcessor';
|
|
9
|
-
export {
|
|
9
|
+
export { useUserMediaDevices } from "./useUserMediaDevices";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/// <reference types="react" />
|
|
2
2
|
import { MediaDevice, MediaDeviceList, Session } from '@apirtc/apirtc';
|
|
3
|
-
export
|
|
3
|
+
export declare function useUserMediaDevices(session: Session | undefined, storageKeyPrefix?: string): {
|
|
4
4
|
userMediaDevices: MediaDeviceList;
|
|
5
5
|
selectedAudioIn: MediaDevice | undefined;
|
|
6
6
|
setSelectedAudioIn: import("react").Dispatch<import("react").SetStateAction<MediaDevice | undefined>>;
|
package/dist/esm/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import e,{useRef as o,useEffect as t,useState as n,useCallback as i}from"react";import{UserAgent as a}from"@apirtc/apirtc";function s(n){const{autoPlay:i=!0}=n,a=o(null);return t((()=>{const e=a.current;if(e&&n.stream)return n.stream.attachToElement(e),()=>{e.src=""}}),[n.stream]),e.createElement("video",{id:n.stream.getId(),style:{maxWidth:"100%"},ref:a,autoPlay:i,muted:n.muted})}const l="useCameraStream";function r(e,o={}){const[i,a]=n();return t((()=>{if(e){e.getUserAgent().createStream(o).then((e=>{globalThis.apirtcReactLibLogLevel.isInfoEnabled&&console.info(l+"|createStream",o,e),a(e)})).catch((e=>{console.error(l+"|createStream",o,e),a(void 0)}))}else a(void 0)}),[e,JSON.stringify(o)]),t((()=>()=>{i&&(globalThis.apirtcReactLibLogLevel.isInfoEnabled&&console.info(l+"|release stream",i),i.release())}),[i]),{stream:i}}const c="useConversation";function b(e,o,a,s=!0){const[l,r]=n(),[b,d]=n(!1),[g,u]=n(!1),L=i((()=>(globalThis.apirtcReactLibLogLevel.isDebugEnabled&&console.debug(c+"|join",l),new Promise(((e,o)=>{l?l.isJoined()?o(c+"|join|conversation already joined"):(u(!0),l.join().then((()=>{d(!0),e()})).catch((e=>{o(e)})).finally((()=>{u(!1)}))):o(c+"|join|conversation not defined")})))),[l]),p=i((()=>(globalThis.apirtcReactLibLogLevel.isDebugEnabled&&console.debug(c+"|leave",l),new Promise(((e,o)=>{l?l.isJoined()?l.leave().then((()=>{d(!1),e()})).catch((e=>{o(e)})):o(c+"|leave|conversation is not joined"):o(c+"|leave|conversation not defined")})))),[l]);return t((()=>{if(e&&o){globalThis.apirtcReactLibLogLevel.isDebugEnabled&&console.debug(c+"|getOrCreateConversation",o,a,s);const t=e.getOrCreateConversation(o,a);return r(t),()=>{globalThis.apirtcReactLibLogLevel.isDebugEnabled&&console.debug(c+"|useEffect cleanup",o,a,s),t.isJoined()?t.leave().then((()=>{})).catch((e=>{globalThis.apirtcReactLibLogLevel.isWarnEnabled&&console.warn(c+"|useEffect conversation.leave()",e)})).finally((()=>{t.destroy()})):t.destroy(),r(void 0),d(!1)}}}),[e,o,JSON.stringify(a)]),t((()=>{if(l&&s){globalThis.apirtcReactLibLogLevel.isDebugEnabled&&console.debug(c+"|useEffect",l,s);const e=l,o=s;return o&&(u(!0),e.join().then((()=>{globalThis.apirtcReactLibLogLevel.isInfoEnabled&&console.info(c+"|joined",e),d(!0)})).catch((e=>{globalThis.apirtcReactLibLogLevel.isWarnEnabled&&console.warn(c+"|useEffect conversation.join()",e)})).finally((()=>{u(!1)}))),()=>{globalThis.apirtcReactLibLogLevel.isDebugEnabled&&console.debug(c+"|useEffect cleanup",e,o),e.isJoined()&&e.leave().then((()=>{d(!1)})).catch((e=>{globalThis.apirtcReactLibLogLevel.isWarnEnabled&&console.warn(c+"|useEffect conversation.leave()",e)}))}}}),[l,s]),{conversation:l,joining:g,joined:b,join:L,leave:p}}const d="useConversationMessages";function g(e){const[o]=n(new Array),[a,s]=n(new Array);t((()=>{if(e){const t=t=>{globalThis.apirtcReactLibLogLevel.isInfoEnabled&&console.info(d+"|on:message:",e.getName(),t),o.push(t),s(Array.from(o))};return e.on("message",t),()=>{e.removeListener("message",t),o.length=0,s(new Array)}}}),[e]);return{messages:a,sendMessage:i(((t,n)=>new Promise(((i,a)=>{null==e||e.sendMessage(t).then((a=>{globalThis.apirtcReactLibLogLevel.isInfoEnabled&&console.info(d+"|sentMessage",e.getName(),a,t),o.push({content:t,sender:n,time:new Date}),s(Array.from(o)),i()})).catch((e=>{globalThis.apirtcReactLibLogLevel.isWarnEnabled&&console.warn(d+"|sendMessage error",e),a(e)}))}))),[e])}}const u="useConversationModeration";function L(e,o,i){const[a,s]=n(new Set);return t((()=>{if(globalThis.apirtcReactLibLogLevel.isDebugEnabled&&console.debug(u+"|useEffect conversation",e),e){const t=e=>{globalThis.apirtcReactLibLogLevel.isInfoEnabled&&console.info(u+"|on:contactJoinedWaitingRoom",e),a.add(e),s(new Set(a))},n=e=>{globalThis.apirtcReactLibLogLevel.isInfoEnabled&&console.info(u+"|on:contactLeftWaitingRoom",e),a.delete(e),s(new Set(a))},l=e=>{globalThis.apirtcReactLibLogLevel.isInfoEnabled&&console.info(u+"|on:participantEjected",e),!0===e.self?(globalThis.apirtcReactLibLogLevel.isInfoEnabled&&console.info(u+"|Self participant was ejected"),i&&i()):o&&o(e.contact)};return e.on("contactJoinedWaitingRoom",t).on("contactLeftWaitingRoom",n).on("participantEjected",l),()=>{globalThis.apirtcReactLibLogLevel.isDebugEnabled&&console.debug(u+"|conversation clear",e),e.removeListener("contactJoinedWaitingRoom",t).removeListener("contactLeftWaitingRoom",n).removeListener("participantEjected",l),s(new Set)}}}),[e]),{candidates:a}}function p(e){return null!=e}const f="useConversationStreams";function h(e,o=[],a){globalThis.apirtcReactLibLogLevel.isDebugEnabled&&console.debug(`${f}|hook render`,o.map((e=>null==e?void 0:e.options)));const[s,l]=n([]),[r]=n(new Array),[c,b]=n(new Array),[d]=n(new Array),[g,u]=n(new Array),L=i(((o,t)=>new Promise(((n,i)=>{e&&(globalThis.apirtcReactLibLogLevel.isDebugEnabled&&console.debug(`${f}|publish|${e.getName()}`,o,t),e.publish(o,t).then((o=>{globalThis.apirtcReactLibLogLevel.isInfoEnabled&&console.info(`${f}|published|${e.getName()}`,o),r.push(o),b(Array.from(r)),n(o)})).catch((e=>{i(e)})))}))),[e]),h=i(((o,t)=>new Promise(((n,i)=>{if(e){globalThis.apirtcReactLibLogLevel.isDebugEnabled&&console.debug(`${f}|replacePublishedStream|${e.getName()}|${o.getId()} -> ${t.getId()}`);const a=e.getConversationCall(o);a&&a.replacePublishedStream(t).then((t=>{globalThis.apirtcReactLibLogLevel.isInfoEnabled&&console.info(`${f}|stream replaced|${e.getName()}`,o,t);const i=r.indexOf(o);i>=0&&(r.splice(i,1,t),b(Array.from(r))),n(t)})).catch((e=>{i(e)}))}}))),[e]),v=i((o=>{if(e){globalThis.apirtcReactLibLogLevel.isDebugEnabled&&console.debug(`${f}|unpublish|${e.getName()}`,o),e.unpublish(o);const t=r.indexOf(o);t>=0&&(r.splice(t,1),b(Array.from(r)))}}),[e]),m=i((()=>{const t=Math.max(s.length,o.length);globalThis.apirtcReactLibLogLevel.isDebugEnabled&&console.debug(f+"|doHandlePublication",o,JSON.stringify(s.map((e=>null==e?void 0:e.stream.getId()))),t);const n=o.map((e=>e&&e.options?{stream:e.stream,options:Object.assign({},e.options)}:e));l(n);const i=new Set(o.filter(p).map((e=>e.stream)));for(let l=0;l<t;l++){const t=s[l],r=o[l],c=e=>{L(e.stream,e.options).catch((e=>{n.splice(l,1,null),a?a(e):globalThis.apirtcReactLibLogLevel.isWarnEnabled&&console.warn(`${f}|publish|error`,e)}))};if(t&&r){const o=()=>{v(t.stream),c(r)};t.stream===r.stream?JSON.stringify(t.options)!==JSON.stringify(r.options)&&o():i.has(t.stream)?e&&!e.isPublishedStream(r.stream)&&c(r):e&&!e.isPublishedStream(r.stream)?JSON.stringify(t.options)===JSON.stringify(r.options)?h(t.stream,r.stream).catch((e=>{n.splice(l,1,null),a?a(e):globalThis.apirtcReactLibLogLevel.isWarnEnabled&&console.warn(`${f}|replacePublishedStream|error`,e)})):o():v(t.stream)}else t&&!r?i.has(t.stream)||v(t.stream):!t&&r&&e&&!e.isPublishedStream(r.stream)&&c(r)}}),[e,o,s,L,v,h]),E=e=>{r.forEach((o=>{globalThis.apirtcReactLibLogLevel.isDebugEnabled&&console.debug(f+"|unpublish stream",e,o),e.unpublish(o)})),r.length=0,l([]),d.forEach((o=>{globalThis.apirtcReactLibLogLevel.isDebugEnabled&&console.debug(f+"|unsubscribeToStream stream",e,o),e.unsubscribeToStream(o.getId())})),d.length=0,b(new Array),u(new Array)};return t((()=>{if(e){const o=e=>{globalThis.apirtcReactLibLogLevel.isInfoEnabled&&console.info(f+"|on_streamAdded",e),d.push(e),u(Array.from(d))},t=e=>{globalThis.apirtcReactLibLogLevel.isInfoEnabled&&console.info(f+"|on_streamRemoved",e);const o=d.indexOf(e);o>=0&&(d.splice(o,1),u(Array.from(d)))},n=o=>{const t=String(o.streamId);!0===o.isRemote&&("added"===o.listEventType?e.subscribeToStream(t):"removed"===o.listEventType&&e.unsubscribeToStream(t))};return e.on("streamAdded",o),e.on("streamRemoved",t),e.on("streamListChanged",n),()=>{e.removeListener("streamListChanged",n),e.removeListener("streamRemoved",t),e.removeListener("streamAdded",o),E(e)}}}),[e]),t((()=>{if(e){globalThis.apirtcReactLibLogLevel.isDebugEnabled&&console.debug(f+"|useEffect doHandlePublication",e.getName());const t=()=>{globalThis.apirtcReactLibLogLevel.isInfoEnabled&&console.info(f+"|on_joined",e.getName(),o),m()},n=()=>{globalThis.apirtcReactLibLogLevel.isInfoEnabled&&console.info(f+"|on_left",e.getName()),E(e)};return e.on("joined",t),e.on("left",n),()=>{e.removeListener("joined",t),e.removeListener("left",n)}}}),[m]),t((()=>{globalThis.apirtcReactLibLogLevel.isDebugEnabled&&console.debug(`${f}|useEffect streamsToPublish`,JSON.stringify(o.map((e=>(null==e?void 0:e.stream.getId())+"-"+JSON.stringify(null==e?void 0:e.options))))),e&&e.isJoined()&&m()}),[JSON.stringify(o.map((e=>(null==e?void 0:e.stream.getId())+"-"+JSON.stringify(null==e?void 0:e.options))))]),{publishedStreams:c,subscribedStreams:g,publish:L,unpublish:v,replacePublishedStream:h}}const v="usePresence";function m(e,o){const[i]=n(new Set),[a]=n(new Map),[s,l]=n(new Map);t((()=>{if(e)return()=>{a.clear(),l(new Map(a)),i.clear()}}),[e]);const r=e=>{var o;const t=null!==(o=a.get(e))&&void 0!==o?o:new Set;return a.has(e)||a.set(e,t),t};return t((()=>{if(globalThis.apirtcReactLibLogLevel.isDebugEnabled&&console.debug(v+"|useEffect session, groups",o),e){const t=e,n=new Set(o);n.forEach((e=>{i.has(e)||(globalThis.apirtcReactLibLogLevel.isInfoEnabled&&console.info(v+"|subscribeToGroup",e),i.add(e),t.subscribeToGroup(e))}));let s=!1;if(i.forEach((e=>{n.has(e)||(globalThis.apirtcReactLibLogLevel.isInfoEnabled&&console.info(v+"|unsubscribeToGroup",e),t.unsubscribeToGroup(e),i.delete(e),a.delete(e),s=!0)})),s&&l(new Map(a)),o.length>0){const e=e=>{globalThis.apirtcReactLibLogLevel.isDebugEnabled&&console.debug(v+"|contactListUpdate",e);let o=!1;for(const t of Object.keys(e.joinedGroup))if(n.has(t)){const n=r(t);for(const i of e.joinedGroup[t])n.add(i),o=!0}for(const t of Object.keys(e.leftGroup))if(n.has(t)){const n=r(t);for(const i of e.leftGroup[t])n.delete(i),o=!0,0===n.size&&a.delete(t)}for(const t of e.userDataChanged)for(const e of a.values())if(e.has(t)){o=!0;break}o&&l(new Map(a))};return t.on("contactListUpdate",e),()=>{t.removeListener("contactListUpdate",e)}}}}),[e,JSON.stringify(o)]),{contactsByGroup:s}}const E="useSession";function T(e,o,i){const[s,l]=n(),[r,c]=n(!1);t((()=>{if(globalThis.apirtcReactLibLogLevel.isDebugEnabled&&console.debug(E+"|useEffect credentials, options",e,o),e)return b(e,o).catch((e=>{console.error(E+"|connection failed",e),l(void 0),i?i(e):globalThis.apirtcReactLibLogLevel.isWarnEnabled&&console.warn(`${E}|connect|error`,e)})),()=>{l(void 0),c(!1)}}),[JSON.stringify(e),JSON.stringify(o)]),t((()=>{if(globalThis.apirtcReactLibLogLevel.isDebugEnabled&&console.debug(E+"|useEffect session",s),s){const e=s;return()=>{e.disconnect().then((()=>{globalThis.apirtcReactLibLogLevel.isInfoEnabled&&console.info(E+"|disconnected",e)})).catch((e=>{console.error(E+"|disconnect",e)}))}}}),[s]);const b=(e,o)=>new Promise(((t,n)=>{const i=o||{cloudUrl:"https://cloud.apirtc.com"};let s;if("object"==typeof(r=e)&&"username"in r)i.password=e.password,s=new a({uri:"apirtc:"+e.username});else if(function(e){return"object"==typeof e&&"apiKey"in e}(e))s=new a({uri:`apiKey:${e.apiKey}`});else{if(!function(e){return"object"==typeof e&&"token"in e}(e))return void n("credentials not recognized");s=new a({uri:`token:${e.token}`})}var r;c(!0),s.register(i).then((e=>{globalThis.apirtcReactLibLogLevel.isInfoEnabled&&console.info(E+"|connected",e),l(e),t()})).catch((e=>{n(e)})).finally((()=>{c(!1)}))}));return{session:s,connecting:r,connect:b,disconnect:()=>{l(void 0)}}}const R="useStreamApplyVideoProcessor";function I(e,o,i,a){const[s,l]=n(e),[r,c]=n(e?e.videoAppliedFilter:"none");return t((()=>{globalThis.apirtcReactLibLogLevel.isDebugEnabled&&console.debug(R+"|useEffect",e,o,i,e?JSON.stringify(e.children):"empty"),e?e.applyVideoProcessor(o,i).then((e=>{l(e),c(o)})).catch((t=>{l(e),c(e.videoAppliedFilter),a?a(t):globalThis.apirtcReactLibLogLevel.isWarnEnabled&&console.warn(R+"|useEffect",e,o,i,t)})):(l(e),c("none"))}),[e,o,JSON.stringify(i)]),{stream:s,applied:r}}const S={audioinput:{},audiooutput:{},videoinput:{}},y="useUserMediaDevices";function w(e,o="apirtc"){const[i,a]=n(S),[s,l]=n(),[r,c]=n(),[b,d]=n(),g=o+"audioInputId",u=o+"audioOutputId",L=o+"videoInputId";return t((()=>{if(e){const o=e.getUserAgent(),t=()=>{const e=o.getUserMediaDevices();globalThis.apirtcReactLibLogLevel.isInfoEnabled&&console.info(y+"|mediaDeviceChanged",e),a(e)};return o.on("mediaDeviceChanged",t),()=>{o.removeListener("mediaDeviceChanged",t),a(S)}}}),[e]),t((()=>{const e=localStorage.getItem(g),o=localStorage.getItem(u),t=localStorage.getItem(L);globalThis.apirtcReactLibLogLevel.isDebugEnabled&&console.debug(y+"|userMediaDevices, audioInputId, audioOutputId, videoInputId",i,e,o,t),e&&i.audioinput[e]&&l(i.audioinput[e]),o&&i.audiooutput[o]&&c(i.audiooutput[o]),t&&i.videoinput[t]&&d(i.videoinput[t])}),[i]),t((()=>{s&&(globalThis.apirtcReactLibLogLevel.isDebugEnabled&&console.debug(y+"|Storing audioInputId",s.getId()),localStorage.setItem(g,s.getId()))}),[s]),t((()=>{r&&(globalThis.apirtcReactLibLogLevel.isDebugEnabled&&console.debug(y+"|Storing audioOutputId",r.getId()),localStorage.setItem(u,r.getId()))}),[r]),t((()=>{b&&(globalThis.apirtcReactLibLogLevel.isDebugEnabled&&console.debug(y+"|Storing videoInputId",b.getId()),localStorage.setItem(L,b.getId()))}),[b]),{userMediaDevices:i,selectedAudioIn:s,setSelectedAudioIn:l,selectedAudioOut:r,setSelectedAudioOut:c,selectedVideoIn:b,setSelectedVideoIn:d}}const D={level:"info",isDebugEnabled:!1,isInfoEnabled:!0,isWarnEnabled:!0};function A(e){switch(e){case"debug":globalThis.apirtcReactLibLogLevel={level:"debug",isDebugEnabled:!0,isInfoEnabled:!0,isWarnEnabled:!0};break;case"info":default:globalThis.apirtcReactLibLogLevel=D;break;case"warn":globalThis.apirtcReactLibLogLevel={level:"warn",isDebugEnabled:!1,isInfoEnabled:!1,isWarnEnabled:!0};break;case"error":globalThis.apirtcReactLibLogLevel={level:"error",isDebugEnabled:!1,isInfoEnabled:!1,isWarnEnabled:!1}}return globalThis.apirtcReactLibLogLevel}globalThis.apirtcReactLibLogLevel=D,globalThis.setApirtcReactLibLogLevel=A;export{s as VideoStream,A as setLogLevel,r as useCameraStream,b as useConversation,g as useConversationMessages,L as useConversationModeration,h as useConversationStreams,m as usePresence,T as useSession,I as useStreamApplyVideoProcessor,w as useUserMediaDevices};
|
|
1
|
+
import e,{useRef as o,useEffect as t,useState as n,useCallback as i}from"react";import{UserAgent as a,MediaDevice as s}from"@apirtc/apirtc";function l(n){const{autoPlay:i=!0}=n,a=o(null);return t((()=>{const e=a.current;if(e&&n.stream)return n.stream.attachToElement(e),()=>{e.src=""}}),[n.stream]),e.createElement("video",{id:n.stream.getId(),style:{maxWidth:"100%"},ref:a,autoPlay:i,muted:n.muted})}const r="useCameraStream";function c(e,o={}){const[i,a]=n();return t((()=>{if(e){e.getUserAgent().createStream(o).then((e=>{globalThis.apirtcReactLibLogLevel.isInfoEnabled&&console.info(r+"|createStream",o,e),a(e)})).catch((e=>{console.error(r+"|createStream",o,e),a(void 0)}))}else a(void 0)}),[e,JSON.stringify(o)]),t((()=>()=>{i&&(globalThis.apirtcReactLibLogLevel.isInfoEnabled&&console.info(r+"|release stream",i),i.release())}),[i]),{stream:i}}const b="useConversation";function d(e,o,a,s=!0){const[l,r]=n(),[c,d]=n(!1),[g,u]=n(!1),L=i((()=>(globalThis.apirtcReactLibLogLevel.isDebugEnabled&&console.debug(b+"|join",l),new Promise(((e,o)=>{l?l.isJoined()?o(b+"|join|conversation already joined"):(u(!0),l.join().then((()=>{d(!0),e()})).catch((e=>{o(e)})).finally((()=>{u(!1)}))):o(b+"|join|conversation not defined")})))),[l]),p=i((()=>(globalThis.apirtcReactLibLogLevel.isDebugEnabled&&console.debug(b+"|leave",l),new Promise(((e,o)=>{l?l.isJoined()?l.leave().then((()=>{d(!1),e()})).catch((e=>{o(e)})):o(b+"|leave|conversation is not joined"):o(b+"|leave|conversation not defined")})))),[l]);return t((()=>{if(e&&o){globalThis.apirtcReactLibLogLevel.isDebugEnabled&&console.debug(b+"|getOrCreateConversation",o,a,s);const t=e.getOrCreateConversation(o,a);return r(t),()=>{globalThis.apirtcReactLibLogLevel.isDebugEnabled&&console.debug(b+"|useEffect cleanup",o,a,s),t.isJoined()?t.leave().then((()=>{})).catch((e=>{globalThis.apirtcReactLibLogLevel.isWarnEnabled&&console.warn(b+"|useEffect conversation.leave()",e)})).finally((()=>{t.destroy()})):t.destroy(),r(void 0),d(!1)}}}),[e,o,JSON.stringify(a)]),t((()=>{if(l&&s){globalThis.apirtcReactLibLogLevel.isDebugEnabled&&console.debug(b+"|useEffect",l,s);const e=l,o=s;return o&&(u(!0),e.join().then((()=>{globalThis.apirtcReactLibLogLevel.isInfoEnabled&&console.info(b+"|joined",e),d(!0)})).catch((e=>{globalThis.apirtcReactLibLogLevel.isWarnEnabled&&console.warn(b+"|useEffect conversation.join()",e)})).finally((()=>{u(!1)}))),()=>{globalThis.apirtcReactLibLogLevel.isDebugEnabled&&console.debug(b+"|useEffect cleanup",e,o),e.isJoined()&&e.leave().then((()=>{d(!1)})).catch((e=>{globalThis.apirtcReactLibLogLevel.isWarnEnabled&&console.warn(b+"|useEffect conversation.leave()",e)}))}}}),[l,s]),{conversation:l,joining:g,joined:c,join:L,leave:p}}const g="useConversationMessages";function u(e){const[o]=n(new Array),[a,s]=n(new Array);t((()=>{if(e){const t=t=>{globalThis.apirtcReactLibLogLevel.isInfoEnabled&&console.info(g+"|on:message:",e.getName(),t),o.push(t),s(Array.from(o))};return e.on("message",t),()=>{e.removeListener("message",t),o.length=0,s(new Array)}}}),[e]);return{messages:a,sendMessage:i(((t,n)=>new Promise(((i,a)=>{null==e||e.sendMessage(t).then((a=>{globalThis.apirtcReactLibLogLevel.isInfoEnabled&&console.info(g+"|sentMessage",e.getName(),a,t),o.push({content:t,sender:n,time:new Date}),s(Array.from(o)),i()})).catch((e=>{globalThis.apirtcReactLibLogLevel.isWarnEnabled&&console.warn(g+"|sendMessage error",e),a(e)}))}))),[e])}}const L="useConversationModeration";function p(e,o,i){const[a,s]=n(new Set);return t((()=>{if(globalThis.apirtcReactLibLogLevel.isDebugEnabled&&console.debug(L+"|useEffect conversation",e),e){const t=e=>{globalThis.apirtcReactLibLogLevel.isInfoEnabled&&console.info(L+"|on:contactJoinedWaitingRoom",e),a.add(e),s(new Set(a))},n=e=>{globalThis.apirtcReactLibLogLevel.isInfoEnabled&&console.info(L+"|on:contactLeftWaitingRoom",e),a.delete(e),s(new Set(a))},l=e=>{globalThis.apirtcReactLibLogLevel.isInfoEnabled&&console.info(L+"|on:participantEjected",e),!0===e.self?(globalThis.apirtcReactLibLogLevel.isInfoEnabled&&console.info(L+"|Self participant was ejected"),i&&i()):o&&o(e.contact)};return e.on("contactJoinedWaitingRoom",t).on("contactLeftWaitingRoom",n).on("participantEjected",l),()=>{globalThis.apirtcReactLibLogLevel.isDebugEnabled&&console.debug(L+"|conversation clear",e),e.removeListener("contactJoinedWaitingRoom",t).removeListener("contactLeftWaitingRoom",n).removeListener("participantEjected",l),s(new Set)}}}),[e]),{candidates:a}}function f(e){return null!=e}const v="useConversationStreams";function h(e,o=[],a){globalThis.apirtcReactLibLogLevel.isDebugEnabled&&console.debug(`${v}|hook render`,o.map((e=>null==e?void 0:e.options)));const[s,l]=n([]),[r]=n(new Array),[c,b]=n(new Array),[d]=n(new Array),[g,u]=n(new Array),L=i(((o,t)=>new Promise(((n,i)=>{e&&(globalThis.apirtcReactLibLogLevel.isDebugEnabled&&console.debug(`${v}|publish|${e.getName()}`,o,t),e.publish(o,t).then((o=>{globalThis.apirtcReactLibLogLevel.isInfoEnabled&&console.info(`${v}|published|${e.getName()}`,o),r.push(o),b(Array.from(r)),n(o)})).catch((e=>{i(e)})))}))),[e]),p=i(((o,t)=>new Promise(((n,i)=>{if(e){globalThis.apirtcReactLibLogLevel.isDebugEnabled&&console.debug(`${v}|replacePublishedStream|${e.getName()}|${o.getId()} -> ${t.getId()}`);const a=e.getConversationCall(o);a&&a.replacePublishedStream(t).then((t=>{globalThis.apirtcReactLibLogLevel.isInfoEnabled&&console.info(`${v}|stream replaced|${e.getName()}`,o,t);const i=r.indexOf(o);i>=0&&(r.splice(i,1,t),b(Array.from(r))),n(t)})).catch((e=>{i(e)}))}}))),[e]),h=i((o=>{if(e){globalThis.apirtcReactLibLogLevel.isDebugEnabled&&console.debug(`${v}|unpublish|${e.getName()}`,o),e.unpublish(o);const t=r.indexOf(o);t>=0&&(r.splice(t,1),b(Array.from(r)))}}),[e]),m=i((()=>{const t=Math.max(s.length,o.length);globalThis.apirtcReactLibLogLevel.isDebugEnabled&&console.debug(v+"|doHandlePublication",o,JSON.stringify(s.map((e=>null==e?void 0:e.stream.getId()))),t);const n=o.map((e=>e&&e.options?{stream:e.stream,options:Object.assign({},e.options)}:e));l(n);const i=new Set(o.filter(f).map((e=>e.stream)));for(let l=0;l<t;l++){const t=s[l],r=o[l],c=e=>{L(e.stream,e.options).catch((e=>{n.splice(l,1,null),a?a(e):globalThis.apirtcReactLibLogLevel.isWarnEnabled&&console.warn(`${v}|publish|error`,e)}))};if(t&&r){const o=()=>{h(t.stream),c(r)};t.stream===r.stream?JSON.stringify(t.options)!==JSON.stringify(r.options)&&o():i.has(t.stream)?e&&!e.isPublishedStream(r.stream)&&c(r):e&&!e.isPublishedStream(r.stream)?JSON.stringify(t.options)===JSON.stringify(r.options)?p(t.stream,r.stream).catch((e=>{n.splice(l,1,null),a?a(e):globalThis.apirtcReactLibLogLevel.isWarnEnabled&&console.warn(`${v}|replacePublishedStream|error`,e)})):o():h(t.stream)}else t&&!r?i.has(t.stream)||h(t.stream):!t&&r&&e&&!e.isPublishedStream(r.stream)&&c(r)}}),[e,o,s,L,h,p]),E=e=>{r.forEach((o=>{globalThis.apirtcReactLibLogLevel.isDebugEnabled&&console.debug(v+"|unpublish stream",e,o),e.unpublish(o)})),r.length=0,l([]),d.forEach((o=>{globalThis.apirtcReactLibLogLevel.isDebugEnabled&&console.debug(v+"|unsubscribeToStream stream",e,o),e.unsubscribeToStream(o.getId())})),d.length=0,b(new Array),u(new Array)};return t((()=>{if(e){const o=e=>{globalThis.apirtcReactLibLogLevel.isInfoEnabled&&console.info(v+"|on_streamAdded",e),d.push(e),u(Array.from(d))},t=e=>{globalThis.apirtcReactLibLogLevel.isInfoEnabled&&console.info(v+"|on_streamRemoved",e);const o=d.indexOf(e);o>=0&&(d.splice(o,1),u(Array.from(d)))},n=o=>{const t=String(o.streamId);!0===o.isRemote&&("added"===o.listEventType?e.subscribeToStream(t):"removed"===o.listEventType&&e.unsubscribeToStream(t))};return e.on("streamAdded",o),e.on("streamRemoved",t),e.on("streamListChanged",n),()=>{e.removeListener("streamListChanged",n),e.removeListener("streamRemoved",t),e.removeListener("streamAdded",o),E(e)}}}),[e]),t((()=>{if(e){globalThis.apirtcReactLibLogLevel.isDebugEnabled&&console.debug(v+"|useEffect doHandlePublication",e.getName());const t=()=>{globalThis.apirtcReactLibLogLevel.isInfoEnabled&&console.info(v+"|on_joined",e.getName(),o),m()},n=()=>{globalThis.apirtcReactLibLogLevel.isInfoEnabled&&console.info(v+"|on_left",e.getName()),E(e)};return e.on("joined",t),e.on("left",n),()=>{e.removeListener("joined",t),e.removeListener("left",n)}}}),[m]),t((()=>{globalThis.apirtcReactLibLogLevel.isDebugEnabled&&console.debug(`${v}|useEffect streamsToPublish`,JSON.stringify(o.map((e=>(null==e?void 0:e.stream.getId())+"-"+JSON.stringify(null==e?void 0:e.options))))),e&&e.isJoined()&&m()}),[JSON.stringify(o.map((e=>(null==e?void 0:e.stream.getId())+"-"+JSON.stringify(null==e?void 0:e.options))))]),{publishedStreams:c,subscribedStreams:g,publish:L,unpublish:h,replacePublishedStream:p}}const m="usePresence";function E(e,o){const[i]=n(new Set),[a]=n(new Map),[s,l]=n(new Map);t((()=>{if(e)return()=>{a.clear(),l(new Map(a)),i.clear()}}),[e]);const r=e=>{var o;const t=null!==(o=a.get(e))&&void 0!==o?o:new Set;return a.has(e)||a.set(e,t),t};return t((()=>{if(globalThis.apirtcReactLibLogLevel.isDebugEnabled&&console.debug(m+"|useEffect session, groups",o),e){const t=e,n=new Set(o);n.forEach((e=>{i.has(e)||(globalThis.apirtcReactLibLogLevel.isInfoEnabled&&console.info(m+"|subscribeToGroup",e),i.add(e),t.subscribeToGroup(e))}));let s=!1;if(i.forEach((e=>{n.has(e)||(globalThis.apirtcReactLibLogLevel.isInfoEnabled&&console.info(m+"|unsubscribeToGroup",e),t.unsubscribeToGroup(e),i.delete(e),a.delete(e),s=!0)})),s&&l(new Map(a)),o.length>0){const e=e=>{globalThis.apirtcReactLibLogLevel.isDebugEnabled&&console.debug(m+"|contactListUpdate",e);let o=!1;for(const t of Object.keys(e.joinedGroup))if(n.has(t)){const n=r(t);for(const i of e.joinedGroup[t])n.add(i),o=!0}for(const t of Object.keys(e.leftGroup))if(n.has(t)){const n=r(t);for(const i of e.leftGroup[t])n.delete(i),o=!0,0===n.size&&a.delete(t)}for(const t of e.userDataChanged)for(const e of a.values())if(e.has(t)){o=!0;break}o&&l(new Map(a))};return t.on("contactListUpdate",e),()=>{t.removeListener("contactListUpdate",e)}}}}),[e,JSON.stringify(o)]),{contactsByGroup:s}}const T="useSession";function R(e,o,i){const[s,l]=n(),[r,c]=n(!1);t((()=>{if(globalThis.apirtcReactLibLogLevel.isDebugEnabled&&console.debug(T+"|useEffect credentials, options",e,o),e)return b(e,o).catch((e=>{console.error(T+"|connection failed",e),l(void 0),i?i(e):globalThis.apirtcReactLibLogLevel.isWarnEnabled&&console.warn(`${T}|connect|error`,e)})),()=>{l(void 0),c(!1)}}),[JSON.stringify(e),JSON.stringify(o)]),t((()=>{if(globalThis.apirtcReactLibLogLevel.isDebugEnabled&&console.debug(T+"|useEffect session",s),s){const e=s;return()=>{e.disconnect().then((()=>{globalThis.apirtcReactLibLogLevel.isInfoEnabled&&console.info(T+"|disconnected",e)})).catch((e=>{console.error(T+"|disconnect",e)}))}}}),[s]);const b=(e,o)=>new Promise(((t,n)=>{const i=o||{cloudUrl:"https://cloud.apirtc.com"};let s;if("object"==typeof(r=e)&&"username"in r)i.password=e.password,s=new a({uri:"apirtc:"+e.username});else if(function(e){return"object"==typeof e&&"apiKey"in e}(e))s=new a({uri:`apiKey:${e.apiKey}`});else{if(!function(e){return"object"==typeof e&&"token"in e}(e))return void n("credentials not recognized");s=new a({uri:`token:${e.token}`})}var r;c(!0),s.register(i).then((e=>{globalThis.apirtcReactLibLogLevel.isInfoEnabled&&console.info(T+"|connected",e),l(e),t()})).catch((e=>{n(e)})).finally((()=>{c(!1)}))}));return{session:s,connecting:r,connect:b,disconnect:()=>{l(void 0)}}}const y="useStreamApplyVideoProcessor";function S(e,o,i,a){const[s,l]=n(e),[r,c]=n(e?e.videoAppliedFilter:"none");return t((()=>{globalThis.apirtcReactLibLogLevel.isDebugEnabled&&console.debug(y+"|useEffect",e,o,i,e?JSON.stringify(e.children):"empty"),e?e.applyVideoProcessor(o,i).then((e=>{l(e),c(o)})).catch((t=>{l(e),c(e.videoAppliedFilter),a?a(t):globalThis.apirtcReactLibLogLevel.isWarnEnabled&&console.warn(y+"|useEffect",e,o,i,t)})):(l(e),c("none"))}),[e,o,JSON.stringify(i)]),{stream:s,applied:r}}const I={audioinput:{},audiooutput:{},videoinput:{}},w=e=>{const o=localStorage.getItem(e),t=o?JSON.parse(o):null;return t?new s(t.id,t.type,t.label):void 0},D="useUserMediaDevices";function O(e,o="apirtc"){const[i,a]=n(I),s=o+".audioIn",l=o+".audioOut",r=o+".videoIn",[c,b]=n(w(s)),[d,g]=n(w(l)),[u,L]=n(w(r));return t((()=>{if(e){const o=e.getUserAgent(),t=()=>{const e=o.getUserMediaDevices();globalThis.apirtcReactLibLogLevel.isInfoEnabled&&console.info(D+"|mediaDeviceChanged",e),a(e)};return o.on("mediaDeviceChanged",t),()=>{o.removeListener("mediaDeviceChanged",t),a(I)}}}),[e]),t((()=>{if(i!==I){const e=localStorage.getItem(s),o=e?JSON.parse(e).id:void 0;o&&b(i.audioinput[o]);const t=localStorage.getItem(l),n=t?JSON.parse(t).id:void 0;n&&g(i.audiooutput[n]);const a=localStorage.getItem(r),c=a?JSON.parse(a).id:void 0;c&&L(i.videoinput[c]),globalThis.apirtcReactLibLogLevel.isDebugEnabled&&console.debug(D+"|userMediaDevices, audioInputId, audioOutputId, videoInputId",i,o,n,c)}}),[i]),t((()=>{c&&(globalThis.apirtcReactLibLogLevel.isDebugEnabled&&console.debug(D+"|Storing audioInput",c),localStorage.setItem(s,JSON.stringify({id:c.getId(),type:c.getType(),label:c.getLabel()})))}),[null==c?void 0:c.getId()]),t((()=>{d&&(globalThis.apirtcReactLibLogLevel.isDebugEnabled&&console.debug(D+"|Storing audioOutput",d),localStorage.setItem(l,JSON.stringify({id:d.getId(),type:d.getType(),label:d.getLabel()})))}),[null==d?void 0:d.getId()]),t((()=>{u&&(globalThis.apirtcReactLibLogLevel.isDebugEnabled&&console.debug(D+"|Storing VideoInput",u),localStorage.setItem(r,JSON.stringify({id:u.getId(),type:u.getType(),label:u.getLabel()})))}),[null==u?void 0:u.getId()]),{userMediaDevices:i,selectedAudioIn:c,setSelectedAudioIn:b,selectedAudioOut:d,setSelectedAudioOut:g,selectedVideoIn:u,setSelectedVideoIn:L}}const N={level:"info",isDebugEnabled:!1,isInfoEnabled:!0,isWarnEnabled:!0};function J(e){switch(e){case"debug":globalThis.apirtcReactLibLogLevel={level:"debug",isDebugEnabled:!0,isInfoEnabled:!0,isWarnEnabled:!0};break;case"info":default:globalThis.apirtcReactLibLogLevel=N;break;case"warn":globalThis.apirtcReactLibLogLevel={level:"warn",isDebugEnabled:!1,isInfoEnabled:!1,isWarnEnabled:!0};break;case"error":globalThis.apirtcReactLibLogLevel={level:"error",isDebugEnabled:!1,isInfoEnabled:!1,isWarnEnabled:!1}}return globalThis.apirtcReactLibLogLevel}globalThis.apirtcReactLibLogLevel=N,globalThis.setApirtcReactLibLogLevel=J;export{l as VideoStream,J as setLogLevel,c as useCameraStream,d as useConversation,u as useConversationMessages,p as useConversationModeration,h as useConversationStreams,E as usePresence,R as useSession,S as useStreamApplyVideoProcessor,O as useUserMediaDevices};
|
|
2
2
|
//# sourceMappingURL=index.js.map
|
package/dist/esm/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../../src/components/VideoStream/VideoStream.tsx","../../src/hooks/useCameraStream.ts","../../src/hooks/useConversation.ts","../../src/hooks/useConversationMessages.ts","../../src/hooks/useConversationModeration.ts","../../src/hooks/useConversationStreams.ts","../../src/hooks/usePresence.ts","../../src/hooks/useSession.ts","../../src/hooks/useStreamApplyVideoProcessor.ts","../../src/hooks/useUserMediaDevices.ts","../../src/index.ts"],"sourcesContent":["import React, { useEffect, useRef } from 'react';\n\nimport { Stream } from '@apirtc/apirtc';\n\nexport type VideoStreamProps = {\n stream: Stream,\n autoPlay?: boolean,\n muted?: boolean\n};\nexport default function VideoStream(props: VideoStreamProps) {\n\n const { autoPlay = true } = props;\n\n const videoRef = useRef<HTMLVideoElement>(null)\n\n useEffect(() => {\n const ref = videoRef.current;\n if (ref && props.stream) {\n props.stream.attachToElement(ref)\n return () => {\n ref.src = \"\";\n }\n }\n }, [props.stream])\n // No need to put videoRef.current because useRef does not trigger rerender anyways\n\n return <video id={props.stream.getId()} style={{ maxWidth: '100%' }}\n ref={videoRef}\n autoPlay={autoPlay}\n muted={props.muted}></video>\n}","import { CreateStreamOptions, Session, Stream, UserAgent } from '@apirtc/apirtc';\nimport { useEffect, useState } from 'react';\n\nconst HOOK_NAME = \"useCameraStream\";\nexport default function useCameraStream(\n session: Session | undefined,\n options: CreateStreamOptions = {}\n) {\n const [stream, setStream] = useState<Stream>();\n\n useEffect(() => {\n if (session) {\n const userAgent: UserAgent = session.getUserAgent();\n userAgent.createStream(options).then((localStream: Stream) => {\n if (globalThis.apirtcReactLibLogLevel.isInfoEnabled) {\n console.info(HOOK_NAME + \"|createStream\", options, localStream)\n }\n setStream(localStream)\n }).catch((error: any) => {\n console.error(HOOK_NAME + \"|createStream\", options, error)\n setStream(undefined)\n })\n\n // DO NOT set out stream to undefined in the return, to prevent unnecessary refreshes\n // of other components with undefined stream, whereas we are expecting to change it\n // to another instance..\n // return () => { setStream(undefined) } // DON'T\n } else {\n setStream(undefined)\n }\n\n }, [session, JSON.stringify(options)])\n\n useEffect(() => {\n return () => {\n if (stream) {\n if (globalThis.apirtcReactLibLogLevel.isInfoEnabled) {\n console.info(HOOK_NAME + \"|release stream\", stream)\n }\n stream.release()\n }\n }\n }, [stream])\n\n return {\n stream\n }\n}","import { Conversation, GetOrCreateConversationOptions, Session } from '@apirtc/apirtc';\nimport { useCallback, useEffect, useState } from 'react';\n\nconst HOOK_NAME = \"useConversation\";\n/**\n * A hook to getOrCreate a named conversation and manage join/leave\n * @param session an ApiRTC Session\n * @param name the conversation name\n * @param options getOrCreateConversation options\n * @param join true by default.\n */\nexport default function useConversation(\n session: Session | undefined,\n name: string | undefined,\n options?: GetOrCreateConversationOptions,\n join: boolean = true\n) {\n const [conversation, setConversation] = useState<Conversation>();\n const [joined, setJoined] = useState<boolean>(false);\n const [joining, setJoining] = useState<boolean>(false);\n\n // Callbacks\n //\n // Offering Promised join/leave methods allows developer to act on then/catch\n //\n const o_join = useCallback(() => {\n if (globalThis.apirtcReactLibLogLevel.isDebugEnabled) {\n console.debug(HOOK_NAME + \"|join\", conversation)\n //JSON.stringify((apiRTC as any).session.apiCCWebRTCClient.webRTCClient.MCUClient.sessionMCUs))\n }\n return new Promise<void>((resolve, reject) => {\n if (!conversation) {\n reject(HOOK_NAME + \"|join|conversation not defined\")\n return\n }\n if (!conversation.isJoined()) {\n setJoining(true)\n conversation.join().then(() => {\n // successfully joined the conversation.\n setJoined(true)\n resolve()\n }).catch((error: any) => {\n // could not join the conversation.\n reject(error)\n }).finally(() => {\n setJoining(false)\n })\n } else {\n reject(HOOK_NAME + \"|join|conversation already joined\")\n }\n })\n }, [conversation]);\n\n const o_leave = useCallback(() => {\n if (globalThis.apirtcReactLibLogLevel.isDebugEnabled) {\n console.debug(HOOK_NAME + \"|leave\", conversation)\n }\n return new Promise<void>((resolve, reject) => {\n if (!conversation) {\n reject(HOOK_NAME + \"|leave|conversation not defined\")\n return\n }\n if (conversation.isJoined()) {\n conversation.leave().then(() => {\n // local user successfully left the conversation.\n setJoined(false)\n resolve()\n }).catch((error: any) => {\n reject(error)\n })\n } else {\n reject(HOOK_NAME + \"|leave|conversation is not joined\")\n }\n })\n }, [conversation]);\n\n // Effects\n //\n useEffect(() => {\n if (session && name) {\n if (globalThis.apirtcReactLibLogLevel.isDebugEnabled) {\n console.debug(HOOK_NAME + \"|getOrCreateConversation\", name, options, join)\n }\n const l_conversation = session.getOrCreateConversation(name, options);\n setConversation(l_conversation)\n return () => {\n if (globalThis.apirtcReactLibLogLevel.isDebugEnabled) {\n console.debug(HOOK_NAME + \"|useEffect cleanup\", name, options, join)\n }\n if (l_conversation.isJoined()) {\n l_conversation.leave()\n .then(() => { })\n .catch((error: any) => {\n if (globalThis.apirtcReactLibLogLevel.isWarnEnabled) {\n console.warn(HOOK_NAME + \"|useEffect conversation.leave()\", error)\n }\n })\n .finally(() => {\n l_conversation.destroy()\n // SHOULD NOT touch the state here as this async and the conversation may have already changed\n })\n } else {\n // It is important to destroy the conversation.\n // Otherwise subsequent getOrCreateConversation with same name would get\n // previous handle, regardless of the potentially new options.\n // This also allows to cleanup memory\n l_conversation.destroy()\n }\n // In any cases, update state accordingly\n // Note: this is done here synchronously, this shall NOT be done in the leave().finally to prevent\n // overriding a potential conversation change\n setConversation(undefined)\n setJoined(false)\n }\n }\n }, [session, name, JSON.stringify(options)])\n\n useEffect(() => {\n if (conversation && join) {\n if (globalThis.apirtcReactLibLogLevel.isDebugEnabled) {\n console.debug(HOOK_NAME + \"|useEffect\", conversation, join)\n }\n const l_conversation = conversation;\n const l_join = join;\n if (l_join) {\n setJoining(true)\n l_conversation.join().then(() => {\n if (globalThis.apirtcReactLibLogLevel.isInfoEnabled) {\n console.info(HOOK_NAME + \"|joined\", l_conversation)\n }\n setJoined(true)\n }).catch((error: any) => {\n if (globalThis.apirtcReactLibLogLevel.isWarnEnabled) {\n console.warn(HOOK_NAME + \"|useEffect conversation.join()\", error)\n }\n }).finally(() => {\n setJoining(false)\n })\n }\n return () => {\n if (globalThis.apirtcReactLibLogLevel.isDebugEnabled) {\n console.debug(HOOK_NAME + \"|useEffect cleanup\", l_conversation, l_join)\n }\n if (l_conversation.isJoined()) {\n l_conversation.leave().then(() => {\n setJoined(false)\n }).catch((error: any) => {\n if (globalThis.apirtcReactLibLogLevel.isWarnEnabled) {\n console.warn(HOOK_NAME + \"|useEffect conversation.leave()\", error)\n }\n })\n }\n }\n }\n }, [conversation, join])\n\n return {\n conversation,\n joining,\n joined,\n join: o_join,\n leave: o_leave\n }\n}","import { Contact, Conversation, ConversationMessage } from '@apirtc/apirtc';\nimport { useCallback, useEffect, useState } from 'react';\n\n// TODO : get and handle with pagination messages history\n// TODO : ask apirtc to include the uuid in ConversationMessage so that we can store it\n// into ConversationMessage when creating the local one, and we get it from conversation on:message\n// the uuid shall be the value used as a react child key when displaying list of messages\n\nconst HOOK_NAME = \"useConversationMessages\";\nexport default function useConversationMessages(\n conversation: Conversation | undefined,\n) {\n // Use an internal array which will always be the same object as far as React knows\n // This will avoid the need for adding it as a dependency for each callback\n const [messages] = useState<Array<ConversationMessage>>(new Array<ConversationMessage>());\n // And use a copy as output array so that client code will react upon change\n // (only a new instance of array is detected by React)\n const [o_messages, setO_Messages] = useState<Array<ConversationMessage>>(new Array<ConversationMessage>());\n\n useEffect(() => {\n if (conversation) {\n const onMessage = (message: ConversationMessage) => {\n if (globalThis.apirtcReactLibLogLevel.isInfoEnabled) {\n console.info(HOOK_NAME + \"|on:message:\", conversation.getName(), message)\n }\n messages.push(message)\n setO_Messages(Array.from(messages))\n };\n conversation.on('message', onMessage)\n\n return () => {\n conversation.removeListener('message', onMessage)\n messages.length = 0;\n setO_Messages(new Array<any>())\n }\n }\n }, [conversation])\n\n const sendMessage = useCallback((msgContent: string, sender: Contact) => {\n return new Promise<void>((resolve, reject) => {\n conversation?.sendMessage(msgContent)\n .then((uuid: number) => {\n if (globalThis.apirtcReactLibLogLevel.isInfoEnabled) {\n console.info(HOOK_NAME + \"|sentMessage\", conversation.getName(), uuid, msgContent)\n }\n messages.push({ content: msgContent, sender: sender, time: new Date() })\n setO_Messages(Array.from(messages))\n resolve()\n })\n .catch((error: any) => {\n if (globalThis.apirtcReactLibLogLevel.isWarnEnabled) {\n console.warn(HOOK_NAME + \"|sendMessage error\", error)\n }\n reject(error)\n })\n })\n }, [conversation]);\n\n return {\n messages: o_messages,\n sendMessage\n }\n}","import { Contact, Conversation } from '@apirtc/apirtc';\nimport { useEffect, useState } from 'react';\n\nconst HOOK_NAME = \"useConversationModeration\";\nexport default function useConversationModeration(\n conversation: Conversation | undefined,\n onEjected?: (contact: Contact) => void,\n onEjectedSelf?: () => void) {\n\n const [candidates, setCandidates] = useState<Set<Contact>>(new Set<Contact>());\n\n useEffect(() => {\n if (globalThis.apirtcReactLibLogLevel.isDebugEnabled) {\n console.debug(HOOK_NAME + \"|useEffect conversation\", conversation)\n }\n\n if (conversation) {\n const on_contactJoinedWaitingRoom = (contact: Contact) => {\n if (globalThis.apirtcReactLibLogLevel.isInfoEnabled) {\n console.info(HOOK_NAME + \"|on:contactJoinedWaitingRoom\", contact)\n }\n // A candidate joined the waiting room.\n candidates.add(contact)\n setCandidates(new Set(candidates))\n };\n const on_contactLeftWaitingRoom = (contact: Contact) => {\n if (globalThis.apirtcReactLibLogLevel.isInfoEnabled) {\n console.info(HOOK_NAME + \"|on:contactLeftWaitingRoom\", contact)\n }\n // A candidate left the waiting room.\n candidates.delete(contact)\n setCandidates(new Set(candidates))\n };\n // TODO make apirtc.d.ts update to replace 'any'\n const on_participantEjected = (data: any) => {\n if (globalThis.apirtcReactLibLogLevel.isInfoEnabled) {\n console.info(HOOK_NAME + \"|on:participantEjected\", data)\n }\n if (data.self === true) {\n if (globalThis.apirtcReactLibLogLevel.isInfoEnabled) {\n console.info(HOOK_NAME + \"|Self participant was ejected\")\n }\n if (onEjectedSelf) {\n onEjectedSelf()\n }\n } else {\n if (onEjected) {\n onEjected(data.contact)\n }\n }\n };\n\n conversation\n .on('contactJoinedWaitingRoom', on_contactJoinedWaitingRoom)\n .on('contactLeftWaitingRoom', on_contactLeftWaitingRoom)\n .on('participantEjected', on_participantEjected)\n\n return () => {\n if (globalThis.apirtcReactLibLogLevel.isDebugEnabled) {\n console.debug(HOOK_NAME + \"|conversation clear\", conversation)\n }\n // remove listeners\n conversation\n .removeListener('contactJoinedWaitingRoom', on_contactJoinedWaitingRoom)\n .removeListener('contactLeftWaitingRoom', on_contactLeftWaitingRoom)\n .removeListener('participantEjected', on_participantEjected)\n setCandidates(new Set())\n }\n }\n }, [conversation])\n\n return {\n candidates\n }\n}","import { Conversation, PublishOptions, Stream, StreamInfo } from '@apirtc/apirtc';\nimport { useCallback, useEffect, useState } from 'react';\n\n// TODO?: add pagination ?\n// interface Options {\n// streamsSubscribePageSize: number\n// }\n\nfunction notEmpty<T>(value: T | null | undefined): value is T {\n return value !== null && value !== undefined;\n}\n\nconst HOOK_NAME = \"useConversationStreams\";\nexport default function useConversationStreams(\n conversation: Conversation | undefined,\n /** fully managed list of Stream(s) to publish, with associated publish options */\n streamsToPublish: Array<{ stream: Stream, options?: PublishOptions } | undefined | null> = [],\n errorCallback?: (error: any) => void\n) {\n\n if (globalThis.apirtcReactLibLogLevel.isDebugEnabled) {\n console.debug(`${HOOK_NAME}|hook render`, streamsToPublish.map((obj) => obj?.options))\n }\n\n // A cache to handle publication differences\n const [publishedStreamsCache, setPublishedStreamsCache] =\n useState<Array<{ stream: Stream, options?: PublishOptions } | undefined | null>>([]);\n\n // Use an internal array which will always be the same object as far as React knows\n // This will avoid the need for adding it as a dependency for each callback\n const [publishedStreams] = useState<Array<Stream>>(new Array<Stream>());\n // And use a copy as output array so that client code will react upon change\n // (only a new instance of array is detected by React)\n const [o_publishedStreams, setO_PublishedStreams] = useState<Array<Stream>>(new Array<Stream>());\n\n const [subscribedStreams] = useState<Array<Stream>>(new Array<Stream>());\n const [o_subscribedStreams, setO_SubscribedStreams] = useState<Array<Stream>>(new Array<Stream>());\n\n const publish: (localStream: Stream, options?: PublishOptions) => Promise<Stream> =\n useCallback((localStream: Stream, options?: PublishOptions) => {\n return new Promise<Stream>((resolve, reject) => {\n if (conversation) {\n if (globalThis.apirtcReactLibLogLevel.isDebugEnabled) {\n console.debug(`${HOOK_NAME}|publish|${conversation.getName()}`, localStream, options)\n }\n conversation.publish(localStream, options).then((stream: Stream) => {\n if (globalThis.apirtcReactLibLogLevel.isInfoEnabled) {\n console.info(`${HOOK_NAME}|published|${conversation.getName()}`, stream)\n }\n //console.log(`PUSHING ${stream.getId()} to publishedStreams`, JSON.stringify(publishedStreams.map(s => s.getId())))\n publishedStreams.push(stream)\n // Returning a new array makes lets React detect changes\n setO_PublishedStreams(Array.from(publishedStreams))\n resolve(stream)\n }).catch((error: any) => {\n reject(error)\n })\n }\n })\n }, [conversation]);\n\n const replacePublishedStream = useCallback((oldStream: Stream, newStream: Stream) => {\n return new Promise<Stream>((resolve, reject) => {\n if (conversation) {\n if (globalThis.apirtcReactLibLogLevel.isDebugEnabled) {\n console.debug(`${HOOK_NAME}|replacePublishedStream|${conversation.getName()}|${oldStream.getId()} -> ${newStream.getId()}`)\n }\n const conversationCall = conversation.getConversationCall(oldStream);\n if (conversationCall) {\n conversationCall.replacePublishedStream(newStream)\n .then((stream: Stream) => {\n if (globalThis.apirtcReactLibLogLevel.isInfoEnabled) {\n console.info(`${HOOK_NAME}|stream replaced|${conversation.getName()}`, oldStream, stream)\n }\n const index = publishedStreams.indexOf(oldStream);\n if (index >= 0) {\n publishedStreams.splice(index, 1, stream)\n setO_PublishedStreams(Array.from(publishedStreams))\n }\n resolve(stream)\n }).catch((error: any) => {\n reject(error)\n })\n }\n }\n })\n }, [conversation]);\n\n const unpublish: (localStream: Stream) => void = useCallback((localStream: Stream) => {\n if (conversation) {\n if (globalThis.apirtcReactLibLogLevel.isDebugEnabled) {\n console.debug(`${HOOK_NAME}|unpublish|${conversation.getName()}`, localStream)\n }\n conversation.unpublish(localStream)\n const index = publishedStreams.indexOf(localStream);\n if (index >= 0) {\n publishedStreams.splice(index, 1)\n setO_PublishedStreams(Array.from(publishedStreams))\n }\n }\n }, [conversation]);\n\n const doHandlePublication = useCallback(() => {\n const maxLength = Math.max(publishedStreamsCache.length, streamsToPublish.length);\n if (globalThis.apirtcReactLibLogLevel.isDebugEnabled) {\n console.debug(HOOK_NAME + \"|doHandlePublication\", streamsToPublish,\n JSON.stringify(publishedStreamsCache.map(l_s => l_s?.stream.getId())), maxLength)\n }\n\n // Strategy for published streams cache is to initialize it as it should be\n // and remove items if publication fails.\n //const newPublishedStreamsCache = [...streamsToPublish];\n // Need to do a real copy of options !:\n const newPublishedStreamsCache = streamsToPublish.map(elt => {\n if (elt && elt.options) {\n return { stream: elt.stream, options: { ...elt.options } }\n } else {\n return elt\n }\n });\n setPublishedStreamsCache(newPublishedStreamsCache)\n\n // Prepare a set for Streams to publish, for further optimized check\n const streamsToPublishSet = new Set(streamsToPublish.filter(notEmpty).map((item) => item.stream));\n\n // Loop on arrays index to publish new streams, or replace if necessary\n for (let i = 0; i < maxLength; i++) {\n const previous = publishedStreamsCache[i];\n const next = streamsToPublish[i];\n\n const doPublish = (obj: { stream: Stream, options?: PublishOptions }) => {\n publish(obj.stream, obj.options).catch((error: Error) => {\n newPublishedStreamsCache.splice(i, 1, null)\n if (errorCallback) {\n errorCallback(error)\n } else if (globalThis.apirtcReactLibLogLevel.isWarnEnabled) {\n console.warn(`${HOOK_NAME}|publish|error`, error)\n }\n })\n };\n\n if (previous && next) {\n\n const doUnpublishPublish = () => {\n unpublish(previous.stream)\n doPublish(next)\n };\n\n if (previous.stream === next.stream) {\n // Streams are the same, only replace if options are different\n if (JSON.stringify(previous.options) !== JSON.stringify(next.options)) {\n // replacePublishStream does not allow to change PublishOptions, so we need to\n // unpublish and republish\n doUnpublishPublish()\n }\n } else {\n // If position in both new and cached list are defined but are different:\n // replace if and only if stream to unpublish shall not be published (at other position)\n if (streamsToPublishSet.has(previous.stream)) { // previous shall be published\n // Previous shall actually be published (at another position), so don't do anything about it\n // But then we still have to publish new stream (if not already published)\n if (conversation && !conversation.isPublishedStream(next.stream)) {\n doPublish(next)\n }\n } else {\n if (conversation && !conversation.isPublishedStream(next.stream)) {\n // replacePublishStream does not allow to change PublishOptions, so we need to\n // unpublish and republish if options also change\n if (JSON.stringify(previous.options) === JSON.stringify(next.options)) {\n replacePublishedStream(previous.stream, next.stream)\n .catch((error: Error) => {\n newPublishedStreamsCache.splice(i, 1, null)\n if (errorCallback) {\n errorCallback(error)\n } else if (globalThis.apirtcReactLibLogLevel.isWarnEnabled) {\n console.warn(`${HOOK_NAME}|replacePublishedStream|error`, error)\n }\n })\n } else {\n doUnpublishPublish()\n }\n } else { // new stream is already published\n // So we shall not replace another stream by it, but we need to unpublish the previous\n unpublish(previous.stream)\n }\n }\n }\n } else if (previous && !next) {\n // If position in new list is now undefined(or null) while it was in cache:\n // unpublish if and only if stream to unpublish shall not be published (at other position)\n if (!streamsToPublishSet.has(previous.stream)) {\n unpublish(previous.stream)\n }\n } else if (!previous && next) {\n // If position in new list is valid : publish it whatever the position in cache.\n // Depending on the case the stream might be already published, or it might be not\n // (can happen if the cache was set while Conversation was not joined yet).\n // Note that we could try to publish without checking isPublishedStream, the call would\n // reject with a console error but this would not affect the behavior.\n if (conversation && !conversation.isPublishedStream(next.stream)) {\n doPublish(next)\n }\n }\n }\n }, [conversation,\n streamsToPublish,\n publishedStreamsCache,\n publish, unpublish, replacePublishedStream]);\n\n const unpublishAndUnsubscribeAll = (i_conversation: Conversation) => {\n publishedStreams.forEach(stream => {\n if (globalThis.apirtcReactLibLogLevel.isDebugEnabled) {\n console.debug(HOOK_NAME + \"|unpublish stream\", i_conversation, stream)\n }\n i_conversation.unpublish(stream)\n })\n // Clear internal array\n publishedStreams.length = 0;\n\n // Clear cache\n setPublishedStreamsCache([])\n\n subscribedStreams.forEach(stream => {\n if (globalThis.apirtcReactLibLogLevel.isDebugEnabled) {\n console.debug(HOOK_NAME + \"|unsubscribeToStream stream\", i_conversation, stream)\n }\n i_conversation.unsubscribeToStream(stream.getId())\n })\n // Clear internal array\n subscribedStreams.length = 0;\n\n // Clear output arrays with new array so that parent gets notified of a change.\n // Simply setting length to 0 is not detected by react.\n setO_PublishedStreams(new Array<Stream>())\n setO_SubscribedStreams(new Array<Stream>())\n };\n\n // --------------------------------------------------------------------------\n // useEffect(s) - Order is important\n //\n useEffect(() => {\n if (conversation) {\n const on_streamAdded = (remoteStream: Stream) => {\n if (globalThis.apirtcReactLibLogLevel.isInfoEnabled) {\n console.info(HOOK_NAME + \"|on_streamAdded\", remoteStream)\n }\n subscribedStreams.push(remoteStream)\n setO_SubscribedStreams(Array.from(subscribedStreams))\n };\n const on_streamRemoved = (remoteStream: Stream) => {\n if (globalThis.apirtcReactLibLogLevel.isInfoEnabled) {\n console.info(HOOK_NAME + \"|on_streamRemoved\", remoteStream)\n }\n const index = subscribedStreams.indexOf(remoteStream);\n if (index >= 0) {\n subscribedStreams.splice(index, 1)\n setO_SubscribedStreams(Array.from(subscribedStreams))\n }\n };\n const on_streamListChanged = (streamInfo: StreamInfo) => {\n const streamId = String(streamInfo.streamId);\n if (streamInfo.isRemote === true) {\n if (streamInfo.listEventType === 'added') {\n // a remote stream was published\n conversation.subscribeToStream(streamId)\n } else if (streamInfo.listEventType === 'removed') {\n // a remote stream is not published anymore\n conversation.unsubscribeToStream(streamId)\n }\n }\n };\n // Subscribe to incoming streams\n conversation.on('streamAdded', on_streamAdded)\n conversation.on('streamRemoved', on_streamRemoved)\n conversation.on('streamListChanged', on_streamListChanged)\n\n return () => {\n // remove listeners\n conversation.removeListener('streamListChanged', on_streamListChanged)\n conversation.removeListener('streamRemoved', on_streamRemoved)\n conversation.removeListener('streamAdded', on_streamAdded)\n\n unpublishAndUnsubscribeAll(conversation)\n }\n }\n }, [conversation])\n\n useEffect(() => {\n if (conversation) {\n if (globalThis.apirtcReactLibLogLevel.isDebugEnabled) {\n console.debug(HOOK_NAME + \"|useEffect doHandlePublication\", conversation.getName())\n }\n\n const on_joined = () => {\n if (globalThis.apirtcReactLibLogLevel.isInfoEnabled) {\n console.info(HOOK_NAME + \"|on_joined\", conversation.getName(), streamsToPublish)\n }\n doHandlePublication()\n };\n const on_left = () => {\n if (globalThis.apirtcReactLibLogLevel.isInfoEnabled) {\n console.info(HOOK_NAME + \"|on_left\", conversation.getName())\n }\n // Forcing unpublish will allow to republish if joining again\n unpublishAndUnsubscribeAll(conversation)\n };\n\n conversation.on('joined', on_joined)\n conversation.on('left', on_left)\n\n return () => {\n conversation.removeListener('joined', on_joined)\n conversation.removeListener('left', on_left)\n }\n }\n }, [doHandlePublication]) // Don't add 'conversation' in here because\n // doHandlePublication already changes on conversation change\n\n useEffect(() => {\n if (globalThis.apirtcReactLibLogLevel.isDebugEnabled) {\n console.debug(`${HOOK_NAME}|useEffect streamsToPublish`,\n JSON.stringify(streamsToPublish.map(l_s => l_s?.stream.getId() + '-' + JSON.stringify(l_s?.options))))\n }\n if (conversation && conversation.isJoined()) {\n doHandlePublication()\n }\n }, [JSON.stringify(streamsToPublish.map(l_s => l_s?.stream.getId() + '-' + JSON.stringify(l_s?.options)))])\n\n return {\n publishedStreams: o_publishedStreams,\n subscribedStreams: o_subscribedStreams,\n publish,\n unpublish,\n replacePublishedStream\n }\n}\n","import { Contact, Session } from '@apirtc/apirtc';\nimport { useEffect, useState } from 'react';\n\n/**\n * Subscribe to groups and returns contactsByGroup (of theses groups only) when updated.\n * If input groups list is updated, this hooks works diff with the previous set in order\n * to make as little as possible unsubscribe/subscribe calls.\n */\n\nconst HOOK_NAME = \"usePresence\";\nexport default function usePresence(session: Session | undefined, groups: Array<string>) {\n\n const [groupsCache] = useState<Set<string>>(new Set());\n\n const [m_contactsByGroup] = useState<Map<string, Set<Contact>>>(new Map());\n\n const [contactsByGroup, setContactsByGroup] = useState<Map<string, Set<Contact>>>(new Map());\n\n useEffect(() => {\n if (session) {\n return () => {\n m_contactsByGroup.clear()\n setContactsByGroup(new Map(m_contactsByGroup))\n groupsCache.clear()\n }\n }\n }, [session])\n\n const getOrCreateGroupSet = (group: string) => {\n const o_set = m_contactsByGroup.get(group) ?? new Set();\n if (!m_contactsByGroup.has(group)) {\n m_contactsByGroup.set(group, o_set)\n }\n return o_set\n };\n\n useEffect(() => {\n if (globalThis.apirtcReactLibLogLevel.isDebugEnabled) {\n console.debug(HOOK_NAME + \"|useEffect session, groups\", groups)\n }\n if (session) {\n const l_session = session;\n const l_groupsSet = new Set(groups);\n\n // Diff update subscription to groups\n //\n l_groupsSet.forEach(group => {\n if (!groupsCache.has(group)) {\n if (globalThis.apirtcReactLibLogLevel.isInfoEnabled) {\n console.info(HOOK_NAME + \"|subscribeToGroup\", group)\n }\n groupsCache.add(group)\n l_session.subscribeToGroup(group)\n }\n })\n\n let needsRefresh = false;\n groupsCache.forEach(group => {\n if (!l_groupsSet.has(group)) {\n if (globalThis.apirtcReactLibLogLevel.isInfoEnabled) {\n console.info(HOOK_NAME + \"|unsubscribeToGroup\", group)\n }\n l_session.unsubscribeToGroup(group)\n groupsCache.delete(group)\n m_contactsByGroup.delete(group)\n needsRefresh = true;\n }\n })\n\n if (needsRefresh) {\n // contactsByGroup is exposed, so change the Map object to let client code detect a change.\n setContactsByGroup(new Map(m_contactsByGroup))\n }\n\n if (groups.length > 0) {\n const onContactListUpdate = (updatedContacts: any) => {\n\n if (globalThis.apirtcReactLibLogLevel.isDebugEnabled) {\n console.debug(HOOK_NAME + \"|contactListUpdate\", updatedContacts)\n }\n\n let needsRefresh = false;\n\n // Maintain Map of Contacts per Group\n //\n for (const group of Object.keys(updatedContacts.joinedGroup)) {\n if (l_groupsSet.has(group)) {\n const l_set = getOrCreateGroupSet(group);\n for (const contact of updatedContacts.joinedGroup[group]) {\n l_set.add(contact)\n needsRefresh = true;\n }\n }\n }\n for (const group of Object.keys(updatedContacts.leftGroup)) {\n if (l_groupsSet.has(group)) {\n const l_set = getOrCreateGroupSet(group);\n for (const contact of updatedContacts.leftGroup[group]) {\n l_set.delete(contact)\n needsRefresh = true;\n\n // if set is empty, no need to keep the group as key in the map\n if (l_set.size === 0) {\n m_contactsByGroup.delete(group)\n }\n }\n }\n }\n\n // For data updates, trigger a refresh if and only if contact is part of managed groups\n for (const contact of updatedContacts.userDataChanged as Contact[]) {\n for (const l_contacts of m_contactsByGroup.values()) {\n if (l_contacts.has(contact)) {\n needsRefresh = true;\n break;\n }\n }\n }\n\n if (needsRefresh) {\n // contactsByGroup is exposed, so change the Map object to let client code detect a change.\n setContactsByGroup(new Map(m_contactsByGroup))\n }\n };\n l_session.on('contactListUpdate', onContactListUpdate)\n return () => {\n l_session.removeListener('contactListUpdate', onContactListUpdate)\n }\n }\n }\n }, [session, JSON.stringify(groups)])\n\n return {\n contactsByGroup\n }\n}","import { RegisterInformation, Session, UserAgent } from '@apirtc/apirtc';\nimport { useEffect, useState } from 'react';\n\nexport type LoginPassword = {\n username: string\n password: string\n};\nfunction isInstanceOfLoginPassword(object: any): object is LoginPassword {\n if (typeof object !== 'object') return false;\n return 'username' in object;\n}\n\nexport type ApiKey = { apiKey: string };\nfunction isInstanceOfApiKey(object: any): object is ApiKey {\n if (typeof object !== 'object') return false;\n return 'apiKey' in object;\n}\n\nexport type Token = { token: string };\nfunction isInstanceOfToken(object: any): object is Token {\n if (typeof object !== 'object') return false;\n return 'token' in object;\n}\n\nexport type Credentials = LoginPassword | ApiKey | Token;\n\nconst HOOK_NAME = \"useSession\";\nexport default function useSession(credentials?: Credentials, options?: RegisterInformation,\n errorCallback?: (error: any) => void) {\n\n const [session, setSession] = useState<Session | undefined>();\n const [connecting, setConnecting] = useState<boolean>(false);\n\n useEffect(() => {\n if (globalThis.apirtcReactLibLogLevel.isDebugEnabled) {\n console.debug(HOOK_NAME + \"|useEffect credentials, options\", credentials, options)\n }\n if (credentials) {\n // To fix errors like \"Warning: Can't perform a React state update on an unmounted component\"\n // https://stackoverflow.com/questions/53949393/cant-perform-a-react-state-update-on-an-unmounted-component\n //let isMounted = true;\n connect(credentials, options).catch((error: any) => {\n console.error(HOOK_NAME + \"|connection failed\", error)\n setSession(undefined)\n\n if (errorCallback) {\n errorCallback(error)\n } else if (globalThis.apirtcReactLibLogLevel.isWarnEnabled) {\n console.warn(`${HOOK_NAME}|connect|error`, error)\n }\n })\n return () => {\n setSession(undefined)\n // Even though connecting is managed in connect(),\n // mark connecting to false when credentials are changed\n // as this shall be way to connect elsewhere or connect to\n // with other credentials. Note that to be perfect we should\n // cancel the potentially running connect : Is that possible with ApiRTC ?\n setConnecting(false)\n }\n }\n }, [JSON.stringify(credentials), JSON.stringify(options)])\n\n useEffect(() => {\n if (globalThis.apirtcReactLibLogLevel.isDebugEnabled) {\n console.debug(HOOK_NAME + \"|useEffect session\", session)\n }\n if (session) {\n const l_session = session;\n return () => {\n l_session.disconnect().then(() => {\n if (globalThis.apirtcReactLibLogLevel.isInfoEnabled) {\n console.info(HOOK_NAME + \"|disconnected\", l_session)\n }\n }).catch((error: any) => {\n console.error(HOOK_NAME + \"|disconnect\", error)\n })\n }\n }\n }, [session])\n\n const connect = (credentials: Credentials | undefined, options?: RegisterInformation) => {\n return new Promise<void>((resolve, reject) => {\n const registerInformation: RegisterInformation = options ? options : {\n cloudUrl: 'https://cloud.apirtc.com',\n };\n\n let l_userAgent;\n\n if (isInstanceOfLoginPassword(credentials)) {\n registerInformation.password = credentials.password;\n l_userAgent = new UserAgent({\n uri: 'apirtc:' + credentials.username\n });\n } else if (isInstanceOfApiKey(credentials)) {\n l_userAgent = new UserAgent({\n uri: `apiKey:${credentials.apiKey}`\n });\n } else if (isInstanceOfToken(credentials)) {\n l_userAgent = new UserAgent({\n uri: `token:${credentials.token}`\n });\n } else {\n reject(\"credentials not recognized\")\n return\n }\n\n setConnecting(true)\n l_userAgent.register(registerInformation).then(l_session => {\n if (globalThis.apirtcReactLibLogLevel.isInfoEnabled) {\n console.info(HOOK_NAME + \"|connected\", l_session)\n }\n setSession(l_session)\n resolve()\n }).catch((error: any) => {\n reject(error)\n }).finally(() => {\n setConnecting(false)\n })\n })\n };\n\n // const disconnect = useCallback(() => {\n // return new Promise<void>((resolve, reject) => {\n // if (session) {\n // const l_session = session;\n // l_session.disconnect().then(() => {\n // console.log(HOOK_NAME + \"|disconnected\", l_session)\n // setSession(undefined)\n // resolve()\n // }).catch((error: any) => {\n // console.error(HOOK_NAME + \"|disconnect\", error)\n // reject(error)\n // })\n // } else {\n // resolve()\n // }\n // })\n // }, [session])\n\n const disconnect = () => {\n setSession(undefined)\n };\n\n return {\n //userAgent: userAgent, // can get it from session\n session: session,\n connecting,\n connect,\n disconnect\n }\n}\n","import { Stream, VideoProcessorOptions } from '@apirtc/apirtc';\nimport { useEffect, useState } from 'react';\n\nconst HOOK_NAME = \"useStreamApplyVideoProcessor\";\n/**\n * This hook takes stream passed as parameter, and\n * returns either this stream or a stream with video processor applied.\n * This is controlled by the videoProcessorType input attribute.\n * By default the output stream is the input stream.\n * The hook fully manages the output stream (applies 'none' if input stream is set to undefined).\n * The hook never releases the input stream.\n * \n * @param stream\n * @param videoProcessorType\n * @param {VideoProcessorOptions} options\n * @returns new stream with video processor applied (or original stream if no processor applied)\n */\nexport default function useStreamApplyVideoProcessor(\n stream: Stream | undefined,\n videoProcessorType: 'none' | 'blur' | 'backgroundImage', options?: VideoProcessorOptions,\n errorCallback?: (error: any) => void) {\n //\n const [outStream, setOutStream] = useState(stream);\n const [applied, setApplied] = useState<'none' | 'blur' | 'backgroundImage'>(stream ? (stream as any).videoAppliedFilter : 'none');\n\n useEffect(() => {\n if (globalThis.apirtcReactLibLogLevel.isDebugEnabled) {\n console.debug(HOOK_NAME + \"|useEffect\", stream, videoProcessorType, options, stream ? JSON.stringify((stream as any).children) : \"empty\")\n }\n if (stream) {\n stream.applyVideoProcessor(videoProcessorType, options).then(l_stream => {\n setOutStream(l_stream)\n setApplied(videoProcessorType)\n }).catch(error => {\n setOutStream(stream)\n setApplied((stream as any).videoAppliedFilter)\n if (errorCallback) {\n errorCallback(error)\n } else if (globalThis.apirtcReactLibLogLevel.isWarnEnabled) {\n console.warn(HOOK_NAME + \"|useEffect\", stream, videoProcessorType, options, error)\n }\n })\n } else {\n setOutStream(stream)\n setApplied('none')\n }\n }, [stream, videoProcessorType, JSON.stringify(options)])\n\n return {\n stream: outStream,\n applied\n }\n}","import { MediaDevice, MediaDeviceList, Session, UserAgent } from '@apirtc/apirtc';\nimport { useEffect, useState } from 'react';\n\nconst EMPTY_LIST: MediaDeviceList = { audioinput: {}, audiooutput: {}, videoinput: {} };\n\nconst HOOK_NAME = \"useUserMediaDevices\";\nexport default function useUserMediaDevices(\n session: Session | undefined,\n storageKeyPrefix: string = \"apirtc\"\n) {\n const [userMediaDevices, setUserMediaDevices] = useState<MediaDeviceList>(EMPTY_LIST);\n\n const [selectedAudioIn, setSelectedAudioIn] = useState<MediaDevice>();\n const [selectedAudioOut, setSelectedAudioOut] = useState<MediaDevice>();\n const [selectedVideoIn, setSelectedVideoIn] = useState<MediaDevice>();\n\n const AUDIO_INPUT_ID_KEY = storageKeyPrefix + 'audioInputId';\n const AUDIO_OUTPUT_ID_KEY = storageKeyPrefix + 'audioOutputId';\n const VIDEO_INPUT_ID_KEY = storageKeyPrefix + 'videoInputId';\n\n useEffect(() => {\n if (session) {\n const userAgent: UserAgent = session.getUserAgent();\n\n const on_mediaDeviceChanged = () => {\n const mediaDevices: MediaDeviceList = userAgent.getUserMediaDevices()\n if (globalThis.apirtcReactLibLogLevel.isInfoEnabled) {\n console.info(HOOK_NAME + \"|mediaDeviceChanged\", mediaDevices)\n }\n setUserMediaDevices(mediaDevices)\n };\n userAgent.on('mediaDeviceChanged', on_mediaDeviceChanged)\n\n return () => {\n userAgent.removeListener('mediaDeviceChanged', on_mediaDeviceChanged)\n setUserMediaDevices(EMPTY_LIST)\n }\n }\n }, [session])\n\n useEffect(() => {\n const audioInputId = localStorage.getItem(AUDIO_INPUT_ID_KEY);\n const audioOutputId = localStorage.getItem(AUDIO_OUTPUT_ID_KEY);\n const videoInputId = localStorage.getItem(VIDEO_INPUT_ID_KEY);\n\n if (globalThis.apirtcReactLibLogLevel.isDebugEnabled) {\n console.debug(HOOK_NAME + '|userMediaDevices, audioInputId, audioOutputId, videoInputId', userMediaDevices, audioInputId, audioOutputId, videoInputId)\n }\n\n if (audioInputId && userMediaDevices.audioinput[audioInputId]) {\n setSelectedAudioIn(userMediaDevices.audioinput[audioInputId])\n }\n if (audioOutputId && userMediaDevices.audiooutput[audioOutputId]) {\n setSelectedAudioOut(userMediaDevices.audiooutput[audioOutputId])\n }\n if (videoInputId && userMediaDevices.videoinput[videoInputId]) {\n setSelectedVideoIn(userMediaDevices.videoinput[videoInputId])\n }\n }, [userMediaDevices])\n\n useEffect(() => {\n if (selectedAudioIn) {\n if (globalThis.apirtcReactLibLogLevel.isDebugEnabled) {\n console.debug(HOOK_NAME + '|Storing audioInputId', selectedAudioIn.getId())\n }\n localStorage.setItem(AUDIO_INPUT_ID_KEY, selectedAudioIn.getId())\n }\n }, [selectedAudioIn])\n\n useEffect(() => {\n if (selectedAudioOut) {\n if (globalThis.apirtcReactLibLogLevel.isDebugEnabled) {\n console.debug(HOOK_NAME + '|Storing audioOutputId', selectedAudioOut.getId())\n }\n localStorage.setItem(AUDIO_OUTPUT_ID_KEY, selectedAudioOut.getId())\n }\n }, [selectedAudioOut])\n\n useEffect(() => {\n if (selectedVideoIn) {\n if (globalThis.apirtcReactLibLogLevel.isDebugEnabled) {\n console.debug(HOOK_NAME + '|Storing videoInputId', selectedVideoIn.getId())\n }\n localStorage.setItem(VIDEO_INPUT_ID_KEY, selectedVideoIn.getId())\n }\n }, [selectedVideoIn])\n\n return {\n userMediaDevices,\n selectedAudioIn, setSelectedAudioIn,\n selectedAudioOut, setSelectedAudioOut,\n selectedVideoIn, setSelectedVideoIn\n }\n}","export * from './components'\nexport * from './hooks'\n\nexport type LogLevel = {\n level: 'debug' | 'info' | 'warn' | 'error'\n isDebugEnabled: boolean\n isInfoEnabled: boolean\n isWarnEnabled: boolean\n}\n\nconst INFO: LogLevel = { level: 'info', isDebugEnabled: false, isInfoEnabled: true, isWarnEnabled: true };\n\ndeclare global {\n var apirtcReactLibLogLevel: LogLevel;\n var setApirtcReactLibLogLevel: (logLevelText: 'debug' | 'info' | 'warn' | 'error') => void;\n}\n\n// a default value MUST be set in case application using the library does not override it\nglobalThis.apirtcReactLibLogLevel = INFO;\n\nexport function setLogLevel(logLevelText: 'debug' | 'info' | 'warn' | 'error') {\n switch (logLevelText) {\n case 'debug':\n globalThis.apirtcReactLibLogLevel = { level: 'debug', isDebugEnabled: true, isInfoEnabled: true, isWarnEnabled: true };\n break\n case 'info':\n globalThis.apirtcReactLibLogLevel = INFO;\n break\n case 'warn':\n globalThis.apirtcReactLibLogLevel = { level: 'warn', isDebugEnabled: false, isInfoEnabled: false, isWarnEnabled: true };\n break\n case 'error':\n globalThis.apirtcReactLibLogLevel = { level: 'error', isDebugEnabled: false, isInfoEnabled: false, isWarnEnabled: false };\n break\n default:\n // in case null is passed as input, default to 'info'\n globalThis.apirtcReactLibLogLevel = INFO;\n }\n return globalThis.apirtcReactLibLogLevel\n}\n\nglobalThis.setApirtcReactLibLogLevel = setLogLevel;\n"],"names":["VideoStream","props","autoPlay","videoRef","useRef","useEffect","ref","current","stream","attachToElement","src","React","createElement","id","getId","style","maxWidth","muted","HOOK_NAME","useCameraStream","session","options","setStream","useState","getUserAgent","createStream","then","localStream","globalThis","apirtcReactLibLogLevel","isInfoEnabled","console","info","catch","error","undefined","JSON","stringify","release","useConversation","name","join","conversation","setConversation","joined","setJoined","joining","setJoining","o_join","useCallback","isDebugEnabled","debug","Promise","resolve","reject","isJoined","finally","o_leave","leave","l_conversation","getOrCreateConversation","isWarnEnabled","warn","destroy","l_join","useConversationMessages","messages","Array","o_messages","setO_Messages","onMessage","message","getName","push","from","on","removeListener","length","sendMessage","msgContent","sender","uuid","content","time","Date","useConversationModeration","onEjected","onEjectedSelf","candidates","setCandidates","Set","on_contactJoinedWaitingRoom","contact","add","on_contactLeftWaitingRoom","delete","on_participantEjected","data","self","notEmpty","value","useConversationStreams","streamsToPublish","errorCallback","map","obj","publishedStreamsCache","setPublishedStreamsCache","publishedStreams","o_publishedStreams","setO_PublishedStreams","subscribedStreams","o_subscribedStreams","setO_SubscribedStreams","publish","replacePublishedStream","oldStream","newStream","conversationCall","getConversationCall","index","indexOf","splice","unpublish","doHandlePublication","maxLength","Math","max","l_s","newPublishedStreamsCache","elt","Object","assign","streamsToPublishSet","filter","item","i","previous","next","doPublish","doUnpublishPublish","has","isPublishedStream","unpublishAndUnsubscribeAll","i_conversation","forEach","unsubscribeToStream","on_streamAdded","remoteStream","on_streamRemoved","on_streamListChanged","streamInfo","streamId","String","isRemote","listEventType","subscribeToStream","on_joined","on_left","usePresence","groups","groupsCache","m_contactsByGroup","Map","contactsByGroup","setContactsByGroup","clear","getOrCreateGroupSet","group","o_set","_a","get","set","l_session","l_groupsSet","subscribeToGroup","needsRefresh","unsubscribeToGroup","onContactListUpdate","updatedContacts","keys","joinedGroup","l_set","leftGroup","size","userDataChanged","l_contacts","values","useSession","credentials","setSession","connecting","setConnecting","connect","disconnect","registerInformation","cloudUrl","l_userAgent","object","password","UserAgent","uri","username","isInstanceOfApiKey","apiKey","isInstanceOfToken","token","register","useStreamApplyVideoProcessor","videoProcessorType","outStream","setOutStream","applied","setApplied","videoAppliedFilter","children","applyVideoProcessor","l_stream","EMPTY_LIST","audioinput","audiooutput","videoinput","useUserMediaDevices","storageKeyPrefix","userMediaDevices","setUserMediaDevices","selectedAudioIn","setSelectedAudioIn","selectedAudioOut","setSelectedAudioOut","selectedVideoIn","setSelectedVideoIn","AUDIO_INPUT_ID_KEY","AUDIO_OUTPUT_ID_KEY","VIDEO_INPUT_ID_KEY","userAgent","on_mediaDeviceChanged","mediaDevices","getUserMediaDevices","audioInputId","localStorage","getItem","audioOutputId","videoInputId","setItem","INFO","level","setLogLevel","logLevelText","setApirtcReactLibLogLevel"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../src/components/VideoStream/VideoStream.tsx","../../src/hooks/useCameraStream.ts","../../src/hooks/useConversation.ts","../../src/hooks/useConversationMessages.ts","../../src/hooks/useConversationModeration.ts","../../src/hooks/useConversationStreams.ts","../../src/hooks/usePresence.ts","../../src/hooks/useSession.ts","../../src/hooks/useStreamApplyVideoProcessor.ts","../../src/hooks/useUserMediaDevices.ts","../../src/index.ts"],"sourcesContent":["import React, { useEffect, useRef } from 'react';\n\nimport { Stream } from '@apirtc/apirtc';\n\nexport type VideoStreamProps = {\n stream: Stream,\n autoPlay?: boolean,\n muted?: boolean\n};\nexport default function VideoStream(props: VideoStreamProps) {\n\n const { autoPlay = true } = props;\n\n const videoRef = useRef<HTMLVideoElement>(null)\n\n useEffect(() => {\n const ref = videoRef.current;\n if (ref && props.stream) {\n props.stream.attachToElement(ref)\n return () => {\n ref.src = \"\";\n }\n }\n }, [props.stream])\n // No need to put videoRef.current because useRef does not trigger rerender anyways\n\n return <video id={props.stream.getId()} style={{ maxWidth: '100%' }}\n ref={videoRef}\n autoPlay={autoPlay}\n muted={props.muted}></video>\n}","import { CreateStreamOptions, Session, Stream, UserAgent } from '@apirtc/apirtc';\nimport { useEffect, useState } from 'react';\n\nconst HOOK_NAME = \"useCameraStream\";\nexport default function useCameraStream(\n session: Session | undefined,\n options: CreateStreamOptions = {}\n) {\n const [stream, setStream] = useState<Stream>();\n\n useEffect(() => {\n if (session) {\n const userAgent: UserAgent = session.getUserAgent();\n userAgent.createStream(options).then((localStream: Stream) => {\n if (globalThis.apirtcReactLibLogLevel.isInfoEnabled) {\n console.info(HOOK_NAME + \"|createStream\", options, localStream)\n }\n setStream(localStream)\n }).catch((error: any) => {\n console.error(HOOK_NAME + \"|createStream\", options, error)\n setStream(undefined)\n })\n\n // DO NOT set out stream to undefined in the return, to prevent unnecessary refreshes\n // of other components with undefined stream, whereas we are expecting to change it\n // to another instance..\n // return () => { setStream(undefined) } // DON'T\n } else {\n setStream(undefined)\n }\n\n }, [session, JSON.stringify(options)])\n\n useEffect(() => {\n return () => {\n if (stream) {\n if (globalThis.apirtcReactLibLogLevel.isInfoEnabled) {\n console.info(HOOK_NAME + \"|release stream\", stream)\n }\n stream.release()\n }\n }\n }, [stream])\n\n return {\n stream\n }\n}","import { Conversation, GetOrCreateConversationOptions, Session } from '@apirtc/apirtc';\nimport { useCallback, useEffect, useState } from 'react';\n\nconst HOOK_NAME = \"useConversation\";\n/**\n * A hook to getOrCreate a named conversation and manage join/leave\n * @param session an ApiRTC Session\n * @param name the conversation name\n * @param options getOrCreateConversation options\n * @param join true by default.\n */\nexport default function useConversation(\n session: Session | undefined,\n name: string | undefined,\n options?: GetOrCreateConversationOptions,\n join: boolean = true\n) {\n const [conversation, setConversation] = useState<Conversation>();\n const [joined, setJoined] = useState<boolean>(false);\n const [joining, setJoining] = useState<boolean>(false);\n\n // Callbacks\n //\n // Offering Promised join/leave methods allows developer to act on then/catch\n //\n const o_join = useCallback(() => {\n if (globalThis.apirtcReactLibLogLevel.isDebugEnabled) {\n console.debug(HOOK_NAME + \"|join\", conversation)\n //JSON.stringify((apiRTC as any).session.apiCCWebRTCClient.webRTCClient.MCUClient.sessionMCUs))\n }\n return new Promise<void>((resolve, reject) => {\n if (!conversation) {\n reject(HOOK_NAME + \"|join|conversation not defined\")\n return\n }\n if (!conversation.isJoined()) {\n setJoining(true)\n conversation.join().then(() => {\n // successfully joined the conversation.\n setJoined(true)\n resolve()\n }).catch((error: any) => {\n // could not join the conversation.\n reject(error)\n }).finally(() => {\n setJoining(false)\n })\n } else {\n reject(HOOK_NAME + \"|join|conversation already joined\")\n }\n })\n }, [conversation]);\n\n const o_leave = useCallback(() => {\n if (globalThis.apirtcReactLibLogLevel.isDebugEnabled) {\n console.debug(HOOK_NAME + \"|leave\", conversation)\n }\n return new Promise<void>((resolve, reject) => {\n if (!conversation) {\n reject(HOOK_NAME + \"|leave|conversation not defined\")\n return\n }\n if (conversation.isJoined()) {\n conversation.leave().then(() => {\n // local user successfully left the conversation.\n setJoined(false)\n resolve()\n }).catch((error: any) => {\n reject(error)\n })\n } else {\n reject(HOOK_NAME + \"|leave|conversation is not joined\")\n }\n })\n }, [conversation]);\n\n // Effects\n //\n useEffect(() => {\n if (session && name) {\n if (globalThis.apirtcReactLibLogLevel.isDebugEnabled) {\n console.debug(HOOK_NAME + \"|getOrCreateConversation\", name, options, join)\n }\n const l_conversation = session.getOrCreateConversation(name, options);\n setConversation(l_conversation)\n return () => {\n if (globalThis.apirtcReactLibLogLevel.isDebugEnabled) {\n console.debug(HOOK_NAME + \"|useEffect cleanup\", name, options, join)\n }\n if (l_conversation.isJoined()) {\n l_conversation.leave()\n .then(() => { })\n .catch((error: any) => {\n if (globalThis.apirtcReactLibLogLevel.isWarnEnabled) {\n console.warn(HOOK_NAME + \"|useEffect conversation.leave()\", error)\n }\n })\n .finally(() => {\n l_conversation.destroy()\n // SHOULD NOT touch the state here as this async and the conversation may have already changed\n })\n } else {\n // It is important to destroy the conversation.\n // Otherwise subsequent getOrCreateConversation with same name would get\n // previous handle, regardless of the potentially new options.\n // This also allows to cleanup memory\n l_conversation.destroy()\n }\n // In any cases, update state accordingly\n // Note: this is done here synchronously, this shall NOT be done in the leave().finally to prevent\n // overriding a potential conversation change\n setConversation(undefined)\n setJoined(false)\n }\n }\n }, [session, name, JSON.stringify(options)])\n\n useEffect(() => {\n if (conversation && join) {\n if (globalThis.apirtcReactLibLogLevel.isDebugEnabled) {\n console.debug(HOOK_NAME + \"|useEffect\", conversation, join)\n }\n const l_conversation = conversation;\n const l_join = join;\n if (l_join) {\n setJoining(true)\n l_conversation.join().then(() => {\n if (globalThis.apirtcReactLibLogLevel.isInfoEnabled) {\n console.info(HOOK_NAME + \"|joined\", l_conversation)\n }\n setJoined(true)\n }).catch((error: any) => {\n if (globalThis.apirtcReactLibLogLevel.isWarnEnabled) {\n console.warn(HOOK_NAME + \"|useEffect conversation.join()\", error)\n }\n }).finally(() => {\n setJoining(false)\n })\n }\n return () => {\n if (globalThis.apirtcReactLibLogLevel.isDebugEnabled) {\n console.debug(HOOK_NAME + \"|useEffect cleanup\", l_conversation, l_join)\n }\n if (l_conversation.isJoined()) {\n l_conversation.leave().then(() => {\n setJoined(false)\n }).catch((error: any) => {\n if (globalThis.apirtcReactLibLogLevel.isWarnEnabled) {\n console.warn(HOOK_NAME + \"|useEffect conversation.leave()\", error)\n }\n })\n }\n }\n }\n }, [conversation, join])\n\n return {\n conversation,\n joining,\n joined,\n join: o_join,\n leave: o_leave\n }\n}","import { Contact, Conversation, ConversationMessage } from '@apirtc/apirtc';\nimport { useCallback, useEffect, useState } from 'react';\n\n// TODO : get and handle with pagination messages history\n// TODO : ask apirtc to include the uuid in ConversationMessage so that we can store it\n// into ConversationMessage when creating the local one, and we get it from conversation on:message\n// the uuid shall be the value used as a react child key when displaying list of messages\n\nconst HOOK_NAME = \"useConversationMessages\";\nexport default function useConversationMessages(\n conversation: Conversation | undefined,\n) {\n // Use an internal array which will always be the same object as far as React knows\n // This will avoid the need for adding it as a dependency for each callback\n const [messages] = useState<Array<ConversationMessage>>(new Array<ConversationMessage>());\n // And use a copy as output array so that client code will react upon change\n // (only a new instance of array is detected by React)\n const [o_messages, setO_Messages] = useState<Array<ConversationMessage>>(new Array<ConversationMessage>());\n\n useEffect(() => {\n if (conversation) {\n const onMessage = (message: ConversationMessage) => {\n if (globalThis.apirtcReactLibLogLevel.isInfoEnabled) {\n console.info(HOOK_NAME + \"|on:message:\", conversation.getName(), message)\n }\n messages.push(message)\n setO_Messages(Array.from(messages))\n };\n conversation.on('message', onMessage)\n\n return () => {\n conversation.removeListener('message', onMessage)\n messages.length = 0;\n setO_Messages(new Array<any>())\n }\n }\n }, [conversation])\n\n const sendMessage = useCallback((msgContent: string, sender: Contact) => {\n return new Promise<void>((resolve, reject) => {\n conversation?.sendMessage(msgContent)\n .then((uuid: number) => {\n if (globalThis.apirtcReactLibLogLevel.isInfoEnabled) {\n console.info(HOOK_NAME + \"|sentMessage\", conversation.getName(), uuid, msgContent)\n }\n messages.push({ content: msgContent, sender: sender, time: new Date() })\n setO_Messages(Array.from(messages))\n resolve()\n })\n .catch((error: any) => {\n if (globalThis.apirtcReactLibLogLevel.isWarnEnabled) {\n console.warn(HOOK_NAME + \"|sendMessage error\", error)\n }\n reject(error)\n })\n })\n }, [conversation]);\n\n return {\n messages: o_messages,\n sendMessage\n }\n}","import { Contact, Conversation } from '@apirtc/apirtc';\nimport { useEffect, useState } from 'react';\n\nconst HOOK_NAME = \"useConversationModeration\";\nexport default function useConversationModeration(\n conversation: Conversation | undefined,\n onEjected?: (contact: Contact) => void,\n onEjectedSelf?: () => void) {\n\n const [candidates, setCandidates] = useState<Set<Contact>>(new Set<Contact>());\n\n useEffect(() => {\n if (globalThis.apirtcReactLibLogLevel.isDebugEnabled) {\n console.debug(HOOK_NAME + \"|useEffect conversation\", conversation)\n }\n\n if (conversation) {\n const on_contactJoinedWaitingRoom = (contact: Contact) => {\n if (globalThis.apirtcReactLibLogLevel.isInfoEnabled) {\n console.info(HOOK_NAME + \"|on:contactJoinedWaitingRoom\", contact)\n }\n // A candidate joined the waiting room.\n candidates.add(contact)\n setCandidates(new Set(candidates))\n };\n const on_contactLeftWaitingRoom = (contact: Contact) => {\n if (globalThis.apirtcReactLibLogLevel.isInfoEnabled) {\n console.info(HOOK_NAME + \"|on:contactLeftWaitingRoom\", contact)\n }\n // A candidate left the waiting room.\n candidates.delete(contact)\n setCandidates(new Set(candidates))\n };\n // TODO make apirtc.d.ts update to replace 'any'\n const on_participantEjected = (data: any) => {\n if (globalThis.apirtcReactLibLogLevel.isInfoEnabled) {\n console.info(HOOK_NAME + \"|on:participantEjected\", data)\n }\n if (data.self === true) {\n if (globalThis.apirtcReactLibLogLevel.isInfoEnabled) {\n console.info(HOOK_NAME + \"|Self participant was ejected\")\n }\n if (onEjectedSelf) {\n onEjectedSelf()\n }\n } else {\n if (onEjected) {\n onEjected(data.contact)\n }\n }\n };\n\n conversation\n .on('contactJoinedWaitingRoom', on_contactJoinedWaitingRoom)\n .on('contactLeftWaitingRoom', on_contactLeftWaitingRoom)\n .on('participantEjected', on_participantEjected)\n\n return () => {\n if (globalThis.apirtcReactLibLogLevel.isDebugEnabled) {\n console.debug(HOOK_NAME + \"|conversation clear\", conversation)\n }\n // remove listeners\n conversation\n .removeListener('contactJoinedWaitingRoom', on_contactJoinedWaitingRoom)\n .removeListener('contactLeftWaitingRoom', on_contactLeftWaitingRoom)\n .removeListener('participantEjected', on_participantEjected)\n setCandidates(new Set())\n }\n }\n }, [conversation])\n\n return {\n candidates\n }\n}","import { Conversation, PublishOptions, Stream, StreamInfo } from '@apirtc/apirtc';\nimport { useCallback, useEffect, useState } from 'react';\n\n// TODO?: add pagination ?\n// interface Options {\n// streamsSubscribePageSize: number\n// }\n\nfunction notEmpty<T>(value: T | null | undefined): value is T {\n return value !== null && value !== undefined;\n}\n\nconst HOOK_NAME = \"useConversationStreams\";\nexport default function useConversationStreams(\n conversation: Conversation | undefined,\n /** fully managed list of Stream(s) to publish, with associated publish options */\n streamsToPublish: Array<{ stream: Stream, options?: PublishOptions } | undefined | null> = [],\n errorCallback?: (error: any) => void\n) {\n\n if (globalThis.apirtcReactLibLogLevel.isDebugEnabled) {\n console.debug(`${HOOK_NAME}|hook render`, streamsToPublish.map((obj) => obj?.options))\n }\n\n // A cache to handle publication differences\n const [publishedStreamsCache, setPublishedStreamsCache] =\n useState<Array<{ stream: Stream, options?: PublishOptions } | undefined | null>>([]);\n\n // Use an internal array which will always be the same object as far as React knows\n // This will avoid the need for adding it as a dependency for each callback\n const [publishedStreams] = useState<Array<Stream>>(new Array<Stream>());\n // And use a copy as output array so that client code will react upon change\n // (only a new instance of array is detected by React)\n const [o_publishedStreams, setO_PublishedStreams] = useState<Array<Stream>>(new Array<Stream>());\n\n const [subscribedStreams] = useState<Array<Stream>>(new Array<Stream>());\n const [o_subscribedStreams, setO_SubscribedStreams] = useState<Array<Stream>>(new Array<Stream>());\n\n const publish: (localStream: Stream, options?: PublishOptions) => Promise<Stream> =\n useCallback((localStream: Stream, options?: PublishOptions) => {\n return new Promise<Stream>((resolve, reject) => {\n if (conversation) {\n if (globalThis.apirtcReactLibLogLevel.isDebugEnabled) {\n console.debug(`${HOOK_NAME}|publish|${conversation.getName()}`, localStream, options)\n }\n conversation.publish(localStream, options).then((stream: Stream) => {\n if (globalThis.apirtcReactLibLogLevel.isInfoEnabled) {\n console.info(`${HOOK_NAME}|published|${conversation.getName()}`, stream)\n }\n //console.log(`PUSHING ${stream.getId()} to publishedStreams`, JSON.stringify(publishedStreams.map(s => s.getId())))\n publishedStreams.push(stream)\n // Returning a new array makes lets React detect changes\n setO_PublishedStreams(Array.from(publishedStreams))\n resolve(stream)\n }).catch((error: any) => {\n reject(error)\n })\n }\n })\n }, [conversation]);\n\n const replacePublishedStream = useCallback((oldStream: Stream, newStream: Stream) => {\n return new Promise<Stream>((resolve, reject) => {\n if (conversation) {\n if (globalThis.apirtcReactLibLogLevel.isDebugEnabled) {\n console.debug(`${HOOK_NAME}|replacePublishedStream|${conversation.getName()}|${oldStream.getId()} -> ${newStream.getId()}`)\n }\n const conversationCall = conversation.getConversationCall(oldStream);\n if (conversationCall) {\n conversationCall.replacePublishedStream(newStream)\n .then((stream: Stream) => {\n if (globalThis.apirtcReactLibLogLevel.isInfoEnabled) {\n console.info(`${HOOK_NAME}|stream replaced|${conversation.getName()}`, oldStream, stream)\n }\n const index = publishedStreams.indexOf(oldStream);\n if (index >= 0) {\n publishedStreams.splice(index, 1, stream)\n setO_PublishedStreams(Array.from(publishedStreams))\n }\n resolve(stream)\n }).catch((error: any) => {\n reject(error)\n })\n }\n }\n })\n }, [conversation]);\n\n const unpublish: (localStream: Stream) => void = useCallback((localStream: Stream) => {\n if (conversation) {\n if (globalThis.apirtcReactLibLogLevel.isDebugEnabled) {\n console.debug(`${HOOK_NAME}|unpublish|${conversation.getName()}`, localStream)\n }\n conversation.unpublish(localStream)\n const index = publishedStreams.indexOf(localStream);\n if (index >= 0) {\n publishedStreams.splice(index, 1)\n setO_PublishedStreams(Array.from(publishedStreams))\n }\n }\n }, [conversation]);\n\n const doHandlePublication = useCallback(() => {\n const maxLength = Math.max(publishedStreamsCache.length, streamsToPublish.length);\n if (globalThis.apirtcReactLibLogLevel.isDebugEnabled) {\n console.debug(HOOK_NAME + \"|doHandlePublication\", streamsToPublish,\n JSON.stringify(publishedStreamsCache.map(l_s => l_s?.stream.getId())), maxLength)\n }\n\n // Strategy for published streams cache is to initialize it as it should be\n // and remove items if publication fails.\n //const newPublishedStreamsCache = [...streamsToPublish];\n // Need to do a real copy of options !:\n const newPublishedStreamsCache = streamsToPublish.map(elt => {\n if (elt && elt.options) {\n return { stream: elt.stream, options: { ...elt.options } }\n } else {\n return elt\n }\n });\n setPublishedStreamsCache(newPublishedStreamsCache)\n\n // Prepare a set for Streams to publish, for further optimized check\n const streamsToPublishSet = new Set(streamsToPublish.filter(notEmpty).map((item) => item.stream));\n\n // Loop on arrays index to publish new streams, or replace if necessary\n for (let i = 0; i < maxLength; i++) {\n const previous = publishedStreamsCache[i];\n const next = streamsToPublish[i];\n\n const doPublish = (obj: { stream: Stream, options?: PublishOptions }) => {\n publish(obj.stream, obj.options).catch((error: Error) => {\n newPublishedStreamsCache.splice(i, 1, null)\n if (errorCallback) {\n errorCallback(error)\n } else if (globalThis.apirtcReactLibLogLevel.isWarnEnabled) {\n console.warn(`${HOOK_NAME}|publish|error`, error)\n }\n })\n };\n\n if (previous && next) {\n\n const doUnpublishPublish = () => {\n unpublish(previous.stream)\n doPublish(next)\n };\n\n if (previous.stream === next.stream) {\n // Streams are the same, only replace if options are different\n if (JSON.stringify(previous.options) !== JSON.stringify(next.options)) {\n // replacePublishStream does not allow to change PublishOptions, so we need to\n // unpublish and republish\n doUnpublishPublish()\n }\n } else {\n // If position in both new and cached list are defined but are different:\n // replace if and only if stream to unpublish shall not be published (at other position)\n if (streamsToPublishSet.has(previous.stream)) { // previous shall be published\n // Previous shall actually be published (at another position), so don't do anything about it\n // But then we still have to publish new stream (if not already published)\n if (conversation && !conversation.isPublishedStream(next.stream)) {\n doPublish(next)\n }\n } else {\n if (conversation && !conversation.isPublishedStream(next.stream)) {\n // replacePublishStream does not allow to change PublishOptions, so we need to\n // unpublish and republish if options also change\n if (JSON.stringify(previous.options) === JSON.stringify(next.options)) {\n replacePublishedStream(previous.stream, next.stream)\n .catch((error: Error) => {\n newPublishedStreamsCache.splice(i, 1, null)\n if (errorCallback) {\n errorCallback(error)\n } else if (globalThis.apirtcReactLibLogLevel.isWarnEnabled) {\n console.warn(`${HOOK_NAME}|replacePublishedStream|error`, error)\n }\n })\n } else {\n doUnpublishPublish()\n }\n } else { // new stream is already published\n // So we shall not replace another stream by it, but we need to unpublish the previous\n unpublish(previous.stream)\n }\n }\n }\n } else if (previous && !next) {\n // If position in new list is now undefined(or null) while it was in cache:\n // unpublish if and only if stream to unpublish shall not be published (at other position)\n if (!streamsToPublishSet.has(previous.stream)) {\n unpublish(previous.stream)\n }\n } else if (!previous && next) {\n // If position in new list is valid : publish it whatever the position in cache.\n // Depending on the case the stream might be already published, or it might be not\n // (can happen if the cache was set while Conversation was not joined yet).\n // Note that we could try to publish without checking isPublishedStream, the call would\n // reject with a console error but this would not affect the behavior.\n if (conversation && !conversation.isPublishedStream(next.stream)) {\n doPublish(next)\n }\n }\n }\n }, [conversation,\n streamsToPublish,\n publishedStreamsCache,\n publish, unpublish, replacePublishedStream]);\n\n const unpublishAndUnsubscribeAll = (i_conversation: Conversation) => {\n publishedStreams.forEach(stream => {\n if (globalThis.apirtcReactLibLogLevel.isDebugEnabled) {\n console.debug(HOOK_NAME + \"|unpublish stream\", i_conversation, stream)\n }\n i_conversation.unpublish(stream)\n })\n // Clear internal array\n publishedStreams.length = 0;\n\n // Clear cache\n setPublishedStreamsCache([])\n\n subscribedStreams.forEach(stream => {\n if (globalThis.apirtcReactLibLogLevel.isDebugEnabled) {\n console.debug(HOOK_NAME + \"|unsubscribeToStream stream\", i_conversation, stream)\n }\n i_conversation.unsubscribeToStream(stream.getId())\n })\n // Clear internal array\n subscribedStreams.length = 0;\n\n // Clear output arrays with new array so that parent gets notified of a change.\n // Simply setting length to 0 is not detected by react.\n setO_PublishedStreams(new Array<Stream>())\n setO_SubscribedStreams(new Array<Stream>())\n };\n\n // --------------------------------------------------------------------------\n // useEffect(s) - Order is important\n //\n useEffect(() => {\n if (conversation) {\n const on_streamAdded = (remoteStream: Stream) => {\n if (globalThis.apirtcReactLibLogLevel.isInfoEnabled) {\n console.info(HOOK_NAME + \"|on_streamAdded\", remoteStream)\n }\n subscribedStreams.push(remoteStream)\n setO_SubscribedStreams(Array.from(subscribedStreams))\n };\n const on_streamRemoved = (remoteStream: Stream) => {\n if (globalThis.apirtcReactLibLogLevel.isInfoEnabled) {\n console.info(HOOK_NAME + \"|on_streamRemoved\", remoteStream)\n }\n const index = subscribedStreams.indexOf(remoteStream);\n if (index >= 0) {\n subscribedStreams.splice(index, 1)\n setO_SubscribedStreams(Array.from(subscribedStreams))\n }\n };\n const on_streamListChanged = (streamInfo: StreamInfo) => {\n const streamId = String(streamInfo.streamId);\n if (streamInfo.isRemote === true) {\n if (streamInfo.listEventType === 'added') {\n // a remote stream was published\n conversation.subscribeToStream(streamId)\n } else if (streamInfo.listEventType === 'removed') {\n // a remote stream is not published anymore\n conversation.unsubscribeToStream(streamId)\n }\n }\n };\n // Subscribe to incoming streams\n conversation.on('streamAdded', on_streamAdded)\n conversation.on('streamRemoved', on_streamRemoved)\n conversation.on('streamListChanged', on_streamListChanged)\n\n return () => {\n // remove listeners\n conversation.removeListener('streamListChanged', on_streamListChanged)\n conversation.removeListener('streamRemoved', on_streamRemoved)\n conversation.removeListener('streamAdded', on_streamAdded)\n\n unpublishAndUnsubscribeAll(conversation)\n }\n }\n }, [conversation])\n\n useEffect(() => {\n if (conversation) {\n if (globalThis.apirtcReactLibLogLevel.isDebugEnabled) {\n console.debug(HOOK_NAME + \"|useEffect doHandlePublication\", conversation.getName())\n }\n\n const on_joined = () => {\n if (globalThis.apirtcReactLibLogLevel.isInfoEnabled) {\n console.info(HOOK_NAME + \"|on_joined\", conversation.getName(), streamsToPublish)\n }\n doHandlePublication()\n };\n const on_left = () => {\n if (globalThis.apirtcReactLibLogLevel.isInfoEnabled) {\n console.info(HOOK_NAME + \"|on_left\", conversation.getName())\n }\n // Forcing unpublish will allow to republish if joining again\n unpublishAndUnsubscribeAll(conversation)\n };\n\n conversation.on('joined', on_joined)\n conversation.on('left', on_left)\n\n return () => {\n conversation.removeListener('joined', on_joined)\n conversation.removeListener('left', on_left)\n }\n }\n }, [doHandlePublication]) // Don't add 'conversation' in here because\n // doHandlePublication already changes on conversation change\n\n useEffect(() => {\n if (globalThis.apirtcReactLibLogLevel.isDebugEnabled) {\n console.debug(`${HOOK_NAME}|useEffect streamsToPublish`,\n JSON.stringify(streamsToPublish.map(l_s => l_s?.stream.getId() + '-' + JSON.stringify(l_s?.options))))\n }\n if (conversation && conversation.isJoined()) {\n doHandlePublication()\n }\n }, [JSON.stringify(streamsToPublish.map(l_s => l_s?.stream.getId() + '-' + JSON.stringify(l_s?.options)))])\n\n return {\n publishedStreams: o_publishedStreams,\n subscribedStreams: o_subscribedStreams,\n publish,\n unpublish,\n replacePublishedStream\n }\n}\n","import { Contact, Session } from '@apirtc/apirtc';\nimport { useEffect, useState } from 'react';\n\n/**\n * Subscribe to groups and returns contactsByGroup (of theses groups only) when updated.\n * If input groups list is updated, this hooks works diff with the previous set in order\n * to make as little as possible unsubscribe/subscribe calls.\n */\n\nconst HOOK_NAME = \"usePresence\";\nexport default function usePresence(session: Session | undefined, groups: Array<string>) {\n\n const [groupsCache] = useState<Set<string>>(new Set());\n\n const [m_contactsByGroup] = useState<Map<string, Set<Contact>>>(new Map());\n\n const [contactsByGroup, setContactsByGroup] = useState<Map<string, Set<Contact>>>(new Map());\n\n useEffect(() => {\n if (session) {\n return () => {\n m_contactsByGroup.clear()\n setContactsByGroup(new Map(m_contactsByGroup))\n groupsCache.clear()\n }\n }\n }, [session])\n\n const getOrCreateGroupSet = (group: string) => {\n const o_set = m_contactsByGroup.get(group) ?? new Set();\n if (!m_contactsByGroup.has(group)) {\n m_contactsByGroup.set(group, o_set)\n }\n return o_set\n };\n\n useEffect(() => {\n if (globalThis.apirtcReactLibLogLevel.isDebugEnabled) {\n console.debug(HOOK_NAME + \"|useEffect session, groups\", groups)\n }\n if (session) {\n const l_session = session;\n const l_groupsSet = new Set(groups);\n\n // Diff update subscription to groups\n //\n l_groupsSet.forEach(group => {\n if (!groupsCache.has(group)) {\n if (globalThis.apirtcReactLibLogLevel.isInfoEnabled) {\n console.info(HOOK_NAME + \"|subscribeToGroup\", group)\n }\n groupsCache.add(group)\n l_session.subscribeToGroup(group)\n }\n })\n\n let needsRefresh = false;\n groupsCache.forEach(group => {\n if (!l_groupsSet.has(group)) {\n if (globalThis.apirtcReactLibLogLevel.isInfoEnabled) {\n console.info(HOOK_NAME + \"|unsubscribeToGroup\", group)\n }\n l_session.unsubscribeToGroup(group)\n groupsCache.delete(group)\n m_contactsByGroup.delete(group)\n needsRefresh = true;\n }\n })\n\n if (needsRefresh) {\n // contactsByGroup is exposed, so change the Map object to let client code detect a change.\n setContactsByGroup(new Map(m_contactsByGroup))\n }\n\n if (groups.length > 0) {\n const onContactListUpdate = (updatedContacts: any) => {\n\n if (globalThis.apirtcReactLibLogLevel.isDebugEnabled) {\n console.debug(HOOK_NAME + \"|contactListUpdate\", updatedContacts)\n }\n\n let needsRefresh = false;\n\n // Maintain Map of Contacts per Group\n //\n for (const group of Object.keys(updatedContacts.joinedGroup)) {\n if (l_groupsSet.has(group)) {\n const l_set = getOrCreateGroupSet(group);\n for (const contact of updatedContacts.joinedGroup[group]) {\n l_set.add(contact)\n needsRefresh = true;\n }\n }\n }\n for (const group of Object.keys(updatedContacts.leftGroup)) {\n if (l_groupsSet.has(group)) {\n const l_set = getOrCreateGroupSet(group);\n for (const contact of updatedContacts.leftGroup[group]) {\n l_set.delete(contact)\n needsRefresh = true;\n\n // if set is empty, no need to keep the group as key in the map\n if (l_set.size === 0) {\n m_contactsByGroup.delete(group)\n }\n }\n }\n }\n\n // For data updates, trigger a refresh if and only if contact is part of managed groups\n for (const contact of updatedContacts.userDataChanged as Contact[]) {\n for (const l_contacts of m_contactsByGroup.values()) {\n if (l_contacts.has(contact)) {\n needsRefresh = true;\n break;\n }\n }\n }\n\n if (needsRefresh) {\n // contactsByGroup is exposed, so change the Map object to let client code detect a change.\n setContactsByGroup(new Map(m_contactsByGroup))\n }\n };\n l_session.on('contactListUpdate', onContactListUpdate)\n return () => {\n l_session.removeListener('contactListUpdate', onContactListUpdate)\n }\n }\n }\n }, [session, JSON.stringify(groups)])\n\n return {\n contactsByGroup\n }\n}","import { RegisterInformation, Session, UserAgent } from '@apirtc/apirtc';\nimport { useEffect, useState } from 'react';\n\nexport type LoginPassword = {\n username: string\n password: string\n};\nfunction isInstanceOfLoginPassword(object: any): object is LoginPassword {\n if (typeof object !== 'object') return false;\n return 'username' in object;\n}\n\nexport type ApiKey = { apiKey: string };\nfunction isInstanceOfApiKey(object: any): object is ApiKey {\n if (typeof object !== 'object') return false;\n return 'apiKey' in object;\n}\n\nexport type Token = { token: string };\nfunction isInstanceOfToken(object: any): object is Token {\n if (typeof object !== 'object') return false;\n return 'token' in object;\n}\n\nexport type Credentials = LoginPassword | ApiKey | Token;\n\nconst HOOK_NAME = \"useSession\";\nexport default function useSession(credentials?: Credentials, options?: RegisterInformation,\n errorCallback?: (error: any) => void) {\n\n const [session, setSession] = useState<Session | undefined>();\n const [connecting, setConnecting] = useState<boolean>(false);\n\n useEffect(() => {\n if (globalThis.apirtcReactLibLogLevel.isDebugEnabled) {\n console.debug(HOOK_NAME + \"|useEffect credentials, options\", credentials, options)\n }\n if (credentials) {\n // To fix errors like \"Warning: Can't perform a React state update on an unmounted component\"\n // https://stackoverflow.com/questions/53949393/cant-perform-a-react-state-update-on-an-unmounted-component\n //let isMounted = true;\n connect(credentials, options).catch((error: any) => {\n console.error(HOOK_NAME + \"|connection failed\", error)\n setSession(undefined)\n\n if (errorCallback) {\n errorCallback(error)\n } else if (globalThis.apirtcReactLibLogLevel.isWarnEnabled) {\n console.warn(`${HOOK_NAME}|connect|error`, error)\n }\n })\n return () => {\n setSession(undefined)\n // Even though connecting is managed in connect(),\n // mark connecting to false when credentials are changed\n // as this shall be way to connect elsewhere or connect to\n // with other credentials. Note that to be perfect we should\n // cancel the potentially running connect : Is that possible with ApiRTC ?\n setConnecting(false)\n }\n }\n }, [JSON.stringify(credentials), JSON.stringify(options)])\n\n useEffect(() => {\n if (globalThis.apirtcReactLibLogLevel.isDebugEnabled) {\n console.debug(HOOK_NAME + \"|useEffect session\", session)\n }\n if (session) {\n const l_session = session;\n return () => {\n l_session.disconnect().then(() => {\n if (globalThis.apirtcReactLibLogLevel.isInfoEnabled) {\n console.info(HOOK_NAME + \"|disconnected\", l_session)\n }\n }).catch((error: any) => {\n console.error(HOOK_NAME + \"|disconnect\", error)\n })\n }\n }\n }, [session])\n\n const connect = (credentials: Credentials | undefined, options?: RegisterInformation) => {\n return new Promise<void>((resolve, reject) => {\n const registerInformation: RegisterInformation = options ? options : {\n cloudUrl: 'https://cloud.apirtc.com',\n };\n\n let l_userAgent;\n\n if (isInstanceOfLoginPassword(credentials)) {\n registerInformation.password = credentials.password;\n l_userAgent = new UserAgent({\n uri: 'apirtc:' + credentials.username\n });\n } else if (isInstanceOfApiKey(credentials)) {\n l_userAgent = new UserAgent({\n uri: `apiKey:${credentials.apiKey}`\n });\n } else if (isInstanceOfToken(credentials)) {\n l_userAgent = new UserAgent({\n uri: `token:${credentials.token}`\n });\n } else {\n reject(\"credentials not recognized\")\n return\n }\n\n setConnecting(true)\n l_userAgent.register(registerInformation).then(l_session => {\n if (globalThis.apirtcReactLibLogLevel.isInfoEnabled) {\n console.info(HOOK_NAME + \"|connected\", l_session)\n }\n setSession(l_session)\n resolve()\n }).catch((error: any) => {\n reject(error)\n }).finally(() => {\n setConnecting(false)\n })\n })\n };\n\n // const disconnect = useCallback(() => {\n // return new Promise<void>((resolve, reject) => {\n // if (session) {\n // const l_session = session;\n // l_session.disconnect().then(() => {\n // console.log(HOOK_NAME + \"|disconnected\", l_session)\n // setSession(undefined)\n // resolve()\n // }).catch((error: any) => {\n // console.error(HOOK_NAME + \"|disconnect\", error)\n // reject(error)\n // })\n // } else {\n // resolve()\n // }\n // })\n // }, [session])\n\n const disconnect = () => {\n setSession(undefined)\n };\n\n return {\n //userAgent: userAgent, // can get it from session\n session: session,\n connecting,\n connect,\n disconnect\n }\n}\n","import { Stream, VideoProcessorOptions } from '@apirtc/apirtc';\nimport { useEffect, useState } from 'react';\n\nconst HOOK_NAME = \"useStreamApplyVideoProcessor\";\n/**\n * This hook takes stream passed as parameter, and\n * returns either this stream or a stream with video processor applied.\n * This is controlled by the videoProcessorType input attribute.\n * By default the output stream is the input stream.\n * The hook fully manages the output stream (applies 'none' if input stream is set to undefined).\n * The hook never releases the input stream.\n * \n * @param stream\n * @param videoProcessorType\n * @param {VideoProcessorOptions} options\n * @returns new stream with video processor applied (or original stream if no processor applied)\n */\nexport default function useStreamApplyVideoProcessor(\n stream: Stream | undefined,\n videoProcessorType: 'none' | 'blur' | 'backgroundImage', options?: VideoProcessorOptions,\n errorCallback?: (error: any) => void) {\n //\n const [outStream, setOutStream] = useState(stream);\n const [applied, setApplied] = useState<'none' | 'blur' | 'backgroundImage'>(stream ? (stream as any).videoAppliedFilter : 'none');\n\n useEffect(() => {\n if (globalThis.apirtcReactLibLogLevel.isDebugEnabled) {\n console.debug(HOOK_NAME + \"|useEffect\", stream, videoProcessorType, options, stream ? JSON.stringify((stream as any).children) : \"empty\")\n }\n if (stream) {\n stream.applyVideoProcessor(videoProcessorType, options).then(l_stream => {\n setOutStream(l_stream)\n setApplied(videoProcessorType)\n }).catch(error => {\n setOutStream(stream)\n setApplied((stream as any).videoAppliedFilter)\n if (errorCallback) {\n errorCallback(error)\n } else if (globalThis.apirtcReactLibLogLevel.isWarnEnabled) {\n console.warn(HOOK_NAME + \"|useEffect\", stream, videoProcessorType, options, error)\n }\n })\n } else {\n setOutStream(stream)\n setApplied('none')\n }\n }, [stream, videoProcessorType, JSON.stringify(options)])\n\n return {\n stream: outStream,\n applied\n }\n}","import { MediaDevice, MediaDeviceList, Session, UserAgent } from '@apirtc/apirtc';\nimport { useEffect, useState } from 'react';\n\nconst EMPTY_LIST: MediaDeviceList = { audioinput: {}, audiooutput: {}, videoinput: {} };\n\nconst getMediaDeviceFromLocalStorage = (key: string) => {\n const value = localStorage.getItem(key);\n const obj = value ? JSON.parse(value) : null;\n return obj ? new MediaDevice(obj.id, obj.type, obj.label) : undefined;\n};\n\nconst HOOK_NAME = \"useUserMediaDevices\";\nexport function useUserMediaDevices(\n session: Session | undefined,\n storageKeyPrefix: string = \"apirtc\"\n) {\n const [userMediaDevices, setUserMediaDevices] = useState<MediaDeviceList>(EMPTY_LIST);\n\n const AUDIO_INPUT_KEY = storageKeyPrefix + '.audioIn';\n const AUDIO_OUTPUT_KEY = storageKeyPrefix + '.audioOut';\n const VIDEO_INPUT_KEY = storageKeyPrefix + '.videoIn';\n\n const [selectedAudioIn, setSelectedAudioIn] = useState<MediaDevice | undefined>(getMediaDeviceFromLocalStorage(AUDIO_INPUT_KEY));\n const [selectedAudioOut, setSelectedAudioOut] = useState<MediaDevice | undefined>(getMediaDeviceFromLocalStorage(AUDIO_OUTPUT_KEY));\n const [selectedVideoIn, setSelectedVideoIn] = useState<MediaDevice | undefined>(getMediaDeviceFromLocalStorage(VIDEO_INPUT_KEY));\n\n useEffect(() => {\n if (session) {\n const userAgent: UserAgent = session.getUserAgent();\n\n const on_mediaDeviceChanged = () => {\n const mediaDevices: MediaDeviceList = userAgent.getUserMediaDevices()\n if (globalThis.apirtcReactLibLogLevel.isInfoEnabled) {\n console.info(HOOK_NAME + \"|mediaDeviceChanged\", mediaDevices)\n }\n setUserMediaDevices(mediaDevices)\n };\n userAgent.on('mediaDeviceChanged', on_mediaDeviceChanged)\n\n return () => {\n userAgent.removeListener('mediaDeviceChanged', on_mediaDeviceChanged)\n setUserMediaDevices(EMPTY_LIST)\n }\n }\n }, [session])\n\n useEffect(() => {\n if (userMediaDevices !== EMPTY_LIST) {\n const audioInputValue = localStorage.getItem(AUDIO_INPUT_KEY);\n const audioInputId: string = audioInputValue ? JSON.parse(audioInputValue)['id'] : undefined;\n if (audioInputId) {\n setSelectedAudioIn(userMediaDevices.audioinput[audioInputId])\n }\n\n const audioOutputValue = localStorage.getItem(AUDIO_OUTPUT_KEY);\n const audioOutputId: string = audioOutputValue ? JSON.parse(audioOutputValue)['id'] : undefined;\n if (audioOutputId) {\n setSelectedAudioOut(userMediaDevices.audiooutput[audioOutputId])\n }\n\n const videoInputValue = localStorage.getItem(VIDEO_INPUT_KEY);\n const videoInputId: string = videoInputValue ? JSON.parse(videoInputValue)['id'] : undefined;\n if (videoInputId) {\n setSelectedVideoIn(userMediaDevices.videoinput[videoInputId])\n }\n\n if (globalThis.apirtcReactLibLogLevel.isDebugEnabled) {\n console.debug(HOOK_NAME + '|userMediaDevices, audioInputId, audioOutputId, videoInputId', userMediaDevices, audioInputId, audioOutputId, videoInputId)\n }\n }\n\n }, [userMediaDevices])\n\n useEffect(() => {\n if (selectedAudioIn) {\n if (globalThis.apirtcReactLibLogLevel.isDebugEnabled) {\n console.debug(HOOK_NAME + '|Storing audioInput', selectedAudioIn)\n }\n localStorage.setItem(AUDIO_INPUT_KEY, JSON.stringify({\n id: selectedAudioIn.getId(), type: selectedAudioIn.getType(), label: selectedAudioIn.getLabel()\n }))\n }\n }, [selectedAudioIn?.getId()])\n\n useEffect(() => {\n if (selectedAudioOut) {\n if (globalThis.apirtcReactLibLogLevel.isDebugEnabled) {\n console.debug(HOOK_NAME + '|Storing audioOutput', selectedAudioOut)\n }\n localStorage.setItem(AUDIO_OUTPUT_KEY, JSON.stringify({\n id: selectedAudioOut.getId(), type: selectedAudioOut.getType(), label: selectedAudioOut.getLabel()\n }))\n }\n }, [selectedAudioOut?.getId()])\n\n useEffect(() => {\n if (selectedVideoIn) {\n if (globalThis.apirtcReactLibLogLevel.isDebugEnabled) {\n console.debug(HOOK_NAME + '|Storing VideoInput', selectedVideoIn)\n }\n localStorage.setItem(VIDEO_INPUT_KEY, JSON.stringify({\n id: selectedVideoIn.getId(), type: selectedVideoIn.getType(), label: selectedVideoIn.getLabel()\n }))\n }\n }, [selectedVideoIn?.getId()])\n\n return {\n userMediaDevices,\n selectedAudioIn, setSelectedAudioIn,\n selectedAudioOut, setSelectedAudioOut,\n selectedVideoIn, setSelectedVideoIn\n }\n}","export * from './components'\nexport * from './hooks'\n\nexport type LogLevel = {\n level: 'debug' | 'info' | 'warn' | 'error'\n isDebugEnabled: boolean\n isInfoEnabled: boolean\n isWarnEnabled: boolean\n}\n\nconst INFO: LogLevel = { level: 'info', isDebugEnabled: false, isInfoEnabled: true, isWarnEnabled: true };\n\ndeclare global {\n var apirtcReactLibLogLevel: LogLevel;\n var setApirtcReactLibLogLevel: (logLevelText: 'debug' | 'info' | 'warn' | 'error') => void;\n}\n\n// a default value MUST be set in case application using the library does not override it\nglobalThis.apirtcReactLibLogLevel = INFO;\n\nexport function setLogLevel(logLevelText: 'debug' | 'info' | 'warn' | 'error') {\n switch (logLevelText) {\n case 'debug':\n globalThis.apirtcReactLibLogLevel = { level: 'debug', isDebugEnabled: true, isInfoEnabled: true, isWarnEnabled: true };\n break\n case 'info':\n globalThis.apirtcReactLibLogLevel = INFO;\n break\n case 'warn':\n globalThis.apirtcReactLibLogLevel = { level: 'warn', isDebugEnabled: false, isInfoEnabled: false, isWarnEnabled: true };\n break\n case 'error':\n globalThis.apirtcReactLibLogLevel = { level: 'error', isDebugEnabled: false, isInfoEnabled: false, isWarnEnabled: false };\n break\n default:\n // in case null is passed as input, default to 'info'\n globalThis.apirtcReactLibLogLevel = INFO;\n }\n return globalThis.apirtcReactLibLogLevel\n}\n\nglobalThis.setApirtcReactLibLogLevel = setLogLevel;\n"],"names":["VideoStream","props","autoPlay","videoRef","useRef","useEffect","ref","current","stream","attachToElement","src","React","createElement","id","getId","style","maxWidth","muted","HOOK_NAME","useCameraStream","session","options","setStream","useState","getUserAgent","createStream","then","localStream","globalThis","apirtcReactLibLogLevel","isInfoEnabled","console","info","catch","error","undefined","JSON","stringify","release","useConversation","name","join","conversation","setConversation","joined","setJoined","joining","setJoining","o_join","useCallback","isDebugEnabled","debug","Promise","resolve","reject","isJoined","finally","o_leave","leave","l_conversation","getOrCreateConversation","isWarnEnabled","warn","destroy","l_join","useConversationMessages","messages","Array","o_messages","setO_Messages","onMessage","message","getName","push","from","on","removeListener","length","sendMessage","msgContent","sender","uuid","content","time","Date","useConversationModeration","onEjected","onEjectedSelf","candidates","setCandidates","Set","on_contactJoinedWaitingRoom","contact","add","on_contactLeftWaitingRoom","delete","on_participantEjected","data","self","notEmpty","value","useConversationStreams","streamsToPublish","errorCallback","map","obj","publishedStreamsCache","setPublishedStreamsCache","publishedStreams","o_publishedStreams","setO_PublishedStreams","subscribedStreams","o_subscribedStreams","setO_SubscribedStreams","publish","replacePublishedStream","oldStream","newStream","conversationCall","getConversationCall","index","indexOf","splice","unpublish","doHandlePublication","maxLength","Math","max","l_s","newPublishedStreamsCache","elt","Object","assign","streamsToPublishSet","filter","item","i","previous","next","doPublish","doUnpublishPublish","has","isPublishedStream","unpublishAndUnsubscribeAll","i_conversation","forEach","unsubscribeToStream","on_streamAdded","remoteStream","on_streamRemoved","on_streamListChanged","streamInfo","streamId","String","isRemote","listEventType","subscribeToStream","on_joined","on_left","usePresence","groups","groupsCache","m_contactsByGroup","Map","contactsByGroup","setContactsByGroup","clear","getOrCreateGroupSet","group","o_set","_a","get","set","l_session","l_groupsSet","subscribeToGroup","needsRefresh","unsubscribeToGroup","onContactListUpdate","updatedContacts","keys","joinedGroup","l_set","leftGroup","size","userDataChanged","l_contacts","values","useSession","credentials","setSession","connecting","setConnecting","connect","disconnect","registerInformation","cloudUrl","l_userAgent","object","password","UserAgent","uri","username","isInstanceOfApiKey","apiKey","isInstanceOfToken","token","register","useStreamApplyVideoProcessor","videoProcessorType","outStream","setOutStream","applied","setApplied","videoAppliedFilter","children","applyVideoProcessor","l_stream","EMPTY_LIST","audioinput","audiooutput","videoinput","getMediaDeviceFromLocalStorage","key","localStorage","getItem","parse","MediaDevice","type","label","useUserMediaDevices","storageKeyPrefix","userMediaDevices","setUserMediaDevices","AUDIO_INPUT_KEY","AUDIO_OUTPUT_KEY","VIDEO_INPUT_KEY","selectedAudioIn","setSelectedAudioIn","selectedAudioOut","setSelectedAudioOut","selectedVideoIn","setSelectedVideoIn","userAgent","on_mediaDeviceChanged","mediaDevices","getUserMediaDevices","audioInputValue","audioInputId","audioOutputValue","audioOutputId","videoInputValue","videoInputId","setItem","getType","getLabel","INFO","level","setLogLevel","logLevelText","setApirtcReactLibLogLevel"],"mappings":"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"}
|
package/dist/hooks/index.d.ts
CHANGED
|
@@ -6,4 +6,4 @@ export { default as useConversationStreams } from "./useConversationStreams";
|
|
|
6
6
|
export { default as usePresence } from "./usePresence";
|
|
7
7
|
export { ApiKey, Credentials, default as useSession, LoginPassword, Token } from "./useSession";
|
|
8
8
|
export { default as useStreamApplyVideoProcessor } from './useStreamApplyVideoProcessor';
|
|
9
|
-
export {
|
|
9
|
+
export { useUserMediaDevices } from "./useUserMediaDevices";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/// <reference types="react" />
|
|
2
2
|
import { MediaDevice, MediaDeviceList, Session } from '@apirtc/apirtc';
|
|
3
|
-
export
|
|
3
|
+
export declare function useUserMediaDevices(session: Session | undefined, storageKeyPrefix?: string): {
|
|
4
4
|
userMediaDevices: MediaDeviceList;
|
|
5
5
|
selectedAudioIn: MediaDevice | undefined;
|
|
6
6
|
setSelectedAudioIn: import("react").Dispatch<import("react").SetStateAction<MediaDevice | undefined>>;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("react"),require("@apirtc/apirtc")):"function"==typeof define&&define.amd?define(["exports","react","@apirtc/apirtc"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).ApiRtcReactLib={},e.React,e.apiRTC)}(this,(function(e,t,o){"use strict";function n(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}var a=n(t);const i="useCameraStream";const s="useConversation";const l="useConversationMessages";const c="useConversationModeration";function r(e){return null!=e}const u="useConversationStreams";const b="usePresence";const d="useSession";const g="useStreamApplyVideoProcessor";const f={audioinput:{},audiooutput:{},videoinput:{}},L="useUserMediaDevices";const p={level:"info",isDebugEnabled:!1,isInfoEnabled:!0,isWarnEnabled:!0};function v(e){switch(e){case"debug":globalThis.apirtcReactLibLogLevel={level:"debug",isDebugEnabled:!0,isInfoEnabled:!0,isWarnEnabled:!0};break;case"info":default:globalThis.apirtcReactLibLogLevel=p;break;case"warn":globalThis.apirtcReactLibLogLevel={level:"warn",isDebugEnabled:!1,isInfoEnabled:!1,isWarnEnabled:!0};break;case"error":globalThis.apirtcReactLibLogLevel={level:"error",isDebugEnabled:!1,isInfoEnabled:!1,isWarnEnabled:!1}}return globalThis.apirtcReactLibLogLevel}globalThis.apirtcReactLibLogLevel=p,globalThis.setApirtcReactLibLogLevel=v,e.VideoStream=function(e){const{autoPlay:o=!0}=e,n=t.useRef(null);return t.useEffect((()=>{const t=n.current;if(t&&e.stream)return e.stream.attachToElement(t),()=>{t.src=""}}),[e.stream]),a.default.createElement("video",{id:e.stream.getId(),style:{maxWidth:"100%"},ref:n,autoPlay:o,muted:e.muted})},e.setLogLevel=v,e.useCameraStream=function(e,o={}){const[n,a]=t.useState();return t.useEffect((()=>{if(e){e.getUserAgent().createStream(o).then((e=>{globalThis.apirtcReactLibLogLevel.isInfoEnabled&&console.info(i+"|createStream",o,e),a(e)})).catch((e=>{console.error(i+"|createStream",o,e),a(void 0)}))}else a(void 0)}),[e,JSON.stringify(o)]),t.useEffect((()=>()=>{n&&(globalThis.apirtcReactLibLogLevel.isInfoEnabled&&console.info(i+"|release stream",n),n.release())}),[n]),{stream:n}},e.useConversation=function(e,o,n,a=!0){const[i,l]=t.useState(),[c,r]=t.useState(!1),[u,b]=t.useState(!1),d=t.useCallback((()=>(globalThis.apirtcReactLibLogLevel.isDebugEnabled&&console.debug(s+"|join",i),new Promise(((e,t)=>{i?i.isJoined()?t(s+"|join|conversation already joined"):(b(!0),i.join().then((()=>{r(!0),e()})).catch((e=>{t(e)})).finally((()=>{b(!1)}))):t(s+"|join|conversation not defined")})))),[i]),g=t.useCallback((()=>(globalThis.apirtcReactLibLogLevel.isDebugEnabled&&console.debug(s+"|leave",i),new Promise(((e,t)=>{i?i.isJoined()?i.leave().then((()=>{r(!1),e()})).catch((e=>{t(e)})):t(s+"|leave|conversation is not joined"):t(s+"|leave|conversation not defined")})))),[i]);return t.useEffect((()=>{if(e&&o){globalThis.apirtcReactLibLogLevel.isDebugEnabled&&console.debug(s+"|getOrCreateConversation",o,n,a);const t=e.getOrCreateConversation(o,n);return l(t),()=>{globalThis.apirtcReactLibLogLevel.isDebugEnabled&&console.debug(s+"|useEffect cleanup",o,n,a),t.isJoined()?t.leave().then((()=>{})).catch((e=>{globalThis.apirtcReactLibLogLevel.isWarnEnabled&&console.warn(s+"|useEffect conversation.leave()",e)})).finally((()=>{t.destroy()})):t.destroy(),l(void 0),r(!1)}}}),[e,o,JSON.stringify(n)]),t.useEffect((()=>{if(i&&a){globalThis.apirtcReactLibLogLevel.isDebugEnabled&&console.debug(s+"|useEffect",i,a);const e=i,t=a;return t&&(b(!0),e.join().then((()=>{globalThis.apirtcReactLibLogLevel.isInfoEnabled&&console.info(s+"|joined",e),r(!0)})).catch((e=>{globalThis.apirtcReactLibLogLevel.isWarnEnabled&&console.warn(s+"|useEffect conversation.join()",e)})).finally((()=>{b(!1)}))),()=>{globalThis.apirtcReactLibLogLevel.isDebugEnabled&&console.debug(s+"|useEffect cleanup",e,t),e.isJoined()&&e.leave().then((()=>{r(!1)})).catch((e=>{globalThis.apirtcReactLibLogLevel.isWarnEnabled&&console.warn(s+"|useEffect conversation.leave()",e)}))}}}),[i,a]),{conversation:i,joining:u,joined:c,join:d,leave:g}},e.useConversationMessages=function(e){const[o]=t.useState(new Array),[n,a]=t.useState(new Array);return t.useEffect((()=>{if(e){const t=t=>{globalThis.apirtcReactLibLogLevel.isInfoEnabled&&console.info(l+"|on:message:",e.getName(),t),o.push(t),a(Array.from(o))};return e.on("message",t),()=>{e.removeListener("message",t),o.length=0,a(new Array)}}}),[e]),{messages:n,sendMessage:t.useCallback(((t,n)=>new Promise(((i,s)=>{null==e||e.sendMessage(t).then((s=>{globalThis.apirtcReactLibLogLevel.isInfoEnabled&&console.info(l+"|sentMessage",e.getName(),s,t),o.push({content:t,sender:n,time:new Date}),a(Array.from(o)),i()})).catch((e=>{globalThis.apirtcReactLibLogLevel.isWarnEnabled&&console.warn(l+"|sendMessage error",e),s(e)}))}))),[e])}},e.useConversationModeration=function(e,o,n){const[a,i]=t.useState(new Set);return t.useEffect((()=>{if(globalThis.apirtcReactLibLogLevel.isDebugEnabled&&console.debug(c+"|useEffect conversation",e),e){const t=e=>{globalThis.apirtcReactLibLogLevel.isInfoEnabled&&console.info(c+"|on:contactJoinedWaitingRoom",e),a.add(e),i(new Set(a))},s=e=>{globalThis.apirtcReactLibLogLevel.isInfoEnabled&&console.info(c+"|on:contactLeftWaitingRoom",e),a.delete(e),i(new Set(a))},l=e=>{globalThis.apirtcReactLibLogLevel.isInfoEnabled&&console.info(c+"|on:participantEjected",e),!0===e.self?(globalThis.apirtcReactLibLogLevel.isInfoEnabled&&console.info(c+"|Self participant was ejected"),n&&n()):o&&o(e.contact)};return e.on("contactJoinedWaitingRoom",t).on("contactLeftWaitingRoom",s).on("participantEjected",l),()=>{globalThis.apirtcReactLibLogLevel.isDebugEnabled&&console.debug(c+"|conversation clear",e),e.removeListener("contactJoinedWaitingRoom",t).removeListener("contactLeftWaitingRoom",s).removeListener("participantEjected",l),i(new Set)}}}),[e]),{candidates:a}},e.useConversationStreams=function(e,o=[],n){globalThis.apirtcReactLibLogLevel.isDebugEnabled&&console.debug(`${u}|hook render`,o.map((e=>null==e?void 0:e.options)));const[a,i]=t.useState([]),[s]=t.useState(new Array),[l,c]=t.useState(new Array),[b]=t.useState(new Array),[d,g]=t.useState(new Array),f=t.useCallback(((t,o)=>new Promise(((n,a)=>{e&&(globalThis.apirtcReactLibLogLevel.isDebugEnabled&&console.debug(`${u}|publish|${e.getName()}`,t,o),e.publish(t,o).then((t=>{globalThis.apirtcReactLibLogLevel.isInfoEnabled&&console.info(`${u}|published|${e.getName()}`,t),s.push(t),c(Array.from(s)),n(t)})).catch((e=>{a(e)})))}))),[e]),L=t.useCallback(((t,o)=>new Promise(((n,a)=>{if(e){globalThis.apirtcReactLibLogLevel.isDebugEnabled&&console.debug(`${u}|replacePublishedStream|${e.getName()}|${t.getId()} -> ${o.getId()}`);const i=e.getConversationCall(t);i&&i.replacePublishedStream(o).then((o=>{globalThis.apirtcReactLibLogLevel.isInfoEnabled&&console.info(`${u}|stream replaced|${e.getName()}`,t,o);const a=s.indexOf(t);a>=0&&(s.splice(a,1,o),c(Array.from(s))),n(o)})).catch((e=>{a(e)}))}}))),[e]),p=t.useCallback((t=>{if(e){globalThis.apirtcReactLibLogLevel.isDebugEnabled&&console.debug(`${u}|unpublish|${e.getName()}`,t),e.unpublish(t);const o=s.indexOf(t);o>=0&&(s.splice(o,1),c(Array.from(s)))}}),[e]),v=t.useCallback((()=>{const t=Math.max(a.length,o.length);globalThis.apirtcReactLibLogLevel.isDebugEnabled&&console.debug(u+"|doHandlePublication",o,JSON.stringify(a.map((e=>null==e?void 0:e.stream.getId()))),t);const s=o.map((e=>e&&e.options?{stream:e.stream,options:Object.assign({},e.options)}:e));i(s);const l=new Set(o.filter(r).map((e=>e.stream)));for(let i=0;i<t;i++){const t=a[i],c=o[i],r=e=>{f(e.stream,e.options).catch((e=>{s.splice(i,1,null),n?n(e):globalThis.apirtcReactLibLogLevel.isWarnEnabled&&console.warn(`${u}|publish|error`,e)}))};if(t&&c){const o=()=>{p(t.stream),r(c)};t.stream===c.stream?JSON.stringify(t.options)!==JSON.stringify(c.options)&&o():l.has(t.stream)?e&&!e.isPublishedStream(c.stream)&&r(c):e&&!e.isPublishedStream(c.stream)?JSON.stringify(t.options)===JSON.stringify(c.options)?L(t.stream,c.stream).catch((e=>{s.splice(i,1,null),n?n(e):globalThis.apirtcReactLibLogLevel.isWarnEnabled&&console.warn(`${u}|replacePublishedStream|error`,e)})):o():p(t.stream)}else t&&!c?l.has(t.stream)||p(t.stream):!t&&c&&e&&!e.isPublishedStream(c.stream)&&r(c)}}),[e,o,a,f,p,L]),h=e=>{s.forEach((t=>{globalThis.apirtcReactLibLogLevel.isDebugEnabled&&console.debug(u+"|unpublish stream",e,t),e.unpublish(t)})),s.length=0,i([]),b.forEach((t=>{globalThis.apirtcReactLibLogLevel.isDebugEnabled&&console.debug(u+"|unsubscribeToStream stream",e,t),e.unsubscribeToStream(t.getId())})),b.length=0,c(new Array),g(new Array)};return t.useEffect((()=>{if(e){const t=e=>{globalThis.apirtcReactLibLogLevel.isInfoEnabled&&console.info(u+"|on_streamAdded",e),b.push(e),g(Array.from(b))},o=e=>{globalThis.apirtcReactLibLogLevel.isInfoEnabled&&console.info(u+"|on_streamRemoved",e);const t=b.indexOf(e);t>=0&&(b.splice(t,1),g(Array.from(b)))},n=t=>{const o=String(t.streamId);!0===t.isRemote&&("added"===t.listEventType?e.subscribeToStream(o):"removed"===t.listEventType&&e.unsubscribeToStream(o))};return e.on("streamAdded",t),e.on("streamRemoved",o),e.on("streamListChanged",n),()=>{e.removeListener("streamListChanged",n),e.removeListener("streamRemoved",o),e.removeListener("streamAdded",t),h(e)}}}),[e]),t.useEffect((()=>{if(e){globalThis.apirtcReactLibLogLevel.isDebugEnabled&&console.debug(u+"|useEffect doHandlePublication",e.getName());const t=()=>{globalThis.apirtcReactLibLogLevel.isInfoEnabled&&console.info(u+"|on_joined",e.getName(),o),v()},n=()=>{globalThis.apirtcReactLibLogLevel.isInfoEnabled&&console.info(u+"|on_left",e.getName()),h(e)};return e.on("joined",t),e.on("left",n),()=>{e.removeListener("joined",t),e.removeListener("left",n)}}}),[v]),t.useEffect((()=>{globalThis.apirtcReactLibLogLevel.isDebugEnabled&&console.debug(`${u}|useEffect streamsToPublish`,JSON.stringify(o.map((e=>(null==e?void 0:e.stream.getId())+"-"+JSON.stringify(null==e?void 0:e.options))))),e&&e.isJoined()&&v()}),[JSON.stringify(o.map((e=>(null==e?void 0:e.stream.getId())+"-"+JSON.stringify(null==e?void 0:e.options))))]),{publishedStreams:l,subscribedStreams:d,publish:f,unpublish:p,replacePublishedStream:L}},e.usePresence=function(e,o){const[n]=t.useState(new Set),[a]=t.useState(new Map),[i,s]=t.useState(new Map);t.useEffect((()=>{if(e)return()=>{a.clear(),s(new Map(a)),n.clear()}}),[e]);const l=e=>{var t;const o=null!==(t=a.get(e))&&void 0!==t?t:new Set;return a.has(e)||a.set(e,o),o};return t.useEffect((()=>{if(globalThis.apirtcReactLibLogLevel.isDebugEnabled&&console.debug(b+"|useEffect session, groups",o),e){const t=e,i=new Set(o);i.forEach((e=>{n.has(e)||(globalThis.apirtcReactLibLogLevel.isInfoEnabled&&console.info(b+"|subscribeToGroup",e),n.add(e),t.subscribeToGroup(e))}));let c=!1;if(n.forEach((e=>{i.has(e)||(globalThis.apirtcReactLibLogLevel.isInfoEnabled&&console.info(b+"|unsubscribeToGroup",e),t.unsubscribeToGroup(e),n.delete(e),a.delete(e),c=!0)})),c&&s(new Map(a)),o.length>0){const e=e=>{globalThis.apirtcReactLibLogLevel.isDebugEnabled&&console.debug(b+"|contactListUpdate",e);let t=!1;for(const o of Object.keys(e.joinedGroup))if(i.has(o)){const n=l(o);for(const a of e.joinedGroup[o])n.add(a),t=!0}for(const o of Object.keys(e.leftGroup))if(i.has(o)){const n=l(o);for(const i of e.leftGroup[o])n.delete(i),t=!0,0===n.size&&a.delete(o)}for(const o of e.userDataChanged)for(const e of a.values())if(e.has(o)){t=!0;break}t&&s(new Map(a))};return t.on("contactListUpdate",e),()=>{t.removeListener("contactListUpdate",e)}}}}),[e,JSON.stringify(o)]),{contactsByGroup:i}},e.useSession=function(e,n,a){const[i,s]=t.useState(),[l,c]=t.useState(!1);t.useEffect((()=>{if(globalThis.apirtcReactLibLogLevel.isDebugEnabled&&console.debug(d+"|useEffect credentials, options",e,n),e)return r(e,n).catch((e=>{console.error(d+"|connection failed",e),s(void 0),a?a(e):globalThis.apirtcReactLibLogLevel.isWarnEnabled&&console.warn(`${d}|connect|error`,e)})),()=>{s(void 0),c(!1)}}),[JSON.stringify(e),JSON.stringify(n)]),t.useEffect((()=>{if(globalThis.apirtcReactLibLogLevel.isDebugEnabled&&console.debug(d+"|useEffect session",i),i){const e=i;return()=>{e.disconnect().then((()=>{globalThis.apirtcReactLibLogLevel.isInfoEnabled&&console.info(d+"|disconnected",e)})).catch((e=>{console.error(d+"|disconnect",e)}))}}}),[i]);const r=(e,t)=>new Promise(((n,a)=>{const i=t||{cloudUrl:"https://cloud.apirtc.com"};let l;if("object"==typeof(r=e)&&"username"in r)i.password=e.password,l=new o.UserAgent({uri:"apirtc:"+e.username});else if(function(e){return"object"==typeof e&&"apiKey"in e}(e))l=new o.UserAgent({uri:`apiKey:${e.apiKey}`});else{if(!function(e){return"object"==typeof e&&"token"in e}(e))return void a("credentials not recognized");l=new o.UserAgent({uri:`token:${e.token}`})}var r;c(!0),l.register(i).then((e=>{globalThis.apirtcReactLibLogLevel.isInfoEnabled&&console.info(d+"|connected",e),s(e),n()})).catch((e=>{a(e)})).finally((()=>{c(!1)}))}));return{session:i,connecting:l,connect:r,disconnect:()=>{s(void 0)}}},e.useStreamApplyVideoProcessor=function(e,o,n,a){const[i,s]=t.useState(e),[l,c]=t.useState(e?e.videoAppliedFilter:"none");return t.useEffect((()=>{globalThis.apirtcReactLibLogLevel.isDebugEnabled&&console.debug(g+"|useEffect",e,o,n,e?JSON.stringify(e.children):"empty"),e?e.applyVideoProcessor(o,n).then((e=>{s(e),c(o)})).catch((t=>{s(e),c(e.videoAppliedFilter),a?a(t):globalThis.apirtcReactLibLogLevel.isWarnEnabled&&console.warn(g+"|useEffect",e,o,n,t)})):(s(e),c("none"))}),[e,o,JSON.stringify(n)]),{stream:i,applied:l}},e.useUserMediaDevices=function(e,o="apirtc"){const[n,a]=t.useState(f),[i,s]=t.useState(),[l,c]=t.useState(),[r,u]=t.useState(),b=o+"audioInputId",d=o+"audioOutputId",g=o+"videoInputId";return t.useEffect((()=>{if(e){const t=e.getUserAgent(),o=()=>{const e=t.getUserMediaDevices();globalThis.apirtcReactLibLogLevel.isInfoEnabled&&console.info(L+"|mediaDeviceChanged",e),a(e)};return t.on("mediaDeviceChanged",o),()=>{t.removeListener("mediaDeviceChanged",o),a(f)}}}),[e]),t.useEffect((()=>{const e=localStorage.getItem(b),t=localStorage.getItem(d),o=localStorage.getItem(g);globalThis.apirtcReactLibLogLevel.isDebugEnabled&&console.debug(L+"|userMediaDevices, audioInputId, audioOutputId, videoInputId",n,e,t,o),e&&n.audioinput[e]&&s(n.audioinput[e]),t&&n.audiooutput[t]&&c(n.audiooutput[t]),o&&n.videoinput[o]&&u(n.videoinput[o])}),[n]),t.useEffect((()=>{i&&(globalThis.apirtcReactLibLogLevel.isDebugEnabled&&console.debug(L+"|Storing audioInputId",i.getId()),localStorage.setItem(b,i.getId()))}),[i]),t.useEffect((()=>{l&&(globalThis.apirtcReactLibLogLevel.isDebugEnabled&&console.debug(L+"|Storing audioOutputId",l.getId()),localStorage.setItem(d,l.getId()))}),[l]),t.useEffect((()=>{r&&(globalThis.apirtcReactLibLogLevel.isDebugEnabled&&console.debug(L+"|Storing videoInputId",r.getId()),localStorage.setItem(g,r.getId()))}),[r]),{userMediaDevices:n,selectedAudioIn:i,setSelectedAudioIn:s,selectedAudioOut:l,setSelectedAudioOut:c,selectedVideoIn:r,setSelectedVideoIn:u}},Object.defineProperty(e,"__esModule",{value:!0})}));
|
|
1
|
+
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("react"),require("@apirtc/apirtc")):"function"==typeof define&&define.amd?define(["exports","react","@apirtc/apirtc"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).ApiRtcReactLib={},e.React,e.apiRTC)}(this,(function(e,t,o){"use strict";function n(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}var i=n(t);const a="useCameraStream";const s="useConversation";const l="useConversationMessages";const c="useConversationModeration";function r(e){return null!=e}const u="useConversationStreams";const b="usePresence";const d="useSession";const g="useStreamApplyVideoProcessor";const f={audioinput:{},audiooutput:{},videoinput:{}},L=e=>{const t=localStorage.getItem(e),n=t?JSON.parse(t):null;return n?new o.MediaDevice(n.id,n.type,n.label):void 0},p="useUserMediaDevices";const v={level:"info",isDebugEnabled:!1,isInfoEnabled:!0,isWarnEnabled:!0};function h(e){switch(e){case"debug":globalThis.apirtcReactLibLogLevel={level:"debug",isDebugEnabled:!0,isInfoEnabled:!0,isWarnEnabled:!0};break;case"info":default:globalThis.apirtcReactLibLogLevel=v;break;case"warn":globalThis.apirtcReactLibLogLevel={level:"warn",isDebugEnabled:!1,isInfoEnabled:!1,isWarnEnabled:!0};break;case"error":globalThis.apirtcReactLibLogLevel={level:"error",isDebugEnabled:!1,isInfoEnabled:!1,isWarnEnabled:!1}}return globalThis.apirtcReactLibLogLevel}globalThis.apirtcReactLibLogLevel=v,globalThis.setApirtcReactLibLogLevel=h,e.VideoStream=function(e){const{autoPlay:o=!0}=e,n=t.useRef(null);return t.useEffect((()=>{const t=n.current;if(t&&e.stream)return e.stream.attachToElement(t),()=>{t.src=""}}),[e.stream]),i.default.createElement("video",{id:e.stream.getId(),style:{maxWidth:"100%"},ref:n,autoPlay:o,muted:e.muted})},e.setLogLevel=h,e.useCameraStream=function(e,o={}){const[n,i]=t.useState();return t.useEffect((()=>{if(e){e.getUserAgent().createStream(o).then((e=>{globalThis.apirtcReactLibLogLevel.isInfoEnabled&&console.info(a+"|createStream",o,e),i(e)})).catch((e=>{console.error(a+"|createStream",o,e),i(void 0)}))}else i(void 0)}),[e,JSON.stringify(o)]),t.useEffect((()=>()=>{n&&(globalThis.apirtcReactLibLogLevel.isInfoEnabled&&console.info(a+"|release stream",n),n.release())}),[n]),{stream:n}},e.useConversation=function(e,o,n,i=!0){const[a,l]=t.useState(),[c,r]=t.useState(!1),[u,b]=t.useState(!1),d=t.useCallback((()=>(globalThis.apirtcReactLibLogLevel.isDebugEnabled&&console.debug(s+"|join",a),new Promise(((e,t)=>{a?a.isJoined()?t(s+"|join|conversation already joined"):(b(!0),a.join().then((()=>{r(!0),e()})).catch((e=>{t(e)})).finally((()=>{b(!1)}))):t(s+"|join|conversation not defined")})))),[a]),g=t.useCallback((()=>(globalThis.apirtcReactLibLogLevel.isDebugEnabled&&console.debug(s+"|leave",a),new Promise(((e,t)=>{a?a.isJoined()?a.leave().then((()=>{r(!1),e()})).catch((e=>{t(e)})):t(s+"|leave|conversation is not joined"):t(s+"|leave|conversation not defined")})))),[a]);return t.useEffect((()=>{if(e&&o){globalThis.apirtcReactLibLogLevel.isDebugEnabled&&console.debug(s+"|getOrCreateConversation",o,n,i);const t=e.getOrCreateConversation(o,n);return l(t),()=>{globalThis.apirtcReactLibLogLevel.isDebugEnabled&&console.debug(s+"|useEffect cleanup",o,n,i),t.isJoined()?t.leave().then((()=>{})).catch((e=>{globalThis.apirtcReactLibLogLevel.isWarnEnabled&&console.warn(s+"|useEffect conversation.leave()",e)})).finally((()=>{t.destroy()})):t.destroy(),l(void 0),r(!1)}}}),[e,o,JSON.stringify(n)]),t.useEffect((()=>{if(a&&i){globalThis.apirtcReactLibLogLevel.isDebugEnabled&&console.debug(s+"|useEffect",a,i);const e=a,t=i;return t&&(b(!0),e.join().then((()=>{globalThis.apirtcReactLibLogLevel.isInfoEnabled&&console.info(s+"|joined",e),r(!0)})).catch((e=>{globalThis.apirtcReactLibLogLevel.isWarnEnabled&&console.warn(s+"|useEffect conversation.join()",e)})).finally((()=>{b(!1)}))),()=>{globalThis.apirtcReactLibLogLevel.isDebugEnabled&&console.debug(s+"|useEffect cleanup",e,t),e.isJoined()&&e.leave().then((()=>{r(!1)})).catch((e=>{globalThis.apirtcReactLibLogLevel.isWarnEnabled&&console.warn(s+"|useEffect conversation.leave()",e)}))}}}),[a,i]),{conversation:a,joining:u,joined:c,join:d,leave:g}},e.useConversationMessages=function(e){const[o]=t.useState(new Array),[n,i]=t.useState(new Array);return t.useEffect((()=>{if(e){const t=t=>{globalThis.apirtcReactLibLogLevel.isInfoEnabled&&console.info(l+"|on:message:",e.getName(),t),o.push(t),i(Array.from(o))};return e.on("message",t),()=>{e.removeListener("message",t),o.length=0,i(new Array)}}}),[e]),{messages:n,sendMessage:t.useCallback(((t,n)=>new Promise(((a,s)=>{null==e||e.sendMessage(t).then((s=>{globalThis.apirtcReactLibLogLevel.isInfoEnabled&&console.info(l+"|sentMessage",e.getName(),s,t),o.push({content:t,sender:n,time:new Date}),i(Array.from(o)),a()})).catch((e=>{globalThis.apirtcReactLibLogLevel.isWarnEnabled&&console.warn(l+"|sendMessage error",e),s(e)}))}))),[e])}},e.useConversationModeration=function(e,o,n){const[i,a]=t.useState(new Set);return t.useEffect((()=>{if(globalThis.apirtcReactLibLogLevel.isDebugEnabled&&console.debug(c+"|useEffect conversation",e),e){const t=e=>{globalThis.apirtcReactLibLogLevel.isInfoEnabled&&console.info(c+"|on:contactJoinedWaitingRoom",e),i.add(e),a(new Set(i))},s=e=>{globalThis.apirtcReactLibLogLevel.isInfoEnabled&&console.info(c+"|on:contactLeftWaitingRoom",e),i.delete(e),a(new Set(i))},l=e=>{globalThis.apirtcReactLibLogLevel.isInfoEnabled&&console.info(c+"|on:participantEjected",e),!0===e.self?(globalThis.apirtcReactLibLogLevel.isInfoEnabled&&console.info(c+"|Self participant was ejected"),n&&n()):o&&o(e.contact)};return e.on("contactJoinedWaitingRoom",t).on("contactLeftWaitingRoom",s).on("participantEjected",l),()=>{globalThis.apirtcReactLibLogLevel.isDebugEnabled&&console.debug(c+"|conversation clear",e),e.removeListener("contactJoinedWaitingRoom",t).removeListener("contactLeftWaitingRoom",s).removeListener("participantEjected",l),a(new Set)}}}),[e]),{candidates:i}},e.useConversationStreams=function(e,o=[],n){globalThis.apirtcReactLibLogLevel.isDebugEnabled&&console.debug(`${u}|hook render`,o.map((e=>null==e?void 0:e.options)));const[i,a]=t.useState([]),[s]=t.useState(new Array),[l,c]=t.useState(new Array),[b]=t.useState(new Array),[d,g]=t.useState(new Array),f=t.useCallback(((t,o)=>new Promise(((n,i)=>{e&&(globalThis.apirtcReactLibLogLevel.isDebugEnabled&&console.debug(`${u}|publish|${e.getName()}`,t,o),e.publish(t,o).then((t=>{globalThis.apirtcReactLibLogLevel.isInfoEnabled&&console.info(`${u}|published|${e.getName()}`,t),s.push(t),c(Array.from(s)),n(t)})).catch((e=>{i(e)})))}))),[e]),L=t.useCallback(((t,o)=>new Promise(((n,i)=>{if(e){globalThis.apirtcReactLibLogLevel.isDebugEnabled&&console.debug(`${u}|replacePublishedStream|${e.getName()}|${t.getId()} -> ${o.getId()}`);const a=e.getConversationCall(t);a&&a.replacePublishedStream(o).then((o=>{globalThis.apirtcReactLibLogLevel.isInfoEnabled&&console.info(`${u}|stream replaced|${e.getName()}`,t,o);const i=s.indexOf(t);i>=0&&(s.splice(i,1,o),c(Array.from(s))),n(o)})).catch((e=>{i(e)}))}}))),[e]),p=t.useCallback((t=>{if(e){globalThis.apirtcReactLibLogLevel.isDebugEnabled&&console.debug(`${u}|unpublish|${e.getName()}`,t),e.unpublish(t);const o=s.indexOf(t);o>=0&&(s.splice(o,1),c(Array.from(s)))}}),[e]),v=t.useCallback((()=>{const t=Math.max(i.length,o.length);globalThis.apirtcReactLibLogLevel.isDebugEnabled&&console.debug(u+"|doHandlePublication",o,JSON.stringify(i.map((e=>null==e?void 0:e.stream.getId()))),t);const s=o.map((e=>e&&e.options?{stream:e.stream,options:Object.assign({},e.options)}:e));a(s);const l=new Set(o.filter(r).map((e=>e.stream)));for(let a=0;a<t;a++){const t=i[a],c=o[a],r=e=>{f(e.stream,e.options).catch((e=>{s.splice(a,1,null),n?n(e):globalThis.apirtcReactLibLogLevel.isWarnEnabled&&console.warn(`${u}|publish|error`,e)}))};if(t&&c){const o=()=>{p(t.stream),r(c)};t.stream===c.stream?JSON.stringify(t.options)!==JSON.stringify(c.options)&&o():l.has(t.stream)?e&&!e.isPublishedStream(c.stream)&&r(c):e&&!e.isPublishedStream(c.stream)?JSON.stringify(t.options)===JSON.stringify(c.options)?L(t.stream,c.stream).catch((e=>{s.splice(a,1,null),n?n(e):globalThis.apirtcReactLibLogLevel.isWarnEnabled&&console.warn(`${u}|replacePublishedStream|error`,e)})):o():p(t.stream)}else t&&!c?l.has(t.stream)||p(t.stream):!t&&c&&e&&!e.isPublishedStream(c.stream)&&r(c)}}),[e,o,i,f,p,L]),h=e=>{s.forEach((t=>{globalThis.apirtcReactLibLogLevel.isDebugEnabled&&console.debug(u+"|unpublish stream",e,t),e.unpublish(t)})),s.length=0,a([]),b.forEach((t=>{globalThis.apirtcReactLibLogLevel.isDebugEnabled&&console.debug(u+"|unsubscribeToStream stream",e,t),e.unsubscribeToStream(t.getId())})),b.length=0,c(new Array),g(new Array)};return t.useEffect((()=>{if(e){const t=e=>{globalThis.apirtcReactLibLogLevel.isInfoEnabled&&console.info(u+"|on_streamAdded",e),b.push(e),g(Array.from(b))},o=e=>{globalThis.apirtcReactLibLogLevel.isInfoEnabled&&console.info(u+"|on_streamRemoved",e);const t=b.indexOf(e);t>=0&&(b.splice(t,1),g(Array.from(b)))},n=t=>{const o=String(t.streamId);!0===t.isRemote&&("added"===t.listEventType?e.subscribeToStream(o):"removed"===t.listEventType&&e.unsubscribeToStream(o))};return e.on("streamAdded",t),e.on("streamRemoved",o),e.on("streamListChanged",n),()=>{e.removeListener("streamListChanged",n),e.removeListener("streamRemoved",o),e.removeListener("streamAdded",t),h(e)}}}),[e]),t.useEffect((()=>{if(e){globalThis.apirtcReactLibLogLevel.isDebugEnabled&&console.debug(u+"|useEffect doHandlePublication",e.getName());const t=()=>{globalThis.apirtcReactLibLogLevel.isInfoEnabled&&console.info(u+"|on_joined",e.getName(),o),v()},n=()=>{globalThis.apirtcReactLibLogLevel.isInfoEnabled&&console.info(u+"|on_left",e.getName()),h(e)};return e.on("joined",t),e.on("left",n),()=>{e.removeListener("joined",t),e.removeListener("left",n)}}}),[v]),t.useEffect((()=>{globalThis.apirtcReactLibLogLevel.isDebugEnabled&&console.debug(`${u}|useEffect streamsToPublish`,JSON.stringify(o.map((e=>(null==e?void 0:e.stream.getId())+"-"+JSON.stringify(null==e?void 0:e.options))))),e&&e.isJoined()&&v()}),[JSON.stringify(o.map((e=>(null==e?void 0:e.stream.getId())+"-"+JSON.stringify(null==e?void 0:e.options))))]),{publishedStreams:l,subscribedStreams:d,publish:f,unpublish:p,replacePublishedStream:L}},e.usePresence=function(e,o){const[n]=t.useState(new Set),[i]=t.useState(new Map),[a,s]=t.useState(new Map);t.useEffect((()=>{if(e)return()=>{i.clear(),s(new Map(i)),n.clear()}}),[e]);const l=e=>{var t;const o=null!==(t=i.get(e))&&void 0!==t?t:new Set;return i.has(e)||i.set(e,o),o};return t.useEffect((()=>{if(globalThis.apirtcReactLibLogLevel.isDebugEnabled&&console.debug(b+"|useEffect session, groups",o),e){const t=e,a=new Set(o);a.forEach((e=>{n.has(e)||(globalThis.apirtcReactLibLogLevel.isInfoEnabled&&console.info(b+"|subscribeToGroup",e),n.add(e),t.subscribeToGroup(e))}));let c=!1;if(n.forEach((e=>{a.has(e)||(globalThis.apirtcReactLibLogLevel.isInfoEnabled&&console.info(b+"|unsubscribeToGroup",e),t.unsubscribeToGroup(e),n.delete(e),i.delete(e),c=!0)})),c&&s(new Map(i)),o.length>0){const e=e=>{globalThis.apirtcReactLibLogLevel.isDebugEnabled&&console.debug(b+"|contactListUpdate",e);let t=!1;for(const o of Object.keys(e.joinedGroup))if(a.has(o)){const n=l(o);for(const i of e.joinedGroup[o])n.add(i),t=!0}for(const o of Object.keys(e.leftGroup))if(a.has(o)){const n=l(o);for(const a of e.leftGroup[o])n.delete(a),t=!0,0===n.size&&i.delete(o)}for(const o of e.userDataChanged)for(const e of i.values())if(e.has(o)){t=!0;break}t&&s(new Map(i))};return t.on("contactListUpdate",e),()=>{t.removeListener("contactListUpdate",e)}}}}),[e,JSON.stringify(o)]),{contactsByGroup:a}},e.useSession=function(e,n,i){const[a,s]=t.useState(),[l,c]=t.useState(!1);t.useEffect((()=>{if(globalThis.apirtcReactLibLogLevel.isDebugEnabled&&console.debug(d+"|useEffect credentials, options",e,n),e)return r(e,n).catch((e=>{console.error(d+"|connection failed",e),s(void 0),i?i(e):globalThis.apirtcReactLibLogLevel.isWarnEnabled&&console.warn(`${d}|connect|error`,e)})),()=>{s(void 0),c(!1)}}),[JSON.stringify(e),JSON.stringify(n)]),t.useEffect((()=>{if(globalThis.apirtcReactLibLogLevel.isDebugEnabled&&console.debug(d+"|useEffect session",a),a){const e=a;return()=>{e.disconnect().then((()=>{globalThis.apirtcReactLibLogLevel.isInfoEnabled&&console.info(d+"|disconnected",e)})).catch((e=>{console.error(d+"|disconnect",e)}))}}}),[a]);const r=(e,t)=>new Promise(((n,i)=>{const a=t||{cloudUrl:"https://cloud.apirtc.com"};let l;if("object"==typeof(r=e)&&"username"in r)a.password=e.password,l=new o.UserAgent({uri:"apirtc:"+e.username});else if(function(e){return"object"==typeof e&&"apiKey"in e}(e))l=new o.UserAgent({uri:`apiKey:${e.apiKey}`});else{if(!function(e){return"object"==typeof e&&"token"in e}(e))return void i("credentials not recognized");l=new o.UserAgent({uri:`token:${e.token}`})}var r;c(!0),l.register(a).then((e=>{globalThis.apirtcReactLibLogLevel.isInfoEnabled&&console.info(d+"|connected",e),s(e),n()})).catch((e=>{i(e)})).finally((()=>{c(!1)}))}));return{session:a,connecting:l,connect:r,disconnect:()=>{s(void 0)}}},e.useStreamApplyVideoProcessor=function(e,o,n,i){const[a,s]=t.useState(e),[l,c]=t.useState(e?e.videoAppliedFilter:"none");return t.useEffect((()=>{globalThis.apirtcReactLibLogLevel.isDebugEnabled&&console.debug(g+"|useEffect",e,o,n,e?JSON.stringify(e.children):"empty"),e?e.applyVideoProcessor(o,n).then((e=>{s(e),c(o)})).catch((t=>{s(e),c(e.videoAppliedFilter),i?i(t):globalThis.apirtcReactLibLogLevel.isWarnEnabled&&console.warn(g+"|useEffect",e,o,n,t)})):(s(e),c("none"))}),[e,o,JSON.stringify(n)]),{stream:a,applied:l}},e.useUserMediaDevices=function(e,o="apirtc"){const[n,i]=t.useState(f),a=o+".audioIn",s=o+".audioOut",l=o+".videoIn",[c,r]=t.useState(L(a)),[u,b]=t.useState(L(s)),[d,g]=t.useState(L(l));return t.useEffect((()=>{if(e){const t=e.getUserAgent(),o=()=>{const e=t.getUserMediaDevices();globalThis.apirtcReactLibLogLevel.isInfoEnabled&&console.info(p+"|mediaDeviceChanged",e),i(e)};return t.on("mediaDeviceChanged",o),()=>{t.removeListener("mediaDeviceChanged",o),i(f)}}}),[e]),t.useEffect((()=>{if(n!==f){const e=localStorage.getItem(a),t=e?JSON.parse(e).id:void 0;t&&r(n.audioinput[t]);const o=localStorage.getItem(s),i=o?JSON.parse(o).id:void 0;i&&b(n.audiooutput[i]);const c=localStorage.getItem(l),u=c?JSON.parse(c).id:void 0;u&&g(n.videoinput[u]),globalThis.apirtcReactLibLogLevel.isDebugEnabled&&console.debug(p+"|userMediaDevices, audioInputId, audioOutputId, videoInputId",n,t,i,u)}}),[n]),t.useEffect((()=>{c&&(globalThis.apirtcReactLibLogLevel.isDebugEnabled&&console.debug(p+"|Storing audioInput",c),localStorage.setItem(a,JSON.stringify({id:c.getId(),type:c.getType(),label:c.getLabel()})))}),[null==c?void 0:c.getId()]),t.useEffect((()=>{u&&(globalThis.apirtcReactLibLogLevel.isDebugEnabled&&console.debug(p+"|Storing audioOutput",u),localStorage.setItem(s,JSON.stringify({id:u.getId(),type:u.getType(),label:u.getLabel()})))}),[null==u?void 0:u.getId()]),t.useEffect((()=>{d&&(globalThis.apirtcReactLibLogLevel.isDebugEnabled&&console.debug(p+"|Storing VideoInput",d),localStorage.setItem(l,JSON.stringify({id:d.getId(),type:d.getType(),label:d.getLabel()})))}),[null==d?void 0:d.getId()]),{userMediaDevices:n,selectedAudioIn:c,setSelectedAudioIn:r,selectedAudioOut:u,setSelectedAudioOut:b,selectedVideoIn:d,setSelectedVideoIn:g}},Object.defineProperty(e,"__esModule",{value:!0})}));
|
|
2
2
|
//# sourceMappingURL=react-lib.production.min.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"react-lib.production.min.js","sources":["../src/hooks/useCameraStream.ts","../src/hooks/useConversation.ts","../src/hooks/useConversationMessages.ts","../src/hooks/useConversationModeration.ts","../src/hooks/useConversationStreams.ts","../src/hooks/usePresence.ts","../src/hooks/useSession.ts","../src/hooks/useStreamApplyVideoProcessor.ts","../src/hooks/useUserMediaDevices.ts","../src/index.ts","../src/components/VideoStream/VideoStream.tsx"],"sourcesContent":["import { CreateStreamOptions, Session, Stream, UserAgent } from '@apirtc/apirtc';\nimport { useEffect, useState } from 'react';\n\nconst HOOK_NAME = \"useCameraStream\";\nexport default function useCameraStream(\n session: Session | undefined,\n options: CreateStreamOptions = {}\n) {\n const [stream, setStream] = useState<Stream>();\n\n useEffect(() => {\n if (session) {\n const userAgent: UserAgent = session.getUserAgent();\n userAgent.createStream(options).then((localStream: Stream) => {\n if (globalThis.apirtcReactLibLogLevel.isInfoEnabled) {\n console.info(HOOK_NAME + \"|createStream\", options, localStream)\n }\n setStream(localStream)\n }).catch((error: any) => {\n console.error(HOOK_NAME + \"|createStream\", options, error)\n setStream(undefined)\n })\n\n // DO NOT set out stream to undefined in the return, to prevent unnecessary refreshes\n // of other components with undefined stream, whereas we are expecting to change it\n // to another instance..\n // return () => { setStream(undefined) } // DON'T\n } else {\n setStream(undefined)\n }\n\n }, [session, JSON.stringify(options)])\n\n useEffect(() => {\n return () => {\n if (stream) {\n if (globalThis.apirtcReactLibLogLevel.isInfoEnabled) {\n console.info(HOOK_NAME + \"|release stream\", stream)\n }\n stream.release()\n }\n }\n }, [stream])\n\n return {\n stream\n }\n}","import { Conversation, GetOrCreateConversationOptions, Session } from '@apirtc/apirtc';\nimport { useCallback, useEffect, useState } from 'react';\n\nconst HOOK_NAME = \"useConversation\";\n/**\n * A hook to getOrCreate a named conversation and manage join/leave\n * @param session an ApiRTC Session\n * @param name the conversation name\n * @param options getOrCreateConversation options\n * @param join true by default.\n */\nexport default function useConversation(\n session: Session | undefined,\n name: string | undefined,\n options?: GetOrCreateConversationOptions,\n join: boolean = true\n) {\n const [conversation, setConversation] = useState<Conversation>();\n const [joined, setJoined] = useState<boolean>(false);\n const [joining, setJoining] = useState<boolean>(false);\n\n // Callbacks\n //\n // Offering Promised join/leave methods allows developer to act on then/catch\n //\n const o_join = useCallback(() => {\n if (globalThis.apirtcReactLibLogLevel.isDebugEnabled) {\n console.debug(HOOK_NAME + \"|join\", conversation)\n //JSON.stringify((apiRTC as any).session.apiCCWebRTCClient.webRTCClient.MCUClient.sessionMCUs))\n }\n return new Promise<void>((resolve, reject) => {\n if (!conversation) {\n reject(HOOK_NAME + \"|join|conversation not defined\")\n return\n }\n if (!conversation.isJoined()) {\n setJoining(true)\n conversation.join().then(() => {\n // successfully joined the conversation.\n setJoined(true)\n resolve()\n }).catch((error: any) => {\n // could not join the conversation.\n reject(error)\n }).finally(() => {\n setJoining(false)\n })\n } else {\n reject(HOOK_NAME + \"|join|conversation already joined\")\n }\n })\n }, [conversation]);\n\n const o_leave = useCallback(() => {\n if (globalThis.apirtcReactLibLogLevel.isDebugEnabled) {\n console.debug(HOOK_NAME + \"|leave\", conversation)\n }\n return new Promise<void>((resolve, reject) => {\n if (!conversation) {\n reject(HOOK_NAME + \"|leave|conversation not defined\")\n return\n }\n if (conversation.isJoined()) {\n conversation.leave().then(() => {\n // local user successfully left the conversation.\n setJoined(false)\n resolve()\n }).catch((error: any) => {\n reject(error)\n })\n } else {\n reject(HOOK_NAME + \"|leave|conversation is not joined\")\n }\n })\n }, [conversation]);\n\n // Effects\n //\n useEffect(() => {\n if (session && name) {\n if (globalThis.apirtcReactLibLogLevel.isDebugEnabled) {\n console.debug(HOOK_NAME + \"|getOrCreateConversation\", name, options, join)\n }\n const l_conversation = session.getOrCreateConversation(name, options);\n setConversation(l_conversation)\n return () => {\n if (globalThis.apirtcReactLibLogLevel.isDebugEnabled) {\n console.debug(HOOK_NAME + \"|useEffect cleanup\", name, options, join)\n }\n if (l_conversation.isJoined()) {\n l_conversation.leave()\n .then(() => { })\n .catch((error: any) => {\n if (globalThis.apirtcReactLibLogLevel.isWarnEnabled) {\n console.warn(HOOK_NAME + \"|useEffect conversation.leave()\", error)\n }\n })\n .finally(() => {\n l_conversation.destroy()\n // SHOULD NOT touch the state here as this async and the conversation may have already changed\n })\n } else {\n // It is important to destroy the conversation.\n // Otherwise subsequent getOrCreateConversation with same name would get\n // previous handle, regardless of the potentially new options.\n // This also allows to cleanup memory\n l_conversation.destroy()\n }\n // In any cases, update state accordingly\n // Note: this is done here synchronously, this shall NOT be done in the leave().finally to prevent\n // overriding a potential conversation change\n setConversation(undefined)\n setJoined(false)\n }\n }\n }, [session, name, JSON.stringify(options)])\n\n useEffect(() => {\n if (conversation && join) {\n if (globalThis.apirtcReactLibLogLevel.isDebugEnabled) {\n console.debug(HOOK_NAME + \"|useEffect\", conversation, join)\n }\n const l_conversation = conversation;\n const l_join = join;\n if (l_join) {\n setJoining(true)\n l_conversation.join().then(() => {\n if (globalThis.apirtcReactLibLogLevel.isInfoEnabled) {\n console.info(HOOK_NAME + \"|joined\", l_conversation)\n }\n setJoined(true)\n }).catch((error: any) => {\n if (globalThis.apirtcReactLibLogLevel.isWarnEnabled) {\n console.warn(HOOK_NAME + \"|useEffect conversation.join()\", error)\n }\n }).finally(() => {\n setJoining(false)\n })\n }\n return () => {\n if (globalThis.apirtcReactLibLogLevel.isDebugEnabled) {\n console.debug(HOOK_NAME + \"|useEffect cleanup\", l_conversation, l_join)\n }\n if (l_conversation.isJoined()) {\n l_conversation.leave().then(() => {\n setJoined(false)\n }).catch((error: any) => {\n if (globalThis.apirtcReactLibLogLevel.isWarnEnabled) {\n console.warn(HOOK_NAME + \"|useEffect conversation.leave()\", error)\n }\n })\n }\n }\n }\n }, [conversation, join])\n\n return {\n conversation,\n joining,\n joined,\n join: o_join,\n leave: o_leave\n }\n}","import { Contact, Conversation, ConversationMessage } from '@apirtc/apirtc';\nimport { useCallback, useEffect, useState } from 'react';\n\n// TODO : get and handle with pagination messages history\n// TODO : ask apirtc to include the uuid in ConversationMessage so that we can store it\n// into ConversationMessage when creating the local one, and we get it from conversation on:message\n// the uuid shall be the value used as a react child key when displaying list of messages\n\nconst HOOK_NAME = \"useConversationMessages\";\nexport default function useConversationMessages(\n conversation: Conversation | undefined,\n) {\n // Use an internal array which will always be the same object as far as React knows\n // This will avoid the need for adding it as a dependency for each callback\n const [messages] = useState<Array<ConversationMessage>>(new Array<ConversationMessage>());\n // And use a copy as output array so that client code will react upon change\n // (only a new instance of array is detected by React)\n const [o_messages, setO_Messages] = useState<Array<ConversationMessage>>(new Array<ConversationMessage>());\n\n useEffect(() => {\n if (conversation) {\n const onMessage = (message: ConversationMessage) => {\n if (globalThis.apirtcReactLibLogLevel.isInfoEnabled) {\n console.info(HOOK_NAME + \"|on:message:\", conversation.getName(), message)\n }\n messages.push(message)\n setO_Messages(Array.from(messages))\n };\n conversation.on('message', onMessage)\n\n return () => {\n conversation.removeListener('message', onMessage)\n messages.length = 0;\n setO_Messages(new Array<any>())\n }\n }\n }, [conversation])\n\n const sendMessage = useCallback((msgContent: string, sender: Contact) => {\n return new Promise<void>((resolve, reject) => {\n conversation?.sendMessage(msgContent)\n .then((uuid: number) => {\n if (globalThis.apirtcReactLibLogLevel.isInfoEnabled) {\n console.info(HOOK_NAME + \"|sentMessage\", conversation.getName(), uuid, msgContent)\n }\n messages.push({ content: msgContent, sender: sender, time: new Date() })\n setO_Messages(Array.from(messages))\n resolve()\n })\n .catch((error: any) => {\n if (globalThis.apirtcReactLibLogLevel.isWarnEnabled) {\n console.warn(HOOK_NAME + \"|sendMessage error\", error)\n }\n reject(error)\n })\n })\n }, [conversation]);\n\n return {\n messages: o_messages,\n sendMessage\n }\n}","import { Contact, Conversation } from '@apirtc/apirtc';\nimport { useEffect, useState } from 'react';\n\nconst HOOK_NAME = \"useConversationModeration\";\nexport default function useConversationModeration(\n conversation: Conversation | undefined,\n onEjected?: (contact: Contact) => void,\n onEjectedSelf?: () => void) {\n\n const [candidates, setCandidates] = useState<Set<Contact>>(new Set<Contact>());\n\n useEffect(() => {\n if (globalThis.apirtcReactLibLogLevel.isDebugEnabled) {\n console.debug(HOOK_NAME + \"|useEffect conversation\", conversation)\n }\n\n if (conversation) {\n const on_contactJoinedWaitingRoom = (contact: Contact) => {\n if (globalThis.apirtcReactLibLogLevel.isInfoEnabled) {\n console.info(HOOK_NAME + \"|on:contactJoinedWaitingRoom\", contact)\n }\n // A candidate joined the waiting room.\n candidates.add(contact)\n setCandidates(new Set(candidates))\n };\n const on_contactLeftWaitingRoom = (contact: Contact) => {\n if (globalThis.apirtcReactLibLogLevel.isInfoEnabled) {\n console.info(HOOK_NAME + \"|on:contactLeftWaitingRoom\", contact)\n }\n // A candidate left the waiting room.\n candidates.delete(contact)\n setCandidates(new Set(candidates))\n };\n // TODO make apirtc.d.ts update to replace 'any'\n const on_participantEjected = (data: any) => {\n if (globalThis.apirtcReactLibLogLevel.isInfoEnabled) {\n console.info(HOOK_NAME + \"|on:participantEjected\", data)\n }\n if (data.self === true) {\n if (globalThis.apirtcReactLibLogLevel.isInfoEnabled) {\n console.info(HOOK_NAME + \"|Self participant was ejected\")\n }\n if (onEjectedSelf) {\n onEjectedSelf()\n }\n } else {\n if (onEjected) {\n onEjected(data.contact)\n }\n }\n };\n\n conversation\n .on('contactJoinedWaitingRoom', on_contactJoinedWaitingRoom)\n .on('contactLeftWaitingRoom', on_contactLeftWaitingRoom)\n .on('participantEjected', on_participantEjected)\n\n return () => {\n if (globalThis.apirtcReactLibLogLevel.isDebugEnabled) {\n console.debug(HOOK_NAME + \"|conversation clear\", conversation)\n }\n // remove listeners\n conversation\n .removeListener('contactJoinedWaitingRoom', on_contactJoinedWaitingRoom)\n .removeListener('contactLeftWaitingRoom', on_contactLeftWaitingRoom)\n .removeListener('participantEjected', on_participantEjected)\n setCandidates(new Set())\n }\n }\n }, [conversation])\n\n return {\n candidates\n }\n}","import { Conversation, PublishOptions, Stream, StreamInfo } from '@apirtc/apirtc';\nimport { useCallback, useEffect, useState } from 'react';\n\n// TODO?: add pagination ?\n// interface Options {\n// streamsSubscribePageSize: number\n// }\n\nfunction notEmpty<T>(value: T | null | undefined): value is T {\n return value !== null && value !== undefined;\n}\n\nconst HOOK_NAME = \"useConversationStreams\";\nexport default function useConversationStreams(\n conversation: Conversation | undefined,\n /** fully managed list of Stream(s) to publish, with associated publish options */\n streamsToPublish: Array<{ stream: Stream, options?: PublishOptions } | undefined | null> = [],\n errorCallback?: (error: any) => void\n) {\n\n if (globalThis.apirtcReactLibLogLevel.isDebugEnabled) {\n console.debug(`${HOOK_NAME}|hook render`, streamsToPublish.map((obj) => obj?.options))\n }\n\n // A cache to handle publication differences\n const [publishedStreamsCache, setPublishedStreamsCache] =\n useState<Array<{ stream: Stream, options?: PublishOptions } | undefined | null>>([]);\n\n // Use an internal array which will always be the same object as far as React knows\n // This will avoid the need for adding it as a dependency for each callback\n const [publishedStreams] = useState<Array<Stream>>(new Array<Stream>());\n // And use a copy as output array so that client code will react upon change\n // (only a new instance of array is detected by React)\n const [o_publishedStreams, setO_PublishedStreams] = useState<Array<Stream>>(new Array<Stream>());\n\n const [subscribedStreams] = useState<Array<Stream>>(new Array<Stream>());\n const [o_subscribedStreams, setO_SubscribedStreams] = useState<Array<Stream>>(new Array<Stream>());\n\n const publish: (localStream: Stream, options?: PublishOptions) => Promise<Stream> =\n useCallback((localStream: Stream, options?: PublishOptions) => {\n return new Promise<Stream>((resolve, reject) => {\n if (conversation) {\n if (globalThis.apirtcReactLibLogLevel.isDebugEnabled) {\n console.debug(`${HOOK_NAME}|publish|${conversation.getName()}`, localStream, options)\n }\n conversation.publish(localStream, options).then((stream: Stream) => {\n if (globalThis.apirtcReactLibLogLevel.isInfoEnabled) {\n console.info(`${HOOK_NAME}|published|${conversation.getName()}`, stream)\n }\n //console.log(`PUSHING ${stream.getId()} to publishedStreams`, JSON.stringify(publishedStreams.map(s => s.getId())))\n publishedStreams.push(stream)\n // Returning a new array makes lets React detect changes\n setO_PublishedStreams(Array.from(publishedStreams))\n resolve(stream)\n }).catch((error: any) => {\n reject(error)\n })\n }\n })\n }, [conversation]);\n\n const replacePublishedStream = useCallback((oldStream: Stream, newStream: Stream) => {\n return new Promise<Stream>((resolve, reject) => {\n if (conversation) {\n if (globalThis.apirtcReactLibLogLevel.isDebugEnabled) {\n console.debug(`${HOOK_NAME}|replacePublishedStream|${conversation.getName()}|${oldStream.getId()} -> ${newStream.getId()}`)\n }\n const conversationCall = conversation.getConversationCall(oldStream);\n if (conversationCall) {\n conversationCall.replacePublishedStream(newStream)\n .then((stream: Stream) => {\n if (globalThis.apirtcReactLibLogLevel.isInfoEnabled) {\n console.info(`${HOOK_NAME}|stream replaced|${conversation.getName()}`, oldStream, stream)\n }\n const index = publishedStreams.indexOf(oldStream);\n if (index >= 0) {\n publishedStreams.splice(index, 1, stream)\n setO_PublishedStreams(Array.from(publishedStreams))\n }\n resolve(stream)\n }).catch((error: any) => {\n reject(error)\n })\n }\n }\n })\n }, [conversation]);\n\n const unpublish: (localStream: Stream) => void = useCallback((localStream: Stream) => {\n if (conversation) {\n if (globalThis.apirtcReactLibLogLevel.isDebugEnabled) {\n console.debug(`${HOOK_NAME}|unpublish|${conversation.getName()}`, localStream)\n }\n conversation.unpublish(localStream)\n const index = publishedStreams.indexOf(localStream);\n if (index >= 0) {\n publishedStreams.splice(index, 1)\n setO_PublishedStreams(Array.from(publishedStreams))\n }\n }\n }, [conversation]);\n\n const doHandlePublication = useCallback(() => {\n const maxLength = Math.max(publishedStreamsCache.length, streamsToPublish.length);\n if (globalThis.apirtcReactLibLogLevel.isDebugEnabled) {\n console.debug(HOOK_NAME + \"|doHandlePublication\", streamsToPublish,\n JSON.stringify(publishedStreamsCache.map(l_s => l_s?.stream.getId())), maxLength)\n }\n\n // Strategy for published streams cache is to initialize it as it should be\n // and remove items if publication fails.\n //const newPublishedStreamsCache = [...streamsToPublish];\n // Need to do a real copy of options !:\n const newPublishedStreamsCache = streamsToPublish.map(elt => {\n if (elt && elt.options) {\n return { stream: elt.stream, options: { ...elt.options } }\n } else {\n return elt\n }\n });\n setPublishedStreamsCache(newPublishedStreamsCache)\n\n // Prepare a set for Streams to publish, for further optimized check\n const streamsToPublishSet = new Set(streamsToPublish.filter(notEmpty).map((item) => item.stream));\n\n // Loop on arrays index to publish new streams, or replace if necessary\n for (let i = 0; i < maxLength; i++) {\n const previous = publishedStreamsCache[i];\n const next = streamsToPublish[i];\n\n const doPublish = (obj: { stream: Stream, options?: PublishOptions }) => {\n publish(obj.stream, obj.options).catch((error: Error) => {\n newPublishedStreamsCache.splice(i, 1, null)\n if (errorCallback) {\n errorCallback(error)\n } else if (globalThis.apirtcReactLibLogLevel.isWarnEnabled) {\n console.warn(`${HOOK_NAME}|publish|error`, error)\n }\n })\n };\n\n if (previous && next) {\n\n const doUnpublishPublish = () => {\n unpublish(previous.stream)\n doPublish(next)\n };\n\n if (previous.stream === next.stream) {\n // Streams are the same, only replace if options are different\n if (JSON.stringify(previous.options) !== JSON.stringify(next.options)) {\n // replacePublishStream does not allow to change PublishOptions, so we need to\n // unpublish and republish\n doUnpublishPublish()\n }\n } else {\n // If position in both new and cached list are defined but are different:\n // replace if and only if stream to unpublish shall not be published (at other position)\n if (streamsToPublishSet.has(previous.stream)) { // previous shall be published\n // Previous shall actually be published (at another position), so don't do anything about it\n // But then we still have to publish new stream (if not already published)\n if (conversation && !conversation.isPublishedStream(next.stream)) {\n doPublish(next)\n }\n } else {\n if (conversation && !conversation.isPublishedStream(next.stream)) {\n // replacePublishStream does not allow to change PublishOptions, so we need to\n // unpublish and republish if options also change\n if (JSON.stringify(previous.options) === JSON.stringify(next.options)) {\n replacePublishedStream(previous.stream, next.stream)\n .catch((error: Error) => {\n newPublishedStreamsCache.splice(i, 1, null)\n if (errorCallback) {\n errorCallback(error)\n } else if (globalThis.apirtcReactLibLogLevel.isWarnEnabled) {\n console.warn(`${HOOK_NAME}|replacePublishedStream|error`, error)\n }\n })\n } else {\n doUnpublishPublish()\n }\n } else { // new stream is already published\n // So we shall not replace another stream by it, but we need to unpublish the previous\n unpublish(previous.stream)\n }\n }\n }\n } else if (previous && !next) {\n // If position in new list is now undefined(or null) while it was in cache:\n // unpublish if and only if stream to unpublish shall not be published (at other position)\n if (!streamsToPublishSet.has(previous.stream)) {\n unpublish(previous.stream)\n }\n } else if (!previous && next) {\n // If position in new list is valid : publish it whatever the position in cache.\n // Depending on the case the stream might be already published, or it might be not\n // (can happen if the cache was set while Conversation was not joined yet).\n // Note that we could try to publish without checking isPublishedStream, the call would\n // reject with a console error but this would not affect the behavior.\n if (conversation && !conversation.isPublishedStream(next.stream)) {\n doPublish(next)\n }\n }\n }\n }, [conversation,\n streamsToPublish,\n publishedStreamsCache,\n publish, unpublish, replacePublishedStream]);\n\n const unpublishAndUnsubscribeAll = (i_conversation: Conversation) => {\n publishedStreams.forEach(stream => {\n if (globalThis.apirtcReactLibLogLevel.isDebugEnabled) {\n console.debug(HOOK_NAME + \"|unpublish stream\", i_conversation, stream)\n }\n i_conversation.unpublish(stream)\n })\n // Clear internal array\n publishedStreams.length = 0;\n\n // Clear cache\n setPublishedStreamsCache([])\n\n subscribedStreams.forEach(stream => {\n if (globalThis.apirtcReactLibLogLevel.isDebugEnabled) {\n console.debug(HOOK_NAME + \"|unsubscribeToStream stream\", i_conversation, stream)\n }\n i_conversation.unsubscribeToStream(stream.getId())\n })\n // Clear internal array\n subscribedStreams.length = 0;\n\n // Clear output arrays with new array so that parent gets notified of a change.\n // Simply setting length to 0 is not detected by react.\n setO_PublishedStreams(new Array<Stream>())\n setO_SubscribedStreams(new Array<Stream>())\n };\n\n // --------------------------------------------------------------------------\n // useEffect(s) - Order is important\n //\n useEffect(() => {\n if (conversation) {\n const on_streamAdded = (remoteStream: Stream) => {\n if (globalThis.apirtcReactLibLogLevel.isInfoEnabled) {\n console.info(HOOK_NAME + \"|on_streamAdded\", remoteStream)\n }\n subscribedStreams.push(remoteStream)\n setO_SubscribedStreams(Array.from(subscribedStreams))\n };\n const on_streamRemoved = (remoteStream: Stream) => {\n if (globalThis.apirtcReactLibLogLevel.isInfoEnabled) {\n console.info(HOOK_NAME + \"|on_streamRemoved\", remoteStream)\n }\n const index = subscribedStreams.indexOf(remoteStream);\n if (index >= 0) {\n subscribedStreams.splice(index, 1)\n setO_SubscribedStreams(Array.from(subscribedStreams))\n }\n };\n const on_streamListChanged = (streamInfo: StreamInfo) => {\n const streamId = String(streamInfo.streamId);\n if (streamInfo.isRemote === true) {\n if (streamInfo.listEventType === 'added') {\n // a remote stream was published\n conversation.subscribeToStream(streamId)\n } else if (streamInfo.listEventType === 'removed') {\n // a remote stream is not published anymore\n conversation.unsubscribeToStream(streamId)\n }\n }\n };\n // Subscribe to incoming streams\n conversation.on('streamAdded', on_streamAdded)\n conversation.on('streamRemoved', on_streamRemoved)\n conversation.on('streamListChanged', on_streamListChanged)\n\n return () => {\n // remove listeners\n conversation.removeListener('streamListChanged', on_streamListChanged)\n conversation.removeListener('streamRemoved', on_streamRemoved)\n conversation.removeListener('streamAdded', on_streamAdded)\n\n unpublishAndUnsubscribeAll(conversation)\n }\n }\n }, [conversation])\n\n useEffect(() => {\n if (conversation) {\n if (globalThis.apirtcReactLibLogLevel.isDebugEnabled) {\n console.debug(HOOK_NAME + \"|useEffect doHandlePublication\", conversation.getName())\n }\n\n const on_joined = () => {\n if (globalThis.apirtcReactLibLogLevel.isInfoEnabled) {\n console.info(HOOK_NAME + \"|on_joined\", conversation.getName(), streamsToPublish)\n }\n doHandlePublication()\n };\n const on_left = () => {\n if (globalThis.apirtcReactLibLogLevel.isInfoEnabled) {\n console.info(HOOK_NAME + \"|on_left\", conversation.getName())\n }\n // Forcing unpublish will allow to republish if joining again\n unpublishAndUnsubscribeAll(conversation)\n };\n\n conversation.on('joined', on_joined)\n conversation.on('left', on_left)\n\n return () => {\n conversation.removeListener('joined', on_joined)\n conversation.removeListener('left', on_left)\n }\n }\n }, [doHandlePublication]) // Don't add 'conversation' in here because\n // doHandlePublication already changes on conversation change\n\n useEffect(() => {\n if (globalThis.apirtcReactLibLogLevel.isDebugEnabled) {\n console.debug(`${HOOK_NAME}|useEffect streamsToPublish`,\n JSON.stringify(streamsToPublish.map(l_s => l_s?.stream.getId() + '-' + JSON.stringify(l_s?.options))))\n }\n if (conversation && conversation.isJoined()) {\n doHandlePublication()\n }\n }, [JSON.stringify(streamsToPublish.map(l_s => l_s?.stream.getId() + '-' + JSON.stringify(l_s?.options)))])\n\n return {\n publishedStreams: o_publishedStreams,\n subscribedStreams: o_subscribedStreams,\n publish,\n unpublish,\n replacePublishedStream\n }\n}\n","import { Contact, Session } from '@apirtc/apirtc';\nimport { useEffect, useState } from 'react';\n\n/**\n * Subscribe to groups and returns contactsByGroup (of theses groups only) when updated.\n * If input groups list is updated, this hooks works diff with the previous set in order\n * to make as little as possible unsubscribe/subscribe calls.\n */\n\nconst HOOK_NAME = \"usePresence\";\nexport default function usePresence(session: Session | undefined, groups: Array<string>) {\n\n const [groupsCache] = useState<Set<string>>(new Set());\n\n const [m_contactsByGroup] = useState<Map<string, Set<Contact>>>(new Map());\n\n const [contactsByGroup, setContactsByGroup] = useState<Map<string, Set<Contact>>>(new Map());\n\n useEffect(() => {\n if (session) {\n return () => {\n m_contactsByGroup.clear()\n setContactsByGroup(new Map(m_contactsByGroup))\n groupsCache.clear()\n }\n }\n }, [session])\n\n const getOrCreateGroupSet = (group: string) => {\n const o_set = m_contactsByGroup.get(group) ?? new Set();\n if (!m_contactsByGroup.has(group)) {\n m_contactsByGroup.set(group, o_set)\n }\n return o_set\n };\n\n useEffect(() => {\n if (globalThis.apirtcReactLibLogLevel.isDebugEnabled) {\n console.debug(HOOK_NAME + \"|useEffect session, groups\", groups)\n }\n if (session) {\n const l_session = session;\n const l_groupsSet = new Set(groups);\n\n // Diff update subscription to groups\n //\n l_groupsSet.forEach(group => {\n if (!groupsCache.has(group)) {\n if (globalThis.apirtcReactLibLogLevel.isInfoEnabled) {\n console.info(HOOK_NAME + \"|subscribeToGroup\", group)\n }\n groupsCache.add(group)\n l_session.subscribeToGroup(group)\n }\n })\n\n let needsRefresh = false;\n groupsCache.forEach(group => {\n if (!l_groupsSet.has(group)) {\n if (globalThis.apirtcReactLibLogLevel.isInfoEnabled) {\n console.info(HOOK_NAME + \"|unsubscribeToGroup\", group)\n }\n l_session.unsubscribeToGroup(group)\n groupsCache.delete(group)\n m_contactsByGroup.delete(group)\n needsRefresh = true;\n }\n })\n\n if (needsRefresh) {\n // contactsByGroup is exposed, so change the Map object to let client code detect a change.\n setContactsByGroup(new Map(m_contactsByGroup))\n }\n\n if (groups.length > 0) {\n const onContactListUpdate = (updatedContacts: any) => {\n\n if (globalThis.apirtcReactLibLogLevel.isDebugEnabled) {\n console.debug(HOOK_NAME + \"|contactListUpdate\", updatedContacts)\n }\n\n let needsRefresh = false;\n\n // Maintain Map of Contacts per Group\n //\n for (const group of Object.keys(updatedContacts.joinedGroup)) {\n if (l_groupsSet.has(group)) {\n const l_set = getOrCreateGroupSet(group);\n for (const contact of updatedContacts.joinedGroup[group]) {\n l_set.add(contact)\n needsRefresh = true;\n }\n }\n }\n for (const group of Object.keys(updatedContacts.leftGroup)) {\n if (l_groupsSet.has(group)) {\n const l_set = getOrCreateGroupSet(group);\n for (const contact of updatedContacts.leftGroup[group]) {\n l_set.delete(contact)\n needsRefresh = true;\n\n // if set is empty, no need to keep the group as key in the map\n if (l_set.size === 0) {\n m_contactsByGroup.delete(group)\n }\n }\n }\n }\n\n // For data updates, trigger a refresh if and only if contact is part of managed groups\n for (const contact of updatedContacts.userDataChanged as Contact[]) {\n for (const l_contacts of m_contactsByGroup.values()) {\n if (l_contacts.has(contact)) {\n needsRefresh = true;\n break;\n }\n }\n }\n\n if (needsRefresh) {\n // contactsByGroup is exposed, so change the Map object to let client code detect a change.\n setContactsByGroup(new Map(m_contactsByGroup))\n }\n };\n l_session.on('contactListUpdate', onContactListUpdate)\n return () => {\n l_session.removeListener('contactListUpdate', onContactListUpdate)\n }\n }\n }\n }, [session, JSON.stringify(groups)])\n\n return {\n contactsByGroup\n }\n}","import { RegisterInformation, Session, UserAgent } from '@apirtc/apirtc';\nimport { useEffect, useState } from 'react';\n\nexport type LoginPassword = {\n username: string\n password: string\n};\nfunction isInstanceOfLoginPassword(object: any): object is LoginPassword {\n if (typeof object !== 'object') return false;\n return 'username' in object;\n}\n\nexport type ApiKey = { apiKey: string };\nfunction isInstanceOfApiKey(object: any): object is ApiKey {\n if (typeof object !== 'object') return false;\n return 'apiKey' in object;\n}\n\nexport type Token = { token: string };\nfunction isInstanceOfToken(object: any): object is Token {\n if (typeof object !== 'object') return false;\n return 'token' in object;\n}\n\nexport type Credentials = LoginPassword | ApiKey | Token;\n\nconst HOOK_NAME = \"useSession\";\nexport default function useSession(credentials?: Credentials, options?: RegisterInformation,\n errorCallback?: (error: any) => void) {\n\n const [session, setSession] = useState<Session | undefined>();\n const [connecting, setConnecting] = useState<boolean>(false);\n\n useEffect(() => {\n if (globalThis.apirtcReactLibLogLevel.isDebugEnabled) {\n console.debug(HOOK_NAME + \"|useEffect credentials, options\", credentials, options)\n }\n if (credentials) {\n // To fix errors like \"Warning: Can't perform a React state update on an unmounted component\"\n // https://stackoverflow.com/questions/53949393/cant-perform-a-react-state-update-on-an-unmounted-component\n //let isMounted = true;\n connect(credentials, options).catch((error: any) => {\n console.error(HOOK_NAME + \"|connection failed\", error)\n setSession(undefined)\n\n if (errorCallback) {\n errorCallback(error)\n } else if (globalThis.apirtcReactLibLogLevel.isWarnEnabled) {\n console.warn(`${HOOK_NAME}|connect|error`, error)\n }\n })\n return () => {\n setSession(undefined)\n // Even though connecting is managed in connect(),\n // mark connecting to false when credentials are changed\n // as this shall be way to connect elsewhere or connect to\n // with other credentials. Note that to be perfect we should\n // cancel the potentially running connect : Is that possible with ApiRTC ?\n setConnecting(false)\n }\n }\n }, [JSON.stringify(credentials), JSON.stringify(options)])\n\n useEffect(() => {\n if (globalThis.apirtcReactLibLogLevel.isDebugEnabled) {\n console.debug(HOOK_NAME + \"|useEffect session\", session)\n }\n if (session) {\n const l_session = session;\n return () => {\n l_session.disconnect().then(() => {\n if (globalThis.apirtcReactLibLogLevel.isInfoEnabled) {\n console.info(HOOK_NAME + \"|disconnected\", l_session)\n }\n }).catch((error: any) => {\n console.error(HOOK_NAME + \"|disconnect\", error)\n })\n }\n }\n }, [session])\n\n const connect = (credentials: Credentials | undefined, options?: RegisterInformation) => {\n return new Promise<void>((resolve, reject) => {\n const registerInformation: RegisterInformation = options ? options : {\n cloudUrl: 'https://cloud.apirtc.com',\n };\n\n let l_userAgent;\n\n if (isInstanceOfLoginPassword(credentials)) {\n registerInformation.password = credentials.password;\n l_userAgent = new UserAgent({\n uri: 'apirtc:' + credentials.username\n });\n } else if (isInstanceOfApiKey(credentials)) {\n l_userAgent = new UserAgent({\n uri: `apiKey:${credentials.apiKey}`\n });\n } else if (isInstanceOfToken(credentials)) {\n l_userAgent = new UserAgent({\n uri: `token:${credentials.token}`\n });\n } else {\n reject(\"credentials not recognized\")\n return\n }\n\n setConnecting(true)\n l_userAgent.register(registerInformation).then(l_session => {\n if (globalThis.apirtcReactLibLogLevel.isInfoEnabled) {\n console.info(HOOK_NAME + \"|connected\", l_session)\n }\n setSession(l_session)\n resolve()\n }).catch((error: any) => {\n reject(error)\n }).finally(() => {\n setConnecting(false)\n })\n })\n };\n\n // const disconnect = useCallback(() => {\n // return new Promise<void>((resolve, reject) => {\n // if (session) {\n // const l_session = session;\n // l_session.disconnect().then(() => {\n // console.log(HOOK_NAME + \"|disconnected\", l_session)\n // setSession(undefined)\n // resolve()\n // }).catch((error: any) => {\n // console.error(HOOK_NAME + \"|disconnect\", error)\n // reject(error)\n // })\n // } else {\n // resolve()\n // }\n // })\n // }, [session])\n\n const disconnect = () => {\n setSession(undefined)\n };\n\n return {\n //userAgent: userAgent, // can get it from session\n session: session,\n connecting,\n connect,\n disconnect\n }\n}\n","import { Stream, VideoProcessorOptions } from '@apirtc/apirtc';\nimport { useEffect, useState } from 'react';\n\nconst HOOK_NAME = \"useStreamApplyVideoProcessor\";\n/**\n * This hook takes stream passed as parameter, and\n * returns either this stream or a stream with video processor applied.\n * This is controlled by the videoProcessorType input attribute.\n * By default the output stream is the input stream.\n * The hook fully manages the output stream (applies 'none' if input stream is set to undefined).\n * The hook never releases the input stream.\n * \n * @param stream\n * @param videoProcessorType\n * @param {VideoProcessorOptions} options\n * @returns new stream with video processor applied (or original stream if no processor applied)\n */\nexport default function useStreamApplyVideoProcessor(\n stream: Stream | undefined,\n videoProcessorType: 'none' | 'blur' | 'backgroundImage', options?: VideoProcessorOptions,\n errorCallback?: (error: any) => void) {\n //\n const [outStream, setOutStream] = useState(stream);\n const [applied, setApplied] = useState<'none' | 'blur' | 'backgroundImage'>(stream ? (stream as any).videoAppliedFilter : 'none');\n\n useEffect(() => {\n if (globalThis.apirtcReactLibLogLevel.isDebugEnabled) {\n console.debug(HOOK_NAME + \"|useEffect\", stream, videoProcessorType, options, stream ? JSON.stringify((stream as any).children) : \"empty\")\n }\n if (stream) {\n stream.applyVideoProcessor(videoProcessorType, options).then(l_stream => {\n setOutStream(l_stream)\n setApplied(videoProcessorType)\n }).catch(error => {\n setOutStream(stream)\n setApplied((stream as any).videoAppliedFilter)\n if (errorCallback) {\n errorCallback(error)\n } else if (globalThis.apirtcReactLibLogLevel.isWarnEnabled) {\n console.warn(HOOK_NAME + \"|useEffect\", stream, videoProcessorType, options, error)\n }\n })\n } else {\n setOutStream(stream)\n setApplied('none')\n }\n }, [stream, videoProcessorType, JSON.stringify(options)])\n\n return {\n stream: outStream,\n applied\n }\n}","import { MediaDevice, MediaDeviceList, Session, UserAgent } from '@apirtc/apirtc';\nimport { useEffect, useState } from 'react';\n\nconst EMPTY_LIST: MediaDeviceList = { audioinput: {}, audiooutput: {}, videoinput: {} };\n\nconst HOOK_NAME = \"useUserMediaDevices\";\nexport default function useUserMediaDevices(\n session: Session | undefined,\n storageKeyPrefix: string = \"apirtc\"\n) {\n const [userMediaDevices, setUserMediaDevices] = useState<MediaDeviceList>(EMPTY_LIST);\n\n const [selectedAudioIn, setSelectedAudioIn] = useState<MediaDevice>();\n const [selectedAudioOut, setSelectedAudioOut] = useState<MediaDevice>();\n const [selectedVideoIn, setSelectedVideoIn] = useState<MediaDevice>();\n\n const AUDIO_INPUT_ID_KEY = storageKeyPrefix + 'audioInputId';\n const AUDIO_OUTPUT_ID_KEY = storageKeyPrefix + 'audioOutputId';\n const VIDEO_INPUT_ID_KEY = storageKeyPrefix + 'videoInputId';\n\n useEffect(() => {\n if (session) {\n const userAgent: UserAgent = session.getUserAgent();\n\n const on_mediaDeviceChanged = () => {\n const mediaDevices: MediaDeviceList = userAgent.getUserMediaDevices()\n if (globalThis.apirtcReactLibLogLevel.isInfoEnabled) {\n console.info(HOOK_NAME + \"|mediaDeviceChanged\", mediaDevices)\n }\n setUserMediaDevices(mediaDevices)\n };\n userAgent.on('mediaDeviceChanged', on_mediaDeviceChanged)\n\n return () => {\n userAgent.removeListener('mediaDeviceChanged', on_mediaDeviceChanged)\n setUserMediaDevices(EMPTY_LIST)\n }\n }\n }, [session])\n\n useEffect(() => {\n const audioInputId = localStorage.getItem(AUDIO_INPUT_ID_KEY);\n const audioOutputId = localStorage.getItem(AUDIO_OUTPUT_ID_KEY);\n const videoInputId = localStorage.getItem(VIDEO_INPUT_ID_KEY);\n\n if (globalThis.apirtcReactLibLogLevel.isDebugEnabled) {\n console.debug(HOOK_NAME + '|userMediaDevices, audioInputId, audioOutputId, videoInputId', userMediaDevices, audioInputId, audioOutputId, videoInputId)\n }\n\n if (audioInputId && userMediaDevices.audioinput[audioInputId]) {\n setSelectedAudioIn(userMediaDevices.audioinput[audioInputId])\n }\n if (audioOutputId && userMediaDevices.audiooutput[audioOutputId]) {\n setSelectedAudioOut(userMediaDevices.audiooutput[audioOutputId])\n }\n if (videoInputId && userMediaDevices.videoinput[videoInputId]) {\n setSelectedVideoIn(userMediaDevices.videoinput[videoInputId])\n }\n }, [userMediaDevices])\n\n useEffect(() => {\n if (selectedAudioIn) {\n if (globalThis.apirtcReactLibLogLevel.isDebugEnabled) {\n console.debug(HOOK_NAME + '|Storing audioInputId', selectedAudioIn.getId())\n }\n localStorage.setItem(AUDIO_INPUT_ID_KEY, selectedAudioIn.getId())\n }\n }, [selectedAudioIn])\n\n useEffect(() => {\n if (selectedAudioOut) {\n if (globalThis.apirtcReactLibLogLevel.isDebugEnabled) {\n console.debug(HOOK_NAME + '|Storing audioOutputId', selectedAudioOut.getId())\n }\n localStorage.setItem(AUDIO_OUTPUT_ID_KEY, selectedAudioOut.getId())\n }\n }, [selectedAudioOut])\n\n useEffect(() => {\n if (selectedVideoIn) {\n if (globalThis.apirtcReactLibLogLevel.isDebugEnabled) {\n console.debug(HOOK_NAME + '|Storing videoInputId', selectedVideoIn.getId())\n }\n localStorage.setItem(VIDEO_INPUT_ID_KEY, selectedVideoIn.getId())\n }\n }, [selectedVideoIn])\n\n return {\n userMediaDevices,\n selectedAudioIn, setSelectedAudioIn,\n selectedAudioOut, setSelectedAudioOut,\n selectedVideoIn, setSelectedVideoIn\n }\n}","export * from './components'\nexport * from './hooks'\n\nexport type LogLevel = {\n level: 'debug' | 'info' | 'warn' | 'error'\n isDebugEnabled: boolean\n isInfoEnabled: boolean\n isWarnEnabled: boolean\n}\n\nconst INFO: LogLevel = { level: 'info', isDebugEnabled: false, isInfoEnabled: true, isWarnEnabled: true };\n\ndeclare global {\n var apirtcReactLibLogLevel: LogLevel;\n var setApirtcReactLibLogLevel: (logLevelText: 'debug' | 'info' | 'warn' | 'error') => void;\n}\n\n// a default value MUST be set in case application using the library does not override it\nglobalThis.apirtcReactLibLogLevel = INFO;\n\nexport function setLogLevel(logLevelText: 'debug' | 'info' | 'warn' | 'error') {\n switch (logLevelText) {\n case 'debug':\n globalThis.apirtcReactLibLogLevel = { level: 'debug', isDebugEnabled: true, isInfoEnabled: true, isWarnEnabled: true };\n break\n case 'info':\n globalThis.apirtcReactLibLogLevel = INFO;\n break\n case 'warn':\n globalThis.apirtcReactLibLogLevel = { level: 'warn', isDebugEnabled: false, isInfoEnabled: false, isWarnEnabled: true };\n break\n case 'error':\n globalThis.apirtcReactLibLogLevel = { level: 'error', isDebugEnabled: false, isInfoEnabled: false, isWarnEnabled: false };\n break\n default:\n // in case null is passed as input, default to 'info'\n globalThis.apirtcReactLibLogLevel = INFO;\n }\n return globalThis.apirtcReactLibLogLevel\n}\n\nglobalThis.setApirtcReactLibLogLevel = setLogLevel;\n","import React, { useEffect, useRef } from 'react';\n\nimport { Stream } from '@apirtc/apirtc';\n\nexport type VideoStreamProps = {\n stream: Stream,\n autoPlay?: boolean,\n muted?: boolean\n};\nexport default function VideoStream(props: VideoStreamProps) {\n\n const { autoPlay = true } = props;\n\n const videoRef = useRef<HTMLVideoElement>(null)\n\n useEffect(() => {\n const ref = videoRef.current;\n if (ref && props.stream) {\n props.stream.attachToElement(ref)\n return () => {\n ref.src = \"\";\n }\n }\n }, [props.stream])\n // No need to put videoRef.current because useRef does not trigger rerender anyways\n\n return <video id={props.stream.getId()} style={{ maxWidth: '100%' }}\n ref={videoRef}\n autoPlay={autoPlay}\n muted={props.muted}></video>\n}"],"names":["HOOK_NAME","notEmpty","value","EMPTY_LIST","audioinput","audiooutput","videoinput","INFO","level","isDebugEnabled","isInfoEnabled","isWarnEnabled","setLogLevel","logLevelText","globalThis","apirtcReactLibLogLevel","setApirtcReactLibLogLevel","props","autoPlay","videoRef","useRef","useEffect","ref","current","stream","attachToElement","src","React","createElement","id","getId","style","maxWidth","muted","session","options","setStream","useState","getUserAgent","createStream","then","localStream","console","info","catch","error","undefined","JSON","stringify","release","name","join","conversation","setConversation","joined","setJoined","joining","setJoining","o_join","useCallback","debug","Promise","resolve","reject","isJoined","finally","o_leave","leave","l_conversation","getOrCreateConversation","warn","destroy","l_join","messages","Array","o_messages","setO_Messages","onMessage","message","getName","push","from","on","removeListener","length","sendMessage","msgContent","sender","uuid","content","time","Date","onEjected","onEjectedSelf","candidates","setCandidates","Set","on_contactJoinedWaitingRoom","contact","add","on_contactLeftWaitingRoom","delete","on_participantEjected","data","self","streamsToPublish","errorCallback","map","obj","publishedStreamsCache","setPublishedStreamsCache","publishedStreams","o_publishedStreams","setO_PublishedStreams","subscribedStreams","o_subscribedStreams","setO_SubscribedStreams","publish","replacePublishedStream","oldStream","newStream","conversationCall","getConversationCall","index","indexOf","splice","unpublish","doHandlePublication","maxLength","Math","max","l_s","newPublishedStreamsCache","elt","Object","assign","streamsToPublishSet","filter","item","i","previous","next","doPublish","doUnpublishPublish","has","isPublishedStream","unpublishAndUnsubscribeAll","i_conversation","forEach","unsubscribeToStream","on_streamAdded","remoteStream","on_streamRemoved","on_streamListChanged","streamInfo","streamId","String","isRemote","listEventType","subscribeToStream","on_joined","on_left","groups","groupsCache","m_contactsByGroup","Map","contactsByGroup","setContactsByGroup","clear","getOrCreateGroupSet","group","o_set","_a","get","set","l_session","l_groupsSet","subscribeToGroup","needsRefresh","unsubscribeToGroup","onContactListUpdate","updatedContacts","keys","joinedGroup","l_set","leftGroup","size","userDataChanged","l_contacts","values","credentials","setSession","connecting","setConnecting","connect","disconnect","registerInformation","cloudUrl","l_userAgent","object","password","UserAgent","uri","username","isInstanceOfApiKey","apiKey","isInstanceOfToken","token","register","videoProcessorType","outStream","setOutStream","applied","setApplied","videoAppliedFilter","children","applyVideoProcessor","l_stream","storageKeyPrefix","userMediaDevices","setUserMediaDevices","selectedAudioIn","setSelectedAudioIn","selectedAudioOut","setSelectedAudioOut","selectedVideoIn","setSelectedVideoIn","AUDIO_INPUT_ID_KEY","AUDIO_OUTPUT_ID_KEY","VIDEO_INPUT_ID_KEY","userAgent","on_mediaDeviceChanged","mediaDevices","getUserMediaDevices","audioInputId","localStorage","getItem","audioOutputId","videoInputId","setItem"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"react-lib.production.min.js","sources":["../src/hooks/useCameraStream.ts","../src/hooks/useConversation.ts","../src/hooks/useConversationMessages.ts","../src/hooks/useConversationModeration.ts","../src/hooks/useConversationStreams.ts","../src/hooks/usePresence.ts","../src/hooks/useSession.ts","../src/hooks/useStreamApplyVideoProcessor.ts","../src/hooks/useUserMediaDevices.ts","../src/index.ts","../src/components/VideoStream/VideoStream.tsx"],"sourcesContent":["import { CreateStreamOptions, Session, Stream, UserAgent } from '@apirtc/apirtc';\nimport { useEffect, useState } from 'react';\n\nconst HOOK_NAME = \"useCameraStream\";\nexport default function useCameraStream(\n session: Session | undefined,\n options: CreateStreamOptions = {}\n) {\n const [stream, setStream] = useState<Stream>();\n\n useEffect(() => {\n if (session) {\n const userAgent: UserAgent = session.getUserAgent();\n userAgent.createStream(options).then((localStream: Stream) => {\n if (globalThis.apirtcReactLibLogLevel.isInfoEnabled) {\n console.info(HOOK_NAME + \"|createStream\", options, localStream)\n }\n setStream(localStream)\n }).catch((error: any) => {\n console.error(HOOK_NAME + \"|createStream\", options, error)\n setStream(undefined)\n })\n\n // DO NOT set out stream to undefined in the return, to prevent unnecessary refreshes\n // of other components with undefined stream, whereas we are expecting to change it\n // to another instance..\n // return () => { setStream(undefined) } // DON'T\n } else {\n setStream(undefined)\n }\n\n }, [session, JSON.stringify(options)])\n\n useEffect(() => {\n return () => {\n if (stream) {\n if (globalThis.apirtcReactLibLogLevel.isInfoEnabled) {\n console.info(HOOK_NAME + \"|release stream\", stream)\n }\n stream.release()\n }\n }\n }, [stream])\n\n return {\n stream\n }\n}","import { Conversation, GetOrCreateConversationOptions, Session } from '@apirtc/apirtc';\nimport { useCallback, useEffect, useState } from 'react';\n\nconst HOOK_NAME = \"useConversation\";\n/**\n * A hook to getOrCreate a named conversation and manage join/leave\n * @param session an ApiRTC Session\n * @param name the conversation name\n * @param options getOrCreateConversation options\n * @param join true by default.\n */\nexport default function useConversation(\n session: Session | undefined,\n name: string | undefined,\n options?: GetOrCreateConversationOptions,\n join: boolean = true\n) {\n const [conversation, setConversation] = useState<Conversation>();\n const [joined, setJoined] = useState<boolean>(false);\n const [joining, setJoining] = useState<boolean>(false);\n\n // Callbacks\n //\n // Offering Promised join/leave methods allows developer to act on then/catch\n //\n const o_join = useCallback(() => {\n if (globalThis.apirtcReactLibLogLevel.isDebugEnabled) {\n console.debug(HOOK_NAME + \"|join\", conversation)\n //JSON.stringify((apiRTC as any).session.apiCCWebRTCClient.webRTCClient.MCUClient.sessionMCUs))\n }\n return new Promise<void>((resolve, reject) => {\n if (!conversation) {\n reject(HOOK_NAME + \"|join|conversation not defined\")\n return\n }\n if (!conversation.isJoined()) {\n setJoining(true)\n conversation.join().then(() => {\n // successfully joined the conversation.\n setJoined(true)\n resolve()\n }).catch((error: any) => {\n // could not join the conversation.\n reject(error)\n }).finally(() => {\n setJoining(false)\n })\n } else {\n reject(HOOK_NAME + \"|join|conversation already joined\")\n }\n })\n }, [conversation]);\n\n const o_leave = useCallback(() => {\n if (globalThis.apirtcReactLibLogLevel.isDebugEnabled) {\n console.debug(HOOK_NAME + \"|leave\", conversation)\n }\n return new Promise<void>((resolve, reject) => {\n if (!conversation) {\n reject(HOOK_NAME + \"|leave|conversation not defined\")\n return\n }\n if (conversation.isJoined()) {\n conversation.leave().then(() => {\n // local user successfully left the conversation.\n setJoined(false)\n resolve()\n }).catch((error: any) => {\n reject(error)\n })\n } else {\n reject(HOOK_NAME + \"|leave|conversation is not joined\")\n }\n })\n }, [conversation]);\n\n // Effects\n //\n useEffect(() => {\n if (session && name) {\n if (globalThis.apirtcReactLibLogLevel.isDebugEnabled) {\n console.debug(HOOK_NAME + \"|getOrCreateConversation\", name, options, join)\n }\n const l_conversation = session.getOrCreateConversation(name, options);\n setConversation(l_conversation)\n return () => {\n if (globalThis.apirtcReactLibLogLevel.isDebugEnabled) {\n console.debug(HOOK_NAME + \"|useEffect cleanup\", name, options, join)\n }\n if (l_conversation.isJoined()) {\n l_conversation.leave()\n .then(() => { })\n .catch((error: any) => {\n if (globalThis.apirtcReactLibLogLevel.isWarnEnabled) {\n console.warn(HOOK_NAME + \"|useEffect conversation.leave()\", error)\n }\n })\n .finally(() => {\n l_conversation.destroy()\n // SHOULD NOT touch the state here as this async and the conversation may have already changed\n })\n } else {\n // It is important to destroy the conversation.\n // Otherwise subsequent getOrCreateConversation with same name would get\n // previous handle, regardless of the potentially new options.\n // This also allows to cleanup memory\n l_conversation.destroy()\n }\n // In any cases, update state accordingly\n // Note: this is done here synchronously, this shall NOT be done in the leave().finally to prevent\n // overriding a potential conversation change\n setConversation(undefined)\n setJoined(false)\n }\n }\n }, [session, name, JSON.stringify(options)])\n\n useEffect(() => {\n if (conversation && join) {\n if (globalThis.apirtcReactLibLogLevel.isDebugEnabled) {\n console.debug(HOOK_NAME + \"|useEffect\", conversation, join)\n }\n const l_conversation = conversation;\n const l_join = join;\n if (l_join) {\n setJoining(true)\n l_conversation.join().then(() => {\n if (globalThis.apirtcReactLibLogLevel.isInfoEnabled) {\n console.info(HOOK_NAME + \"|joined\", l_conversation)\n }\n setJoined(true)\n }).catch((error: any) => {\n if (globalThis.apirtcReactLibLogLevel.isWarnEnabled) {\n console.warn(HOOK_NAME + \"|useEffect conversation.join()\", error)\n }\n }).finally(() => {\n setJoining(false)\n })\n }\n return () => {\n if (globalThis.apirtcReactLibLogLevel.isDebugEnabled) {\n console.debug(HOOK_NAME + \"|useEffect cleanup\", l_conversation, l_join)\n }\n if (l_conversation.isJoined()) {\n l_conversation.leave().then(() => {\n setJoined(false)\n }).catch((error: any) => {\n if (globalThis.apirtcReactLibLogLevel.isWarnEnabled) {\n console.warn(HOOK_NAME + \"|useEffect conversation.leave()\", error)\n }\n })\n }\n }\n }\n }, [conversation, join])\n\n return {\n conversation,\n joining,\n joined,\n join: o_join,\n leave: o_leave\n }\n}","import { Contact, Conversation, ConversationMessage } from '@apirtc/apirtc';\nimport { useCallback, useEffect, useState } from 'react';\n\n// TODO : get and handle with pagination messages history\n// TODO : ask apirtc to include the uuid in ConversationMessage so that we can store it\n// into ConversationMessage when creating the local one, and we get it from conversation on:message\n// the uuid shall be the value used as a react child key when displaying list of messages\n\nconst HOOK_NAME = \"useConversationMessages\";\nexport default function useConversationMessages(\n conversation: Conversation | undefined,\n) {\n // Use an internal array which will always be the same object as far as React knows\n // This will avoid the need for adding it as a dependency for each callback\n const [messages] = useState<Array<ConversationMessage>>(new Array<ConversationMessage>());\n // And use a copy as output array so that client code will react upon change\n // (only a new instance of array is detected by React)\n const [o_messages, setO_Messages] = useState<Array<ConversationMessage>>(new Array<ConversationMessage>());\n\n useEffect(() => {\n if (conversation) {\n const onMessage = (message: ConversationMessage) => {\n if (globalThis.apirtcReactLibLogLevel.isInfoEnabled) {\n console.info(HOOK_NAME + \"|on:message:\", conversation.getName(), message)\n }\n messages.push(message)\n setO_Messages(Array.from(messages))\n };\n conversation.on('message', onMessage)\n\n return () => {\n conversation.removeListener('message', onMessage)\n messages.length = 0;\n setO_Messages(new Array<any>())\n }\n }\n }, [conversation])\n\n const sendMessage = useCallback((msgContent: string, sender: Contact) => {\n return new Promise<void>((resolve, reject) => {\n conversation?.sendMessage(msgContent)\n .then((uuid: number) => {\n if (globalThis.apirtcReactLibLogLevel.isInfoEnabled) {\n console.info(HOOK_NAME + \"|sentMessage\", conversation.getName(), uuid, msgContent)\n }\n messages.push({ content: msgContent, sender: sender, time: new Date() })\n setO_Messages(Array.from(messages))\n resolve()\n })\n .catch((error: any) => {\n if (globalThis.apirtcReactLibLogLevel.isWarnEnabled) {\n console.warn(HOOK_NAME + \"|sendMessage error\", error)\n }\n reject(error)\n })\n })\n }, [conversation]);\n\n return {\n messages: o_messages,\n sendMessage\n }\n}","import { Contact, Conversation } from '@apirtc/apirtc';\nimport { useEffect, useState } from 'react';\n\nconst HOOK_NAME = \"useConversationModeration\";\nexport default function useConversationModeration(\n conversation: Conversation | undefined,\n onEjected?: (contact: Contact) => void,\n onEjectedSelf?: () => void) {\n\n const [candidates, setCandidates] = useState<Set<Contact>>(new Set<Contact>());\n\n useEffect(() => {\n if (globalThis.apirtcReactLibLogLevel.isDebugEnabled) {\n console.debug(HOOK_NAME + \"|useEffect conversation\", conversation)\n }\n\n if (conversation) {\n const on_contactJoinedWaitingRoom = (contact: Contact) => {\n if (globalThis.apirtcReactLibLogLevel.isInfoEnabled) {\n console.info(HOOK_NAME + \"|on:contactJoinedWaitingRoom\", contact)\n }\n // A candidate joined the waiting room.\n candidates.add(contact)\n setCandidates(new Set(candidates))\n };\n const on_contactLeftWaitingRoom = (contact: Contact) => {\n if (globalThis.apirtcReactLibLogLevel.isInfoEnabled) {\n console.info(HOOK_NAME + \"|on:contactLeftWaitingRoom\", contact)\n }\n // A candidate left the waiting room.\n candidates.delete(contact)\n setCandidates(new Set(candidates))\n };\n // TODO make apirtc.d.ts update to replace 'any'\n const on_participantEjected = (data: any) => {\n if (globalThis.apirtcReactLibLogLevel.isInfoEnabled) {\n console.info(HOOK_NAME + \"|on:participantEjected\", data)\n }\n if (data.self === true) {\n if (globalThis.apirtcReactLibLogLevel.isInfoEnabled) {\n console.info(HOOK_NAME + \"|Self participant was ejected\")\n }\n if (onEjectedSelf) {\n onEjectedSelf()\n }\n } else {\n if (onEjected) {\n onEjected(data.contact)\n }\n }\n };\n\n conversation\n .on('contactJoinedWaitingRoom', on_contactJoinedWaitingRoom)\n .on('contactLeftWaitingRoom', on_contactLeftWaitingRoom)\n .on('participantEjected', on_participantEjected)\n\n return () => {\n if (globalThis.apirtcReactLibLogLevel.isDebugEnabled) {\n console.debug(HOOK_NAME + \"|conversation clear\", conversation)\n }\n // remove listeners\n conversation\n .removeListener('contactJoinedWaitingRoom', on_contactJoinedWaitingRoom)\n .removeListener('contactLeftWaitingRoom', on_contactLeftWaitingRoom)\n .removeListener('participantEjected', on_participantEjected)\n setCandidates(new Set())\n }\n }\n }, [conversation])\n\n return {\n candidates\n }\n}","import { Conversation, PublishOptions, Stream, StreamInfo } from '@apirtc/apirtc';\nimport { useCallback, useEffect, useState } from 'react';\n\n// TODO?: add pagination ?\n// interface Options {\n// streamsSubscribePageSize: number\n// }\n\nfunction notEmpty<T>(value: T | null | undefined): value is T {\n return value !== null && value !== undefined;\n}\n\nconst HOOK_NAME = \"useConversationStreams\";\nexport default function useConversationStreams(\n conversation: Conversation | undefined,\n /** fully managed list of Stream(s) to publish, with associated publish options */\n streamsToPublish: Array<{ stream: Stream, options?: PublishOptions } | undefined | null> = [],\n errorCallback?: (error: any) => void\n) {\n\n if (globalThis.apirtcReactLibLogLevel.isDebugEnabled) {\n console.debug(`${HOOK_NAME}|hook render`, streamsToPublish.map((obj) => obj?.options))\n }\n\n // A cache to handle publication differences\n const [publishedStreamsCache, setPublishedStreamsCache] =\n useState<Array<{ stream: Stream, options?: PublishOptions } | undefined | null>>([]);\n\n // Use an internal array which will always be the same object as far as React knows\n // This will avoid the need for adding it as a dependency for each callback\n const [publishedStreams] = useState<Array<Stream>>(new Array<Stream>());\n // And use a copy as output array so that client code will react upon change\n // (only a new instance of array is detected by React)\n const [o_publishedStreams, setO_PublishedStreams] = useState<Array<Stream>>(new Array<Stream>());\n\n const [subscribedStreams] = useState<Array<Stream>>(new Array<Stream>());\n const [o_subscribedStreams, setO_SubscribedStreams] = useState<Array<Stream>>(new Array<Stream>());\n\n const publish: (localStream: Stream, options?: PublishOptions) => Promise<Stream> =\n useCallback((localStream: Stream, options?: PublishOptions) => {\n return new Promise<Stream>((resolve, reject) => {\n if (conversation) {\n if (globalThis.apirtcReactLibLogLevel.isDebugEnabled) {\n console.debug(`${HOOK_NAME}|publish|${conversation.getName()}`, localStream, options)\n }\n conversation.publish(localStream, options).then((stream: Stream) => {\n if (globalThis.apirtcReactLibLogLevel.isInfoEnabled) {\n console.info(`${HOOK_NAME}|published|${conversation.getName()}`, stream)\n }\n //console.log(`PUSHING ${stream.getId()} to publishedStreams`, JSON.stringify(publishedStreams.map(s => s.getId())))\n publishedStreams.push(stream)\n // Returning a new array makes lets React detect changes\n setO_PublishedStreams(Array.from(publishedStreams))\n resolve(stream)\n }).catch((error: any) => {\n reject(error)\n })\n }\n })\n }, [conversation]);\n\n const replacePublishedStream = useCallback((oldStream: Stream, newStream: Stream) => {\n return new Promise<Stream>((resolve, reject) => {\n if (conversation) {\n if (globalThis.apirtcReactLibLogLevel.isDebugEnabled) {\n console.debug(`${HOOK_NAME}|replacePublishedStream|${conversation.getName()}|${oldStream.getId()} -> ${newStream.getId()}`)\n }\n const conversationCall = conversation.getConversationCall(oldStream);\n if (conversationCall) {\n conversationCall.replacePublishedStream(newStream)\n .then((stream: Stream) => {\n if (globalThis.apirtcReactLibLogLevel.isInfoEnabled) {\n console.info(`${HOOK_NAME}|stream replaced|${conversation.getName()}`, oldStream, stream)\n }\n const index = publishedStreams.indexOf(oldStream);\n if (index >= 0) {\n publishedStreams.splice(index, 1, stream)\n setO_PublishedStreams(Array.from(publishedStreams))\n }\n resolve(stream)\n }).catch((error: any) => {\n reject(error)\n })\n }\n }\n })\n }, [conversation]);\n\n const unpublish: (localStream: Stream) => void = useCallback((localStream: Stream) => {\n if (conversation) {\n if (globalThis.apirtcReactLibLogLevel.isDebugEnabled) {\n console.debug(`${HOOK_NAME}|unpublish|${conversation.getName()}`, localStream)\n }\n conversation.unpublish(localStream)\n const index = publishedStreams.indexOf(localStream);\n if (index >= 0) {\n publishedStreams.splice(index, 1)\n setO_PublishedStreams(Array.from(publishedStreams))\n }\n }\n }, [conversation]);\n\n const doHandlePublication = useCallback(() => {\n const maxLength = Math.max(publishedStreamsCache.length, streamsToPublish.length);\n if (globalThis.apirtcReactLibLogLevel.isDebugEnabled) {\n console.debug(HOOK_NAME + \"|doHandlePublication\", streamsToPublish,\n JSON.stringify(publishedStreamsCache.map(l_s => l_s?.stream.getId())), maxLength)\n }\n\n // Strategy for published streams cache is to initialize it as it should be\n // and remove items if publication fails.\n //const newPublishedStreamsCache = [...streamsToPublish];\n // Need to do a real copy of options !:\n const newPublishedStreamsCache = streamsToPublish.map(elt => {\n if (elt && elt.options) {\n return { stream: elt.stream, options: { ...elt.options } }\n } else {\n return elt\n }\n });\n setPublishedStreamsCache(newPublishedStreamsCache)\n\n // Prepare a set for Streams to publish, for further optimized check\n const streamsToPublishSet = new Set(streamsToPublish.filter(notEmpty).map((item) => item.stream));\n\n // Loop on arrays index to publish new streams, or replace if necessary\n for (let i = 0; i < maxLength; i++) {\n const previous = publishedStreamsCache[i];\n const next = streamsToPublish[i];\n\n const doPublish = (obj: { stream: Stream, options?: PublishOptions }) => {\n publish(obj.stream, obj.options).catch((error: Error) => {\n newPublishedStreamsCache.splice(i, 1, null)\n if (errorCallback) {\n errorCallback(error)\n } else if (globalThis.apirtcReactLibLogLevel.isWarnEnabled) {\n console.warn(`${HOOK_NAME}|publish|error`, error)\n }\n })\n };\n\n if (previous && next) {\n\n const doUnpublishPublish = () => {\n unpublish(previous.stream)\n doPublish(next)\n };\n\n if (previous.stream === next.stream) {\n // Streams are the same, only replace if options are different\n if (JSON.stringify(previous.options) !== JSON.stringify(next.options)) {\n // replacePublishStream does not allow to change PublishOptions, so we need to\n // unpublish and republish\n doUnpublishPublish()\n }\n } else {\n // If position in both new and cached list are defined but are different:\n // replace if and only if stream to unpublish shall not be published (at other position)\n if (streamsToPublishSet.has(previous.stream)) { // previous shall be published\n // Previous shall actually be published (at another position), so don't do anything about it\n // But then we still have to publish new stream (if not already published)\n if (conversation && !conversation.isPublishedStream(next.stream)) {\n doPublish(next)\n }\n } else {\n if (conversation && !conversation.isPublishedStream(next.stream)) {\n // replacePublishStream does not allow to change PublishOptions, so we need to\n // unpublish and republish if options also change\n if (JSON.stringify(previous.options) === JSON.stringify(next.options)) {\n replacePublishedStream(previous.stream, next.stream)\n .catch((error: Error) => {\n newPublishedStreamsCache.splice(i, 1, null)\n if (errorCallback) {\n errorCallback(error)\n } else if (globalThis.apirtcReactLibLogLevel.isWarnEnabled) {\n console.warn(`${HOOK_NAME}|replacePublishedStream|error`, error)\n }\n })\n } else {\n doUnpublishPublish()\n }\n } else { // new stream is already published\n // So we shall not replace another stream by it, but we need to unpublish the previous\n unpublish(previous.stream)\n }\n }\n }\n } else if (previous && !next) {\n // If position in new list is now undefined(or null) while it was in cache:\n // unpublish if and only if stream to unpublish shall not be published (at other position)\n if (!streamsToPublishSet.has(previous.stream)) {\n unpublish(previous.stream)\n }\n } else if (!previous && next) {\n // If position in new list is valid : publish it whatever the position in cache.\n // Depending on the case the stream might be already published, or it might be not\n // (can happen if the cache was set while Conversation was not joined yet).\n // Note that we could try to publish without checking isPublishedStream, the call would\n // reject with a console error but this would not affect the behavior.\n if (conversation && !conversation.isPublishedStream(next.stream)) {\n doPublish(next)\n }\n }\n }\n }, [conversation,\n streamsToPublish,\n publishedStreamsCache,\n publish, unpublish, replacePublishedStream]);\n\n const unpublishAndUnsubscribeAll = (i_conversation: Conversation) => {\n publishedStreams.forEach(stream => {\n if (globalThis.apirtcReactLibLogLevel.isDebugEnabled) {\n console.debug(HOOK_NAME + \"|unpublish stream\", i_conversation, stream)\n }\n i_conversation.unpublish(stream)\n })\n // Clear internal array\n publishedStreams.length = 0;\n\n // Clear cache\n setPublishedStreamsCache([])\n\n subscribedStreams.forEach(stream => {\n if (globalThis.apirtcReactLibLogLevel.isDebugEnabled) {\n console.debug(HOOK_NAME + \"|unsubscribeToStream stream\", i_conversation, stream)\n }\n i_conversation.unsubscribeToStream(stream.getId())\n })\n // Clear internal array\n subscribedStreams.length = 0;\n\n // Clear output arrays with new array so that parent gets notified of a change.\n // Simply setting length to 0 is not detected by react.\n setO_PublishedStreams(new Array<Stream>())\n setO_SubscribedStreams(new Array<Stream>())\n };\n\n // --------------------------------------------------------------------------\n // useEffect(s) - Order is important\n //\n useEffect(() => {\n if (conversation) {\n const on_streamAdded = (remoteStream: Stream) => {\n if (globalThis.apirtcReactLibLogLevel.isInfoEnabled) {\n console.info(HOOK_NAME + \"|on_streamAdded\", remoteStream)\n }\n subscribedStreams.push(remoteStream)\n setO_SubscribedStreams(Array.from(subscribedStreams))\n };\n const on_streamRemoved = (remoteStream: Stream) => {\n if (globalThis.apirtcReactLibLogLevel.isInfoEnabled) {\n console.info(HOOK_NAME + \"|on_streamRemoved\", remoteStream)\n }\n const index = subscribedStreams.indexOf(remoteStream);\n if (index >= 0) {\n subscribedStreams.splice(index, 1)\n setO_SubscribedStreams(Array.from(subscribedStreams))\n }\n };\n const on_streamListChanged = (streamInfo: StreamInfo) => {\n const streamId = String(streamInfo.streamId);\n if (streamInfo.isRemote === true) {\n if (streamInfo.listEventType === 'added') {\n // a remote stream was published\n conversation.subscribeToStream(streamId)\n } else if (streamInfo.listEventType === 'removed') {\n // a remote stream is not published anymore\n conversation.unsubscribeToStream(streamId)\n }\n }\n };\n // Subscribe to incoming streams\n conversation.on('streamAdded', on_streamAdded)\n conversation.on('streamRemoved', on_streamRemoved)\n conversation.on('streamListChanged', on_streamListChanged)\n\n return () => {\n // remove listeners\n conversation.removeListener('streamListChanged', on_streamListChanged)\n conversation.removeListener('streamRemoved', on_streamRemoved)\n conversation.removeListener('streamAdded', on_streamAdded)\n\n unpublishAndUnsubscribeAll(conversation)\n }\n }\n }, [conversation])\n\n useEffect(() => {\n if (conversation) {\n if (globalThis.apirtcReactLibLogLevel.isDebugEnabled) {\n console.debug(HOOK_NAME + \"|useEffect doHandlePublication\", conversation.getName())\n }\n\n const on_joined = () => {\n if (globalThis.apirtcReactLibLogLevel.isInfoEnabled) {\n console.info(HOOK_NAME + \"|on_joined\", conversation.getName(), streamsToPublish)\n }\n doHandlePublication()\n };\n const on_left = () => {\n if (globalThis.apirtcReactLibLogLevel.isInfoEnabled) {\n console.info(HOOK_NAME + \"|on_left\", conversation.getName())\n }\n // Forcing unpublish will allow to republish if joining again\n unpublishAndUnsubscribeAll(conversation)\n };\n\n conversation.on('joined', on_joined)\n conversation.on('left', on_left)\n\n return () => {\n conversation.removeListener('joined', on_joined)\n conversation.removeListener('left', on_left)\n }\n }\n }, [doHandlePublication]) // Don't add 'conversation' in here because\n // doHandlePublication already changes on conversation change\n\n useEffect(() => {\n if (globalThis.apirtcReactLibLogLevel.isDebugEnabled) {\n console.debug(`${HOOK_NAME}|useEffect streamsToPublish`,\n JSON.stringify(streamsToPublish.map(l_s => l_s?.stream.getId() + '-' + JSON.stringify(l_s?.options))))\n }\n if (conversation && conversation.isJoined()) {\n doHandlePublication()\n }\n }, [JSON.stringify(streamsToPublish.map(l_s => l_s?.stream.getId() + '-' + JSON.stringify(l_s?.options)))])\n\n return {\n publishedStreams: o_publishedStreams,\n subscribedStreams: o_subscribedStreams,\n publish,\n unpublish,\n replacePublishedStream\n }\n}\n","import { Contact, Session } from '@apirtc/apirtc';\nimport { useEffect, useState } from 'react';\n\n/**\n * Subscribe to groups and returns contactsByGroup (of theses groups only) when updated.\n * If input groups list is updated, this hooks works diff with the previous set in order\n * to make as little as possible unsubscribe/subscribe calls.\n */\n\nconst HOOK_NAME = \"usePresence\";\nexport default function usePresence(session: Session | undefined, groups: Array<string>) {\n\n const [groupsCache] = useState<Set<string>>(new Set());\n\n const [m_contactsByGroup] = useState<Map<string, Set<Contact>>>(new Map());\n\n const [contactsByGroup, setContactsByGroup] = useState<Map<string, Set<Contact>>>(new Map());\n\n useEffect(() => {\n if (session) {\n return () => {\n m_contactsByGroup.clear()\n setContactsByGroup(new Map(m_contactsByGroup))\n groupsCache.clear()\n }\n }\n }, [session])\n\n const getOrCreateGroupSet = (group: string) => {\n const o_set = m_contactsByGroup.get(group) ?? new Set();\n if (!m_contactsByGroup.has(group)) {\n m_contactsByGroup.set(group, o_set)\n }\n return o_set\n };\n\n useEffect(() => {\n if (globalThis.apirtcReactLibLogLevel.isDebugEnabled) {\n console.debug(HOOK_NAME + \"|useEffect session, groups\", groups)\n }\n if (session) {\n const l_session = session;\n const l_groupsSet = new Set(groups);\n\n // Diff update subscription to groups\n //\n l_groupsSet.forEach(group => {\n if (!groupsCache.has(group)) {\n if (globalThis.apirtcReactLibLogLevel.isInfoEnabled) {\n console.info(HOOK_NAME + \"|subscribeToGroup\", group)\n }\n groupsCache.add(group)\n l_session.subscribeToGroup(group)\n }\n })\n\n let needsRefresh = false;\n groupsCache.forEach(group => {\n if (!l_groupsSet.has(group)) {\n if (globalThis.apirtcReactLibLogLevel.isInfoEnabled) {\n console.info(HOOK_NAME + \"|unsubscribeToGroup\", group)\n }\n l_session.unsubscribeToGroup(group)\n groupsCache.delete(group)\n m_contactsByGroup.delete(group)\n needsRefresh = true;\n }\n })\n\n if (needsRefresh) {\n // contactsByGroup is exposed, so change the Map object to let client code detect a change.\n setContactsByGroup(new Map(m_contactsByGroup))\n }\n\n if (groups.length > 0) {\n const onContactListUpdate = (updatedContacts: any) => {\n\n if (globalThis.apirtcReactLibLogLevel.isDebugEnabled) {\n console.debug(HOOK_NAME + \"|contactListUpdate\", updatedContacts)\n }\n\n let needsRefresh = false;\n\n // Maintain Map of Contacts per Group\n //\n for (const group of Object.keys(updatedContacts.joinedGroup)) {\n if (l_groupsSet.has(group)) {\n const l_set = getOrCreateGroupSet(group);\n for (const contact of updatedContacts.joinedGroup[group]) {\n l_set.add(contact)\n needsRefresh = true;\n }\n }\n }\n for (const group of Object.keys(updatedContacts.leftGroup)) {\n if (l_groupsSet.has(group)) {\n const l_set = getOrCreateGroupSet(group);\n for (const contact of updatedContacts.leftGroup[group]) {\n l_set.delete(contact)\n needsRefresh = true;\n\n // if set is empty, no need to keep the group as key in the map\n if (l_set.size === 0) {\n m_contactsByGroup.delete(group)\n }\n }\n }\n }\n\n // For data updates, trigger a refresh if and only if contact is part of managed groups\n for (const contact of updatedContacts.userDataChanged as Contact[]) {\n for (const l_contacts of m_contactsByGroup.values()) {\n if (l_contacts.has(contact)) {\n needsRefresh = true;\n break;\n }\n }\n }\n\n if (needsRefresh) {\n // contactsByGroup is exposed, so change the Map object to let client code detect a change.\n setContactsByGroup(new Map(m_contactsByGroup))\n }\n };\n l_session.on('contactListUpdate', onContactListUpdate)\n return () => {\n l_session.removeListener('contactListUpdate', onContactListUpdate)\n }\n }\n }\n }, [session, JSON.stringify(groups)])\n\n return {\n contactsByGroup\n }\n}","import { RegisterInformation, Session, UserAgent } from '@apirtc/apirtc';\nimport { useEffect, useState } from 'react';\n\nexport type LoginPassword = {\n username: string\n password: string\n};\nfunction isInstanceOfLoginPassword(object: any): object is LoginPassword {\n if (typeof object !== 'object') return false;\n return 'username' in object;\n}\n\nexport type ApiKey = { apiKey: string };\nfunction isInstanceOfApiKey(object: any): object is ApiKey {\n if (typeof object !== 'object') return false;\n return 'apiKey' in object;\n}\n\nexport type Token = { token: string };\nfunction isInstanceOfToken(object: any): object is Token {\n if (typeof object !== 'object') return false;\n return 'token' in object;\n}\n\nexport type Credentials = LoginPassword | ApiKey | Token;\n\nconst HOOK_NAME = \"useSession\";\nexport default function useSession(credentials?: Credentials, options?: RegisterInformation,\n errorCallback?: (error: any) => void) {\n\n const [session, setSession] = useState<Session | undefined>();\n const [connecting, setConnecting] = useState<boolean>(false);\n\n useEffect(() => {\n if (globalThis.apirtcReactLibLogLevel.isDebugEnabled) {\n console.debug(HOOK_NAME + \"|useEffect credentials, options\", credentials, options)\n }\n if (credentials) {\n // To fix errors like \"Warning: Can't perform a React state update on an unmounted component\"\n // https://stackoverflow.com/questions/53949393/cant-perform-a-react-state-update-on-an-unmounted-component\n //let isMounted = true;\n connect(credentials, options).catch((error: any) => {\n console.error(HOOK_NAME + \"|connection failed\", error)\n setSession(undefined)\n\n if (errorCallback) {\n errorCallback(error)\n } else if (globalThis.apirtcReactLibLogLevel.isWarnEnabled) {\n console.warn(`${HOOK_NAME}|connect|error`, error)\n }\n })\n return () => {\n setSession(undefined)\n // Even though connecting is managed in connect(),\n // mark connecting to false when credentials are changed\n // as this shall be way to connect elsewhere or connect to\n // with other credentials. Note that to be perfect we should\n // cancel the potentially running connect : Is that possible with ApiRTC ?\n setConnecting(false)\n }\n }\n }, [JSON.stringify(credentials), JSON.stringify(options)])\n\n useEffect(() => {\n if (globalThis.apirtcReactLibLogLevel.isDebugEnabled) {\n console.debug(HOOK_NAME + \"|useEffect session\", session)\n }\n if (session) {\n const l_session = session;\n return () => {\n l_session.disconnect().then(() => {\n if (globalThis.apirtcReactLibLogLevel.isInfoEnabled) {\n console.info(HOOK_NAME + \"|disconnected\", l_session)\n }\n }).catch((error: any) => {\n console.error(HOOK_NAME + \"|disconnect\", error)\n })\n }\n }\n }, [session])\n\n const connect = (credentials: Credentials | undefined, options?: RegisterInformation) => {\n return new Promise<void>((resolve, reject) => {\n const registerInformation: RegisterInformation = options ? options : {\n cloudUrl: 'https://cloud.apirtc.com',\n };\n\n let l_userAgent;\n\n if (isInstanceOfLoginPassword(credentials)) {\n registerInformation.password = credentials.password;\n l_userAgent = new UserAgent({\n uri: 'apirtc:' + credentials.username\n });\n } else if (isInstanceOfApiKey(credentials)) {\n l_userAgent = new UserAgent({\n uri: `apiKey:${credentials.apiKey}`\n });\n } else if (isInstanceOfToken(credentials)) {\n l_userAgent = new UserAgent({\n uri: `token:${credentials.token}`\n });\n } else {\n reject(\"credentials not recognized\")\n return\n }\n\n setConnecting(true)\n l_userAgent.register(registerInformation).then(l_session => {\n if (globalThis.apirtcReactLibLogLevel.isInfoEnabled) {\n console.info(HOOK_NAME + \"|connected\", l_session)\n }\n setSession(l_session)\n resolve()\n }).catch((error: any) => {\n reject(error)\n }).finally(() => {\n setConnecting(false)\n })\n })\n };\n\n // const disconnect = useCallback(() => {\n // return new Promise<void>((resolve, reject) => {\n // if (session) {\n // const l_session = session;\n // l_session.disconnect().then(() => {\n // console.log(HOOK_NAME + \"|disconnected\", l_session)\n // setSession(undefined)\n // resolve()\n // }).catch((error: any) => {\n // console.error(HOOK_NAME + \"|disconnect\", error)\n // reject(error)\n // })\n // } else {\n // resolve()\n // }\n // })\n // }, [session])\n\n const disconnect = () => {\n setSession(undefined)\n };\n\n return {\n //userAgent: userAgent, // can get it from session\n session: session,\n connecting,\n connect,\n disconnect\n }\n}\n","import { Stream, VideoProcessorOptions } from '@apirtc/apirtc';\nimport { useEffect, useState } from 'react';\n\nconst HOOK_NAME = \"useStreamApplyVideoProcessor\";\n/**\n * This hook takes stream passed as parameter, and\n * returns either this stream or a stream with video processor applied.\n * This is controlled by the videoProcessorType input attribute.\n * By default the output stream is the input stream.\n * The hook fully manages the output stream (applies 'none' if input stream is set to undefined).\n * The hook never releases the input stream.\n * \n * @param stream\n * @param videoProcessorType\n * @param {VideoProcessorOptions} options\n * @returns new stream with video processor applied (or original stream if no processor applied)\n */\nexport default function useStreamApplyVideoProcessor(\n stream: Stream | undefined,\n videoProcessorType: 'none' | 'blur' | 'backgroundImage', options?: VideoProcessorOptions,\n errorCallback?: (error: any) => void) {\n //\n const [outStream, setOutStream] = useState(stream);\n const [applied, setApplied] = useState<'none' | 'blur' | 'backgroundImage'>(stream ? (stream as any).videoAppliedFilter : 'none');\n\n useEffect(() => {\n if (globalThis.apirtcReactLibLogLevel.isDebugEnabled) {\n console.debug(HOOK_NAME + \"|useEffect\", stream, videoProcessorType, options, stream ? JSON.stringify((stream as any).children) : \"empty\")\n }\n if (stream) {\n stream.applyVideoProcessor(videoProcessorType, options).then(l_stream => {\n setOutStream(l_stream)\n setApplied(videoProcessorType)\n }).catch(error => {\n setOutStream(stream)\n setApplied((stream as any).videoAppliedFilter)\n if (errorCallback) {\n errorCallback(error)\n } else if (globalThis.apirtcReactLibLogLevel.isWarnEnabled) {\n console.warn(HOOK_NAME + \"|useEffect\", stream, videoProcessorType, options, error)\n }\n })\n } else {\n setOutStream(stream)\n setApplied('none')\n }\n }, [stream, videoProcessorType, JSON.stringify(options)])\n\n return {\n stream: outStream,\n applied\n }\n}","import { MediaDevice, MediaDeviceList, Session, UserAgent } from '@apirtc/apirtc';\nimport { useEffect, useState } from 'react';\n\nconst EMPTY_LIST: MediaDeviceList = { audioinput: {}, audiooutput: {}, videoinput: {} };\n\nconst getMediaDeviceFromLocalStorage = (key: string) => {\n const value = localStorage.getItem(key);\n const obj = value ? JSON.parse(value) : null;\n return obj ? new MediaDevice(obj.id, obj.type, obj.label) : undefined;\n};\n\nconst HOOK_NAME = \"useUserMediaDevices\";\nexport function useUserMediaDevices(\n session: Session | undefined,\n storageKeyPrefix: string = \"apirtc\"\n) {\n const [userMediaDevices, setUserMediaDevices] = useState<MediaDeviceList>(EMPTY_LIST);\n\n const AUDIO_INPUT_KEY = storageKeyPrefix + '.audioIn';\n const AUDIO_OUTPUT_KEY = storageKeyPrefix + '.audioOut';\n const VIDEO_INPUT_KEY = storageKeyPrefix + '.videoIn';\n\n const [selectedAudioIn, setSelectedAudioIn] = useState<MediaDevice | undefined>(getMediaDeviceFromLocalStorage(AUDIO_INPUT_KEY));\n const [selectedAudioOut, setSelectedAudioOut] = useState<MediaDevice | undefined>(getMediaDeviceFromLocalStorage(AUDIO_OUTPUT_KEY));\n const [selectedVideoIn, setSelectedVideoIn] = useState<MediaDevice | undefined>(getMediaDeviceFromLocalStorage(VIDEO_INPUT_KEY));\n\n useEffect(() => {\n if (session) {\n const userAgent: UserAgent = session.getUserAgent();\n\n const on_mediaDeviceChanged = () => {\n const mediaDevices: MediaDeviceList = userAgent.getUserMediaDevices()\n if (globalThis.apirtcReactLibLogLevel.isInfoEnabled) {\n console.info(HOOK_NAME + \"|mediaDeviceChanged\", mediaDevices)\n }\n setUserMediaDevices(mediaDevices)\n };\n userAgent.on('mediaDeviceChanged', on_mediaDeviceChanged)\n\n return () => {\n userAgent.removeListener('mediaDeviceChanged', on_mediaDeviceChanged)\n setUserMediaDevices(EMPTY_LIST)\n }\n }\n }, [session])\n\n useEffect(() => {\n if (userMediaDevices !== EMPTY_LIST) {\n const audioInputValue = localStorage.getItem(AUDIO_INPUT_KEY);\n const audioInputId: string = audioInputValue ? JSON.parse(audioInputValue)['id'] : undefined;\n if (audioInputId) {\n setSelectedAudioIn(userMediaDevices.audioinput[audioInputId])\n }\n\n const audioOutputValue = localStorage.getItem(AUDIO_OUTPUT_KEY);\n const audioOutputId: string = audioOutputValue ? JSON.parse(audioOutputValue)['id'] : undefined;\n if (audioOutputId) {\n setSelectedAudioOut(userMediaDevices.audiooutput[audioOutputId])\n }\n\n const videoInputValue = localStorage.getItem(VIDEO_INPUT_KEY);\n const videoInputId: string = videoInputValue ? JSON.parse(videoInputValue)['id'] : undefined;\n if (videoInputId) {\n setSelectedVideoIn(userMediaDevices.videoinput[videoInputId])\n }\n\n if (globalThis.apirtcReactLibLogLevel.isDebugEnabled) {\n console.debug(HOOK_NAME + '|userMediaDevices, audioInputId, audioOutputId, videoInputId', userMediaDevices, audioInputId, audioOutputId, videoInputId)\n }\n }\n\n }, [userMediaDevices])\n\n useEffect(() => {\n if (selectedAudioIn) {\n if (globalThis.apirtcReactLibLogLevel.isDebugEnabled) {\n console.debug(HOOK_NAME + '|Storing audioInput', selectedAudioIn)\n }\n localStorage.setItem(AUDIO_INPUT_KEY, JSON.stringify({\n id: selectedAudioIn.getId(), type: selectedAudioIn.getType(), label: selectedAudioIn.getLabel()\n }))\n }\n }, [selectedAudioIn?.getId()])\n\n useEffect(() => {\n if (selectedAudioOut) {\n if (globalThis.apirtcReactLibLogLevel.isDebugEnabled) {\n console.debug(HOOK_NAME + '|Storing audioOutput', selectedAudioOut)\n }\n localStorage.setItem(AUDIO_OUTPUT_KEY, JSON.stringify({\n id: selectedAudioOut.getId(), type: selectedAudioOut.getType(), label: selectedAudioOut.getLabel()\n }))\n }\n }, [selectedAudioOut?.getId()])\n\n useEffect(() => {\n if (selectedVideoIn) {\n if (globalThis.apirtcReactLibLogLevel.isDebugEnabled) {\n console.debug(HOOK_NAME + '|Storing VideoInput', selectedVideoIn)\n }\n localStorage.setItem(VIDEO_INPUT_KEY, JSON.stringify({\n id: selectedVideoIn.getId(), type: selectedVideoIn.getType(), label: selectedVideoIn.getLabel()\n }))\n }\n }, [selectedVideoIn?.getId()])\n\n return {\n userMediaDevices,\n selectedAudioIn, setSelectedAudioIn,\n selectedAudioOut, setSelectedAudioOut,\n selectedVideoIn, setSelectedVideoIn\n }\n}","export * from './components'\nexport * from './hooks'\n\nexport type LogLevel = {\n level: 'debug' | 'info' | 'warn' | 'error'\n isDebugEnabled: boolean\n isInfoEnabled: boolean\n isWarnEnabled: boolean\n}\n\nconst INFO: LogLevel = { level: 'info', isDebugEnabled: false, isInfoEnabled: true, isWarnEnabled: true };\n\ndeclare global {\n var apirtcReactLibLogLevel: LogLevel;\n var setApirtcReactLibLogLevel: (logLevelText: 'debug' | 'info' | 'warn' | 'error') => void;\n}\n\n// a default value MUST be set in case application using the library does not override it\nglobalThis.apirtcReactLibLogLevel = INFO;\n\nexport function setLogLevel(logLevelText: 'debug' | 'info' | 'warn' | 'error') {\n switch (logLevelText) {\n case 'debug':\n globalThis.apirtcReactLibLogLevel = { level: 'debug', isDebugEnabled: true, isInfoEnabled: true, isWarnEnabled: true };\n break\n case 'info':\n globalThis.apirtcReactLibLogLevel = INFO;\n break\n case 'warn':\n globalThis.apirtcReactLibLogLevel = { level: 'warn', isDebugEnabled: false, isInfoEnabled: false, isWarnEnabled: true };\n break\n case 'error':\n globalThis.apirtcReactLibLogLevel = { level: 'error', isDebugEnabled: false, isInfoEnabled: false, isWarnEnabled: false };\n break\n default:\n // in case null is passed as input, default to 'info'\n globalThis.apirtcReactLibLogLevel = INFO;\n }\n return globalThis.apirtcReactLibLogLevel\n}\n\nglobalThis.setApirtcReactLibLogLevel = setLogLevel;\n","import React, { useEffect, useRef } from 'react';\n\nimport { Stream } from '@apirtc/apirtc';\n\nexport type VideoStreamProps = {\n stream: Stream,\n autoPlay?: boolean,\n muted?: boolean\n};\nexport default function VideoStream(props: VideoStreamProps) {\n\n const { autoPlay = true } = props;\n\n const videoRef = useRef<HTMLVideoElement>(null)\n\n useEffect(() => {\n const ref = videoRef.current;\n if (ref && props.stream) {\n props.stream.attachToElement(ref)\n return () => {\n ref.src = \"\";\n }\n }\n }, [props.stream])\n // No need to put videoRef.current because useRef does not trigger rerender anyways\n\n return <video id={props.stream.getId()} style={{ maxWidth: '100%' }}\n ref={videoRef}\n autoPlay={autoPlay}\n muted={props.muted}></video>\n}"],"names":["HOOK_NAME","notEmpty","value","EMPTY_LIST","audioinput","audiooutput","videoinput","getMediaDeviceFromLocalStorage","key","localStorage","getItem","obj","JSON","parse","MediaDevice","id","type","label","undefined","INFO","level","isDebugEnabled","isInfoEnabled","isWarnEnabled","setLogLevel","logLevelText","globalThis","apirtcReactLibLogLevel","setApirtcReactLibLogLevel","props","autoPlay","videoRef","useRef","useEffect","ref","current","stream","attachToElement","src","React","createElement","getId","style","maxWidth","muted","session","options","setStream","useState","getUserAgent","createStream","then","localStream","console","info","catch","error","stringify","release","name","join","conversation","setConversation","joined","setJoined","joining","setJoining","o_join","useCallback","debug","Promise","resolve","reject","isJoined","finally","o_leave","leave","l_conversation","getOrCreateConversation","warn","destroy","l_join","messages","Array","o_messages","setO_Messages","onMessage","message","getName","push","from","on","removeListener","length","sendMessage","msgContent","sender","uuid","content","time","Date","onEjected","onEjectedSelf","candidates","setCandidates","Set","on_contactJoinedWaitingRoom","contact","add","on_contactLeftWaitingRoom","delete","on_participantEjected","data","self","streamsToPublish","errorCallback","map","publishedStreamsCache","setPublishedStreamsCache","publishedStreams","o_publishedStreams","setO_PublishedStreams","subscribedStreams","o_subscribedStreams","setO_SubscribedStreams","publish","replacePublishedStream","oldStream","newStream","conversationCall","getConversationCall","index","indexOf","splice","unpublish","doHandlePublication","maxLength","Math","max","l_s","newPublishedStreamsCache","elt","Object","assign","streamsToPublishSet","filter","item","i","previous","next","doPublish","doUnpublishPublish","has","isPublishedStream","unpublishAndUnsubscribeAll","i_conversation","forEach","unsubscribeToStream","on_streamAdded","remoteStream","on_streamRemoved","on_streamListChanged","streamInfo","streamId","String","isRemote","listEventType","subscribeToStream","on_joined","on_left","groups","groupsCache","m_contactsByGroup","Map","contactsByGroup","setContactsByGroup","clear","getOrCreateGroupSet","group","o_set","_a","get","set","l_session","l_groupsSet","subscribeToGroup","needsRefresh","unsubscribeToGroup","onContactListUpdate","updatedContacts","keys","joinedGroup","l_set","leftGroup","size","userDataChanged","l_contacts","values","credentials","setSession","connecting","setConnecting","connect","disconnect","registerInformation","cloudUrl","l_userAgent","object","password","UserAgent","uri","username","isInstanceOfApiKey","apiKey","isInstanceOfToken","token","register","videoProcessorType","outStream","setOutStream","applied","setApplied","videoAppliedFilter","children","applyVideoProcessor","l_stream","storageKeyPrefix","userMediaDevices","setUserMediaDevices","AUDIO_INPUT_KEY","AUDIO_OUTPUT_KEY","VIDEO_INPUT_KEY","selectedAudioIn","setSelectedAudioIn","selectedAudioOut","setSelectedAudioOut","selectedVideoIn","setSelectedVideoIn","userAgent","on_mediaDeviceChanged","mediaDevices","getUserMediaDevices","audioInputValue","audioInputId","audioOutputValue","audioOutputId","videoInputValue","videoInputId","setItem","getType","getLabel"],"mappings":"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"}
|