diff --git a/net/web/src/constants/Strings.js b/net/web/src/constants/Strings.js index 4ce586e2..20eef60e 100644 --- a/net/web/src/constants/Strings.js +++ b/net/web/src/constants/Strings.js @@ -176,6 +176,10 @@ export const en = { editMembership: 'Edit Membership', deleteTopic: 'Delete Topic', leaveTopic: 'Leave Topic', + + integrated: 'Integrated', + microphone: 'Microphone', + camera: 'Camera' }; export const fr = { @@ -356,5 +360,9 @@ export const fr = { editMembership: 'Modifier Membres du Suject', deleteTopic: 'Supprimer le Sujet', leaveTopic: 'Quitter le Suject', + + integrated: 'Intégré', + microphone: 'Microphone', + camera: 'Caméra' }; diff --git a/net/web/src/context/useRingContext.hook.js b/net/web/src/context/useRingContext.hook.js index 74ec1290..bb3430e6 100644 --- a/net/web/src/context/useRingContext.hook.js +++ b/net/web/src/context/useRingContext.hook.js @@ -164,6 +164,9 @@ export function useRingContext() { }; try { + const devices = await navigator.mediaDevices.enumerateDevices(); + console.log('>> ', devices); + const stream = await navigator.mediaDevices.getUserMedia({ video: false, audio: true, @@ -417,6 +420,9 @@ export function useRingContext() { }, enableVideo: async () => { if (!accessVideo.current) { + const devices = await navigator.mediaDevices.enumerateDevices(); + console.log('>> ', devices); + const stream = await navigator.mediaDevices.getUserMedia({ video: true, audio: true, @@ -457,6 +463,24 @@ export function useRingContext() { updateState({ localAudio: false }); } }, + getDevices: async (type) => { + const filtered = new Map(); + const devices = await navigator.mediaDevices.enumerateDevices(); + devices.filter(item => item.kind === type + 'input').forEach(item => { + if (item && item.label) { + const entry = filtered.get(item.groupId); + if (entry) { + if (item.label && item.label.length < entry.label.length) { + filtered.set(item.groupId, item); + } + } + else { + filtered.set(item.groupId, item); + } + } + }); + return Array.from(filtered.values()); + }, } return { state, actions } diff --git a/net/web/src/context/useSettingsContext.hook.js b/net/web/src/context/useSettingsContext.hook.js index 5e0b9f41..0ffa9521 100644 --- a/net/web/src/context/useSettingsContext.hook.js +++ b/net/web/src/context/useSettingsContext.hook.js @@ -18,6 +18,10 @@ export function useSettingsContext() { strings: en, dateFormat: 'mm/dd', timeFormat: '12h', + audioInput: null, + audioInputs: [], + videoInput: null, + videoInputs: [], }); const SMALL_MEDIUM = 650; @@ -43,6 +47,36 @@ export function useSettingsContext() { } }; + const getDevices = async (type) => { + const filtered = new Map(); + const devices = await navigator.mediaDevices.enumerateDevices(); + + devices.filter(item => item.kind === type + 'input').forEach(item => { + if (item) { + const label = item.label ? item.label : state.strings.integrated; + const entry = filtered.get(item.groupId); + if (entry) { + if (item.label && label.length < entry.label.length) { + filtered.set(item.groupId, { value: item.deviceId, label }); + } + } + else { + filtered.set(item.groupId, { value: item.deviceId, label }); + } + } + }); + return Array.from(filtered.values()); + } + + useEffect(() => { + getDevices('audio').then(audio => { + updateState({ audioInputs: audio }); + }); + getDevices('video').then(video => { + updateState({ videoInputs: video }); + }); + }, [state.strings]); + useEffect(() => { for (let i = 0; i < 10; i++) { setTimeout(handleResize, 100 * i); //cludge for my mobile browser @@ -100,6 +134,10 @@ export function useSettingsContext() { } } + const audioInput = localStorage.getItem('audio_input'); + const videoInput = localStorage.getItem('video_input'); + updateState({ audioInput, videoInput }); + return () => { window.removeEventListener('resize', handleResize); window.removeEventListener('orientationchange', handleResize); @@ -155,6 +193,14 @@ export function useSettingsContext() { localStorage.setItem('time_format', timeFormat); updateState({ timeFormat }); }, + setAudioInput: (audioInput) => { + localStorage.setItem('audio_input', audioInput); + updateState({ audioInput }); + }, + setVideoInput: (videoInput) => { + localStorage.setItem('video_input', videoInput); + updateState({ videoInput }); + }, } return { state, actions } diff --git a/net/web/src/session/account/profile/Profile.jsx b/net/web/src/session/account/profile/Profile.jsx index d4bcedfb..6343aae7 100644 --- a/net/web/src/session/account/profile/Profile.jsx +++ b/net/web/src/session/account/profile/Profile.jsx @@ -135,13 +135,13 @@ export function Profile({ closeProfile }) { { state.display !== 'xlarge' && state.displaySet && (