How to call downloadItem.pause() and downloadItem.pause() from outside of session.on(‘will-download’)? - electron

I am trying to implement pause and resume functionality with electron libraries. how could i call item.pause out of session.on(‘will-download’) because it is function of item inside session.on(‘will-download’) or from any other way?
var url, path, filename;
ipcMain.on(‘item:file’, function(e, file) {
if(file.msg === ‘d’){
console.log(file);
url = file.url;
path = pathLib.join(__dirname, file.path);
filename = file.filename;
contents.downloadURL(url);
}
if(file.msg === ‘p’){
item.pause();
}
if(file.msg === ‘r’){
item.resume();
}
contents.session.on('will-download', (event, item, contents) => {
// Set the save path, making Electron not to prompt a save dialog.
path = `${path}${filename}`;
item.setSavePath(path);
item.on('updated', (event, state) => {
if (state === 'interrupted') {
console.log('Download is interrupted but can be resumed');
} else if (state === 'progressing') {
if (item.isPaused()) {
console.log('Download is paused');
} else {
console.log(`Received bytes: ${item.getReceivedBytes()} out of ${item.getTotalBytes()}`);
var percentage = (item.getReceivedBytes()/item.getTotalBytes())*100;
var progress = {'rBytes':item.getReceivedBytes(), 'tBytes':item.getTotalBytes(), 'p':percentage};
contents.send('item:progress', progress);
}
}
});
item.once('done', (event, state) => {
if (state === 'completed') {
console.log('Download successfully');
} else {
console.log(`Download failed: ${state}`);
}
});
});
});

https://github.com/sindresorhus/electron-dl/blob/master/index.js
Following, given above, link Worked for me!

Related

How to pass geolocation permission to react-native-webview?

When using the geolcoation api in a react-native-webview, I am asked twice whether the app is allowed to use my current location. How is it possible to forward the already (not) granted permission to the webview?
I am currently using react-native 0.68 and react-native-webview 11.22.
First prompt:
Second prompt:
I should only be asked once for permission to use my current geolocation.
In case somebody faces the same problem, I solved this issue with the following workaround. I injected a custome javacscript into the webview to override the used geolocation api in the webview. My custome script does all the communication with the app. The app returns the geolocation and so the webview doesn't need to aks for permission.
Custome Script
export const getGeoLocationJS = () => {
const getCurrentPosition = `
navigator.geolocation.getCurrentPosition = (success, error, options) => {
window.ReactNativeWebView.postMessage(JSON.stringify({ event: 'getCurrentPosition', options: options }));
window.addEventListener('message', (e) => {
let eventData = {}
try {
eventData = JSON.parse(e.data);
} catch (e) {}
if (eventData.event === 'currentPosition') {
success(eventData.data);
} else if (eventData.event === 'currentPositionError') {
error(eventData.data);
}
});
};
true;
`;
const watchPosition = `
navigator.geolocation.watchPosition = (success, error, options) => {
window.ReactNativeWebView.postMessage(JSON.stringify({ event: 'watchPosition', options: options }));
window.addEventListener('message', (e) => {
let eventData = {}
try {
eventData = JSON.parse(e.data);
} catch (e) {}
if (eventData.event === 'watchPosition') {
success(eventData.data);
} else if (eventData.event === 'watchPositionError') {
error(eventData.data);
}
});
};
true;
`;
const clearWatch = `
navigator.geolocation.clearWatch = (watchID) => {
window.ReactNativeWebView.postMessage(JSON.stringify({ event: 'clearWatch', watchID: watchID }));
};
true;
`;
return `
(function() {
${getCurrentPosition}
${watchPosition}
${clearWatch}
})();
`;
};
Webview
import Geolocation from '#react-native-community/geolocation';
let webview = null;
<WebView
geolocationEnabled={ true }
injectedJavaScript={ getGeoLocationJS() }
javaScriptEnabled={ true }
onMessage={ event => {
let data = {}
try {
data = JSON.parse(event.nativeEvent.data);
} catch (e) {
console.log(e);
}
if (data?.event && data.event === 'getCurrentPosition') {
Geolocation.getCurrentPosition((position) => {
webview.postMessage(JSON.stringify({ event: 'currentPosition', data: position }));
}, (error) => {
webview.postMessage(JSON.stringify({ event: 'currentPositionError', data: error }));
}, data.options);
} else if (data?.event && data.event === 'watchPosition') {
Geolocation.watchPosition((position) => {
webview.postMessage(JSON.stringify({ event: 'watchPosition', data: position }));
}, (error) => {
webview.postMessage(JSON.stringify({ event: 'watchPositionError', data: error }));
}, data.options);
} else if (data?.event && data.event === 'clearWatch') {
Geolocation.clearWatch(data.watchID);
}
}}
ref={ ref => {
webview = ref;
if (onRef) {
onRef(webview)
}
}}
source={ url }
startInLoadingState={ true }
/>

why is ipcRenderer.sendSync() causing crashing the application?

In the onbeforeunload-Event, I use in my renderer-process ipcRenderer.sendSync() to notify the main-process to show a dialog:
window.onbeforeunload = (e) => {
const response = ipcRenderer.sendSync('askForSavingChanges');
if (response == 0) {
// save ...
} else if (response == 2) {
e.returnValue = false;
}
}
Here is the code in the main-process:
app.whenReady().then(() => {
initSettings().then(() => {
ipcMain.on('askForSavingChanges', (event) => event.returnValue = require('electron').dialog.showMessageBoxSync(this,
{
type: 'question',
buttons: ['Yes', 'No', 'Cancel'],
title: 'Closing',
message: 'Do you want to save changes?'
}));
})
createWindow();
});
Now, when I close the window, the event onbeforeunload will be called, but when calling ipcRenderer.sendSync() the window will be closed immediately. Do I something wrong?

Quasar File Picker doesn't upload image in ios

I want to implement image uploading. It works for web (Chrome/Safari), but not for mobile ios (built with Capacitor). It shows image selection, but when I select it nothing happens.
Here is my input:
<q-file
v-model="avatarFile"
accept=".jpg, .png"
#input="uploadImage"
/>
async uploadImage() {
if (this.avatarFile) {
let extension = "jpg";
if (this.avatarFile.type === "image/png") {
extension = "png";
}
try {
this.loading = 1;
const {
data: {
uploadUrl: { uploadUrl },
},
} = await this.$apollo.query({
query: GET_UPLOAD_URL,
variables: {
extension,
},
});
await axios.put(uploadUrl, this.avatarFile);
await setTimeout(() => {
this.$emit("on-image-upload");
this.loading = 0;
}, 3000);
} catch (e) {
this.alertError(e);
this.loading = 0;
}
}
}
What am I doing wrong? Thanx in advance!
Found the solution. My accept rule had the wrong format. This works:
accept="image/*"

WebRTC - how to switch between getUserMedia and getDisplayMedia tracks inside RTCPeerConnection

I'm trying to develop an app where users can can video call to each other and share their screens using WebRTC technology. I have succeed with either video call or screen sharing app and now I'm trying to make it to be able to switch between getUserMedia and getDisplayMedia on button click during a call inside the same RTCPeerConnection but it doesn't work.
This is how I thought it could work:
function onLogin(success) {
var configuration = { offerToReceiveAudio: true, offerToReceiveVideo: true, "iceServers" : [ { "url" : "stun:stun.1.google.com:19302" } ] };
myConnection = window.RTCPeerConnection ? new RTCPeerConnection(configuration, { optional: [] }) : new RTCPeerConnection(configuration, { optional: [] });
myConnection.onicecandidate = function (event) {
console.log("onicecandidate");
if (event.candidate) send({ type: "candidate", candidate: event.candidate });
};
myConnection.ontrack=function(e){
try{remoteVideo.src = window.webkitURL?window.webkitURL.createObjectURL(e.streams[0]):window.URL.createObjectURL(e.streams[0])}
catch(err){remoteVideo.srcObject=e.streams[0]}
}
myConnection.ondatachannel=openDataChannel
openDataChannel();
startAVStream();
//startSStream()
};
function startAVStream(enable){
if(sStream)sStream.getTracks().forEach( function (track) {
try{myConnection.removeTrack( track, sStream );}
catch(e){}
} );
navigator.mediaDevices.getUserMedia({ video: true, audio: true }).then(s => {
if(!avStream){
avStream = s;
avStream.getTracks().forEach( function (track) {
myConnection.addTrack( track, avStream );
} );
}
}, function (error) { console.log(error); });
}
function startSStream(enable){
if(avStream)avStream.getTracks().forEach( function (track) {
try{myConnection.removeTrack( track, avStream );}
catch(e){}
} );
navigator.mediaDevices.getDisplayMedia({ video: true }).then(s => {
if(!sStream){
sStream = s;
sStream.getTracks().forEach( function (track) {
myConnection.addTrack( track, sStream );
} );
}
}, function (error) { console.log(error); });
}
Can anyone tell me how I can switch between tracks inside the same RTCPeerConnection or should I create 2 separate RTCPeerConnection - one for video/audio streaming and another for screen sharing?
Any help appreciated! Thanks!
You could use RTCRtpSender.replaceTrack to splice the screen capture track. This doesn't require renegotiation, and therefore has very low latency.
let newstream = navigator.mediaDevices.getDisplayMedia({});
let newtrack = newstream.getTracks()[1];
if(newtrack.kind !== 'video')
throw new Error('Eek!?');
pc.getSenders().forEach(async s => {
if(s.track && s.track.kind === 'video')
await s.replaceTrack(newtrack);
});
The test for s.track not being null deals with the case where you previously called replaceTrack(..., null).
shareScreen = () =>{
const success = (stream) => {
window.localStream = stream
// this.localVideoref.current.srcObject = stream
// localStream.replaceStream(stream);
this.setState({
localStream: stream
})
Object.values(this.state.peerConnections).forEach(pc => {
pc.getSenders().forEach(async s => {
console.log("s.track ",s.track);
if(s.track && s.track.kind === 'video'){
stream.getTracks().forEach(track => {
// pc.addTrack(track, this.state.localStream)
s.replaceTrack(track);
});
}
});
});
}
const failure = (e) => {
console.log('getUserMedia Error: ', e)
}
navigator.mediaDevices.getDisplayMedia({ cursor: true }).then(success).catch(failure)}

How to change the value of a JQueryUI progressbar dynamically?

In my import photos script, I try to update a progressbar (Jquery UI) following a while loop with Ajax requests.
The JQueryUI progressbar, which is supposed to be displayed before the launch of ajax requests do it after. So I have the user feedback at the end of the execution of my while loop ... (The console shows me that these applications are running well, in the right order)
I thought about using live () or bind (), but I do not know how to test it ...
Here is my jquery code:
$(function() {
var percent_progressbar=0;
$('#myform').submit(function() {
$('#myform').hide();
$("#text_result").html("Import in progress : <span class='progression'>0/0</span>").show(10, function() {
$("#myprogressbar").progressbar({value:percent_progressbar});
$("#myprogressbar").show(10, function() {
if (jQuery.trim($("#id_src").val()).length!=0) {
// Total number of photos to import
$.ajax({
type : 'POST',
async : false,
url : '/nbphotos.php',
data : 'chem=mydir',
success : function(nbphotos){
if (nbphotos>0){
$(".progression").html("0"+" / "+nbphotos);
var finish=false;
var nb_photos_imported=0;
var ajax_done = false;
var resultat_ajax="";
// Variables envoyées en Ajax
var datas = desvariables;
while (nb_photos_imported < nbphotos) {
ajax_done = false;
$.ajax({
type : 'GET',
async : false,
url : '/traitement.php',
data : datas,
success : function(resultat){
resultat_ajax=resultat;
ajax_done=true;
nb_photos_imported++;
}
});
if (ajax_done==true){
if (resultat_ajax=="ok") {
percent_progressbar = Math.floor(nb_photos_imported*100/nbphotos);
$("#myprogressbar").progressbar("option", "value", percent_progressbar);
console.info("Succès ajax (resultat : OK) : "+percent_progressbar);
$(".progression").html(nb_photos_imported+" / "+nbphotos);
} else {
finish=true;
$("#text_result").html(ajax_done);
return false;
}
} else {
// ajax error => exit the while
console.info("Ajax execution error "+nb_photos_imported);
return false;
}
} // While
if (finish==true) {
$("#myprogressbar").hide('slow');
$('#text_result').html("Import of "+nb_photos_imported+" photos done.");
}
} else{
$("#text_result").html("No photo to import.");
$("#myprogressbar").hide(10);
$('#myform').show("slow");
}
}
});
}
});
}); // callback #text_result.show()
return false;
});
});
Here is my new code. The console log show the progression of the percentage, the photos are imported, but I still have the display at the end. If I put a breakpoint with me debugging tool somewhere in the loop, the display is refreshing and everything is OK...
$(function () {
$("#myprogressbar").show();
var RetourNbPhotos = "";
var RetourImported = "";
var fini = false;
var percent_progressbar = 0;
var nb_photos_imported = 0;
var datas = desvariables; // datas sent with ajax
// Number of photos to import
function NbPhotoAjax() {
return $.ajax({
type: 'POST',
async: false,
url: '/boutique/modules/importimageswithiptc/ajax-nbphotos.php',
data: 'chem=$cheminimport',
success: function (nbphotos) {
RetourNbPhotos = nbphotos;
}
});
}
// Photo Ajax Import
function ImportPhotoAjax() {
$("#text_result").html("Import in progress : <span class='progression'>0/0</span>").show();
// RetourImported = "";
return $.ajax({
type: 'GET',
async: false,
url: '/boutique/modules/importimageswithiptc/ajax-traitement.php',
data: datas,
success: function (resultat) {
RetourImported = resultat;
}
});
}
$("#myprogressbar").progressbar({
value: percent_progressbar
});
$('#generator').submit(function () {
$('#generator').hide();
if (jQuery.trim($("#id_product_src").val()).length != 0) {
$.when(NbPhotoAjax()).then(function () {
if (RetourNbPhotos > 0) {
while (nb_photos_imported < RetourNbPhotos) {
$.when(ImportPhotoAjax()).then(function () {
nb_photos_imported++;
if (RetourImported == "ok") {
percent_progressbar = Math.floor(nb_photos_imported * 100 / RetourNbPhotos);
$("#myprogressbar").progressbar("option", "value", percent_progressbar);
console.info("Success : " + percent_progressbar + "%");
$(".progression").html(nb_photos_imported + " / " + RetourNbPhotos);
} else {
fini = true;
$("#text_result").html("ajax_reussi");
return false;
}
}).fail(function () {
// ajax error => exit the while
console.info("Ajax execution error " + nb_photos_imported);
return false;
});
} // While
if (fini == true) {
$("#myprogressbar").hide('slow');
$('#text_result').html("Import of " + nb_photos_imported + " photos done.");
}
} else {
$("#text_result").html("No photo to import.");
$("#myprogressbar").hide(10);
$('#generator').show("slow");
}
});
}
return false;
});
});

Resources