navigator.mediaDevices.enumerateDevices() not display device label on firefox - javascript

I am working on media control functionality. I am displaying device name to select from a dropdown and it's working fine on chrome but on firefox it will not fetching label or device name.

To complement the answers, on Firefox, the device labels obtained from navigator.mediaDevices.enumerateDevices() will also be set to the blank string in the case where there is no more active MediaStream, even though the application has been previously temporarily authorized to access the devices by calling navigator.mediaDevices.getUserMedia().
In the code below, the navigator.mediaDevices.enumerateDevices() will display the labels first (because the permission was granted from navigator.mediaDevices.getUserMedia()):
let stream = null
navigator.mediaDevices.getUserMedia({audio: true, video: false})
.then(s => {
stream = s
navigator.mediaDevices.enumerateDevices().then(devices => {
devices.forEach(device => {
console.log('device.label :', device.label)
})
})
})
.catch(error => {
console.log('Error :', error)
})
But if you clear the tracks of the created MediaStream, calling navigator.mediaDevices.enumerateDevices() again will result in labels being empty:
stream.getTracks().forEach(track => {
track.stop()
})
// No more active MediaStream => empty labels
navigator.mediaDevices.enumerateDevices().then(devices => {
devices.forEach(device => {
console.log('device.label :', device.label)
})
})
And you actually have to call navigator.mediaDevices.getUserMedia() again for a temporary permission to access the devices:
navigator.mediaDevices.getUserMedia({audio: true, video: false})
.then(s => {
navigator.mediaDevices.enumerateDevices().then(devices => {
devices.forEach(device => {
console.log('device.label :', device.label)
})
})
})
.catch(error => {
console.log('Error :', error)
})
Example here: https://codesandbox.io/s/pensive-hawking-hswzi
Reference:
https://developer.mozilla.org/en-US/docs/Web/API/MediaDeviceInfo/label

navigator.mediaDevices.enumerateDevices() will return an empty label attribute value in the media device info if the respective permissions are not granted.
To make it work, I placed this function after all of the media permissions have been granted so it returns a label attribute value as well.

navigator.mediaDevices.enumerateDevices() returns a promise that's fulfilled with an array of MediaDeviceInfo instances.
It worked for me in Firefox 56.0 (64-bit).
You can do something like this:
navigator.mediaDevices.enumerateDevices()
.then((data) => {
console.log('data', data);
})
.catch((err) => {
console.log('error getting MediaDeviceInfo list', err);
});
where data is the array that contains the list of all MediaDeviceInfo instances.
more info here:
https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/enumerateDevices

You need to grant the permissions first. try this code
if (navigator.mediaDevices.getUserMedia) {
console.log('getUserMedia supported.');
const constraints = {audio: true};
let chunks = [];
let onSuccess = function (stream) {
if (!navigator.mediaDevices || !navigator.mediaDevices.enumerateDevices) {
console.log("enumerateDevices() not supported.");
return false;
}
//List microphones.
navigator.mediaDevices.enumerateDevices().then(function (devices) {
devices.forEach(function (device) {
if (device.kind === "audioinput") {
console.log(device.label);//Other parameters device.kind/device.deviceId
}
});
}).catch(function (err) {
console.log(err.name + ": " + err.message);
});
}
let onError = function (err) {
console.log('The following error occured: ' + err);
}
navigator.mediaDevices.getUserMedia(constraints).then(onSuccess, onError);
} else {
console.log('getUserMedia not supported on your browser!');
}

Related

Getting "TypeError: user.getIdToken is not a function" when updating password in firebase

When I run the function updatePassword I get the error "TypeError: user.getIdToken is not a function", which comes from a file in the firebase sdk.
async changePassword(state, payload) {
const user = auth.currentUser
let cred = EmailAuthProvider.credential(
payload.email,
payload.oldPassword
)
reauthenticateWithCredential(user, cred)
.then(() => {
// User re-authenticated.
console.log(payload.newPassword)
updatePassword(payload.email, payload.newPassword)
.then(() => {
// Update successful.
console.log('Succeed')
})
.catch((error) => {
console.log('Failed', error)
// An error ocurred
// ...
})
})
.catch((error) => {
// An error ocurred
// ...
console.log(error)
})
},
The updatePassword() function takes User as first parameter and not user's email. Try refactoring the code as shown below:
reauthenticateWithCredential(user, cred).then(({ user }) => {
// Pass user here and not payload.email
updatePassword(user, payload.newPassword).then(() => {
console.log('Succeed')
})
})

Firebase email verification WITHOUT creating an account in React Native

I have question regarding email verification in Firebase. Solution to my problem I found here. But when I convert code to react native. It is not working as expected.
My function
const onSignIn = () => {
auth()
.signInAnonymously()
.then(() => {
console.log('User signed in anonymously');
auth()
.onAuthStateChanged((user) => {
user.updateEmail('jasurkurbanov96#gmail.com');
user.sendEmailVerification();
})
.catch(function (error) {
console.log('error', error);
});
})
.catch((error) => {
if (error.code === 'auth/operation-not-allowed') {
console.log('Enable anonymous in your firebase console.');
}
console.error(error);
});
navigation.push('SignUpConfirm');
};
Basically what I want to achieve is. When user enters to app, I need to show only email input. Once user
enters email address, Firebase should send confirmation code to the email user provided.
You should read the docs https://rnfirebase.io/reference/auth/user#updateEmail with the code below should works. if not print what error you got.
Sign In Screen
const onSignIn = () => {
auth()
.signInAnonymously()
.then(() => {
console.log('User signed in anonymously');
.catch((error) => {
if (error.code === 'auth/operation-not-allowed') {
console.log('Enable anonymous in your firebase console.');
}
console.error(error);
});
navigation.push('SignUpConfirm');
};
SignUpConfirm Screen
useEffect(() => {
auth().onAuthStateChanged((userIs) =>
userIs
.updateEmail('jasurkurbanov96#gmail.com')
.then(() =>
userIs
.sendEmailVerification()
.then(() => console.log('email verificiation sent')),
)
.catch((err) => console.log('This is', err)),
);
}, []);

Service Worker - Failed to fetch files

Service worker is integrated in the app. When CSS requested Poppins-Regular.ttf file service worker doesn't send the cached file. Console "throws" error
The FetchEvent for [url] resulted in a network error response
But the files are getting cached along with other files when I run the app for the first time
Here is the code of the CSS file where I have added the font files
#font-face {
font-family: Poppins-Regular;
src: url('../fonts/Poppins-Regular.ttf');
}
#font-face {
font-family: Poppins-Medium;
src: url('../fonts/Poppins-Medium.ttf');
}
Here is the service worker code
const __cacheName = 'MyCache';
const __precacheResources = [
//fonts
'/inv/fonts/Segoe-UI.ttf',
'/inv/fonts/Segoe-UI-Bold.ttf',
'/inv/fonts/Poppins-Medium.ttf',
'/inv/fonts/Poppins-Regular.ttf',
];
var isFileLoadFinished = false;
self.addEventListener('install', event => {
isFileLoadFinished = false;
console.log('Service worker :', __sw_version, 'is installed!');
self.skipWaiting();
caches.delete(__cacheName);
event.waitUntil(
caches.open(__cacheName)
.then(cache => {
return cache.addAll(__precacheResources)
.then(() => {
isFileLoadFinished = true;
})
})
);
});
/*
this will send the object to the client via a message
#param {msg_} is an object to send to
#return null
*/
function sendMessagetoClients(msg_) {
console.log('sending msg to client. msg id is:', msg_.id)
self.clients.matchAll({
includeUncontrolled: true, //returns only the service worker clients controlled by the current service worker. The default is false.
type: "all"// "window"
}
).then(clients => {
if (clients.length == 0) {
console.log('No clients');
}
clients.forEach(client => {
console.log('the client is ', client);
client.postMessage(msg_);
});
});
}
self.addEventListener('activate', event => {
console.log('%s : Service worker :', (new Date()).toISOString(), __sw_version, ' is active! ');
sendMessagetoClients({
id: 002,
msgText: 'All items loaded',
data: isFileLoadFinished
});
});
self.addEventListener('fetch', event => {
event.respondWith(caches.match(event.request)
.then(cachedResponse => {
if (cachedResponse) {
return cachedResponse;
}
return fetch(event.request).catch(err => {
console.error(err);
});
})
);
});
self.addEventListener('message', event => {
console.log('%s : message received. msg id : %s', (new Date()).toISOString(), event.data.id);
//process the msg
if (event.data.id) {
if (event.data.id == 001) {
sendMessagetoClients({
id: 002,
data: isFileLoadFinished
})
} else if (event.data.id == 003) {
sendMessagetoClients({
id: 004,
data: __sw_version
})
}
}
return;
});
What should i do to fix those errors? Any help would be appreciated.
Change caches.match(event.request) to caches.match(event.request, { ignoreSearch: true })
Make sure if the requested URL is the same as the URL in the cache ('/inv/fonts/Poppins-Medium.ttf')
From developer.mozilla.org
ignoreSearch: A Boolean that specifies whether to ignore the query string in the URL. For example, if set to true the ?value=bar part of http://example.com/?value=bar would be ignored when performing a match. It defaults to false.

Firebase: can't write Username + Title to DB [duplicate]

So I'm following a Savvy Apps tutorial in order to learn Vue.js. This tutorial uses Firebase with Firestore. Since Firestore is in Beta (as the tutorial says), changes might happen - and I think that might be the case here.
In any case, I'm trying to sign up a new user. I fill out the form and click 'Sign up' and I get this error message:
Error: Function CollectionReference.doc() requires its first argument to be of type string, but it was: undefined
But looking in Firebase, I see that the user has been created. So why do I get this error message? What is the first argument?
The code for signup looks like this:
signup() {
this.performingRequest = true;
fb.auth.createUserWithEmailAndPassword(this.signupForm.email, this.signupForm.password).then(user => {
this.$store.commit('setCurrentUser', user);
// create user obj
fb.usersCollection.doc(user.uid).set({
name: this.signupForm.name,
title: this.signupForm.title
}).then(() => {
this.$store.dispatch('fetchUserProfile');
this.performingRequest = false;
this.$router.push('/dashboard')
}).catch(err => {
console.log(err);
this.performingRequest = false;
this.errorMsg = err.message
})
}).catch(err => {
console.log(err);
this.performingRequest = false;
this.errorMsg = err.message
})
},
Let me know if you need more code - this is the first time I'm testing Vue.js.
createUserWithEmailAndPassword() returns a Promise containing a UserCredential. UserCredential has a property user for the firebase.User object.
You need to make the appropriate changes to your code to correctly access the UID:
signup() {
this.performingRequest = true;
fb.auth.createUserWithEmailAndPassword(this.signupForm.email, this.signupForm.password)
.then(credential=> { // CHANGED
this.$store.commit('setCurrentUser', credential.user); // CHANGED
// create user obj
fb.usersCollection.doc(credential.user.uid).set({ //CHANGED
name: this.signupForm.name,
title: this.signupForm.title
}).then(() => {
this.$store.dispatch('fetchUserProfile');
this.performingRequest = false;
this.$router.push('/dashboard')
}).catch(err => {
console.log(err);
this.performingRequest = false;
this.errorMsg = err.message
})
}).catch(err => {
console.log(err);
this.performingRequest = false;
this.errorMsg = err.message
})
},

RTCPeerConnection not sending stream

I am trying to establish an RTCPeerConnection and using pusher for handshaking through the following code
var pc = new RTCPeerConnection({
"iceServers": [
{url: 'stun:stun.l.google.com:19302'},
{url: 'stun:stunserver.org'},
]
}
);
pc.onicecandidate = event => {
if (!event.candidate) return;
console.log("icecandidate: ", event);
presenceChannel.trigger("client-ice", {data: event.candidate});
};
pc.onaddstream = event => {
console.warn("stream added");
vidEl.srcObject = event.stream;
};
//for when pusher channel subscription is successful from the other end
presenceChannel.bind("client-subscribed", () => {
console.warn(pc);
pc.createOffer().then(offer => {
return pc.setLocalDescription(new RTCSessionDescription(offer), () => {
console.warn("offer created: ", offer);
presenceChannel.trigger("client-offer", {data: offer});
});
}).catch(error => {
console.warn("error on offer: ", error);
});
});
presenceChannel.bind("client-answer", function (data) {
pc.setRemoteDescription(new RTCSessionDescription(data.data), () => {
console.warn("received an answer");
pc.addStream(currentStream);
setTimeout(() => {
console.warn(pc);
}, 5000);
}, error => {
console.warn("error in answer: ", error)
});
});
presenceChannel.bind("client-ice", function (data) {
pc.addIceCandidate(new RTCIceCandidate(data.data)).catch(error => {
console.warn("ice error: ", error);
});
});
//and the remote peer
presenceChannel.bind("pusher:subscription_succeeded", () => {
if (currentStream === undefined) {
presenceChannel.trigger("client-recipient-error");
pusher.unsubscribe(channel);
return false;
}
var pc = new RTCPeerConnection({
"iceServers": [
{url: 'stun:stun.l.google.com:19302'},
{url: 'stun:stunserver.org'},
]
}
);
pc.onicecandidate = event => {
if (!event.candidate) return;
console.log("icecandidate: ", event);
presenceChannel.trigger("client-ice", {data: event.candidate});
};
pc.onaddstream = event => {
console.warn("stream added");
vidEl.srcObject = event.stream;
};
presenceChannel.trigger("client-subscribed", {});
console.warn(pc);
presenceChannel.bind("client-ice", function (data) {
pc.addIceCandidate(new RTCIceCandidate(data.data)).catch(error => {
console.warn("ice error: ", error);
});
});
presenceChannel.bind("client-offer", signalData => {
// console.warn("client-signal", signalData);
console.warn("received an offer");
pc.setRemoteDescription(new RTCSessionDescription(signalData.data), () => {
return pc.createAnswer().then(answer => {
pc.setLocalDescription(new RTCSessionDescription(answer), () => {
presenceChannel.trigger("client-answer", {data: answer});
console.warn("created answer");
pc.addStream(currentStream);
setTimeout(() => {
console.warn(pc);
}, 7000);
});
}).then(() => {
}).catch(error => {
console.warn("error on answer: ", error);
});
});
});
});
Am not getting any errors the rtcpeerconnection variable on both ends have both local and remote description so am assuming the connection was well established right? Or this doesn't mean the connection was established, (i need help on this too to know if the connection is established or not and how to know), however everything runs, all the events and functions execute (except the onicecandidate event which i know its just not being triggered am not worried about this though) except for onaddstream event, so am guessing if this is not being triggered and am adding a stream then is the connection really on, wasted alot of time on this and frankly its just driving me nuts, any help AND I MEAN ANY HELP would be highly appreciated cause it's my first time handling RTCPeerConnection and maybe there is something am doing wrong or taking a wrong approach, please point this out too if its the case and show me the right way of doing it. Thanks in advance.
EDIT: Am using chrome and it does not yet support addTrack, gave me an error earlier that addTrack is not a function so fell back to addStream.

Categories