I have a renderer file that has the sole purpose of opening a dialog box to select files from. I have tried rewriting this so many times, and each time I get a different error. What am I doing wrong?
Exact code:
const { ipcRenderer, shell, remote } = require('electron')
const dialog = remote.dialog;
function openFileBrowser() {
dialog.showOpenDialog(remote.getCurrentWindow(), {
properties: ["openFile", "multiSelections"]
}).then(result => {
if (result.canceled === false) {
console.log("Selected file paths:")
console.log(result.filePaths)
}
}).catch(err => {
console.log(err)
})
}
Related HTML:
<div id="button-container">
<nav>
<ul class="buttons">
<li id="Open" onclick="openFileBrowser()">Proxies</li>
</ul>
</nav>
</div>
Error Code
renderer.js:37 Uncaught ReferenceError: Cannot access 'dialog' before initialization
at openFileBrowser (renderer.js:37)
at HTMLLIElement.onclick (proxies.html:16)
Using Electron:
"7.1.7"
Since Electron 6.0.0, the functions dialog.showMessageBox(), dialog.showOpenDialog() and dialog.showSaveDialog() return Promises and no longer take callback functions.
There are synchronous counterparts dialog.showMessageBoxSync(), dialog.showOpenDialogSync() and dialog.showSaveDialogSync().
Check out the following code examples showing the asynchronous and the synchronous way of displaying an open dialog:
Asynchronous: dialog.showOpenDialog()
const remote = require("electron").remote
const dialog = remote.dialog
dialog.showOpenDialog(remote.getCurrentWindow(), {
properties: ["openFile", "multiSelections"]
}).then(result => {
if (result.canceled === false) {
console.log("Selected file paths:")
console.log(result.filePaths)
}
}).catch(err => {
console.log(err)
})
Synchronous: dialog.showOpenDialogSync()
const remote = require("electron").remote
const dialog = remote.dialog
let result = dialog.showOpenDialogSync(remote.getCurrentWindow(), {
properties: ["openFile", "multiSelections"]
})
if (typeof result === "object") {
console.log("Selected file paths:")
console.log(result)
}
Both versions can optionally take a BrowserWindow as the first element. If one is provided, the dialog is shown as a modal window.
Check the Electron dialog documentation for detailed usage information.
Related
I am using React in the Frontend and NodeJS in the backend and I have followed below mentioned Repo to implement Video-call and Screen Share in my application.
https://github.com/ksocha/twilio-screensharing
This is the Docs for Screen sharing but there are no examples to do it.
https://www.twilio.com/docs/video/api/rooms-resource#room-instance-resource
I am stuck and don't know where to start.
Any help would be appreciated .
I tried to use the Screen Recording feature that Twilio provides but found the Composition API hard to work with.
This is the code snippet that I added to my Video Application to implement Screen Recording.
async function StartRecording() {
try {
stream = await navigator.mediaDevices.getDisplayMedia({
video: { mediaSource: "screen" },
});
recorder = new MediaRecorder(stream);
const chunks = [];
recorder.ondataavailable = (e) => chunks.push(e.data);
recorder.onstop = (e) => {
setIsRecord(false);
const completeBlob = new Blob(chunks, { type: chunks[0].type });
const fileReader = new FileReader();
fileReader.onload = function (e) {
let anchor = document.createElement("a");
anchor.href = e.target.result;
anchor.download = `video-${new Date()}`;
anchor.click();
};
fileReader.readAsDataURL(completeBlob);
};
recorder.start();
} catch (err) {
console.log(err);
setIsRecord(false);
}
}
function StopRecording() {
recorder.stop();
stream.getVideoTracks()[0].stop();
}
<span onClick={() => setIsRecord(!isRecord)}>
{!isRecord ? (<div onClick={StartRecording} className='record-on'>
<FiberManualRecordIcon
fontSize='large'
className='videoActionOn'
/>
<p>Start Record</p>
</div>
) : (
<div onClick={StopRecording} className='record-off'>
<HighlightOffIcon
fontSize='large'
className='videoActionOn'
/>
<p>Stop Record</p>
</div>
)}
</span>
Feel Free to leave behind a comment so that I could improve this answer
I have a stenciljs component deployed in an nginx server behind an authentication service. In order to get anything the request must include a cookie containing an access_token. the component is dipslyaed with no preoblem on android devices and on chrome/firfox/IE11/ in desktop devices. the problem is with microsoft edge and on ipad (any navigator) and its due to the browser not sending the cookie to the server. Any hint ?
header.tsx
import { Component, Prop, State, Element } from '#stencil/core';
#Component({
tag: 'pm-header',
styleUrl: 'pm-header.scss',
shadow: true
})
export class PmHeader {
...
render() {
return (
<nav>
<ul>
<li id="menu-icon" class="left menu-icon"
onClick={() => this.toggleFocus('menu-icon')} >
<a>
<ion-icon name="md-apps"></ion-icon>
</a>
</li>
<li id="user-icon" class="right menu-icon"
onClick={() => this.toggleFocus('user-icon')} >
<a>
<ion-icon name="md-contact"></ion-icon>
</a>
</li>
</ul>
</nav>
);
}
}
PS: I'm using stencil/core v0.15.2
So after some digging it turned out that the issue is with ionicons implementation.
They fetch the svgs without sending the credentials which result in an authenticated request. Of course some navigator such as chrome and firefox and even IE11 manages to send the cookies even though it's not explicitly specified that they should.
Anyway, to solve this I had to create a script file that run after the build. This script adds credentials: "include" option to the fetch call so that the cookie get sent.
fix-icons-script.js
/**
* Workaround to fix this ion-icons bug https://github.com/ionic-team/ionicons/issues/640
* To be removed when this bug is fixed
*/
const fs = require('fs');
const workDir = 'dist/component-dir';
fs.readdir(workDir, function(err, items) {
if (err) { return console.log(err); }
for (var i=0; i<items.length; i++) {
if (items[i].endsWith('.entry.js')) {
insertString(workDir + '/' + items[i], '"force-cache"', ',credentials:"include"');
}
}
});
function insertString(file, searchValue, insertValue){
fs.readFile(file, 'utf8', function (err, content) {
if (err) { return console.log(err); }
let newContent = content.substr(0, content.indexOf(searchValue) + searchValue.length);
content = content.substr(newContent.length, content.length);
newContent += insertValue + content;
fs.writeFile(file, newContent, function (err) {
if (err) { return console.log(err); }
console.log('Successfully rewrote ' + file);
});
});
}
This is my react js file code to render media player.
componentDidMount() I imported js file on a load of this page and at the time of render call 'amp' function with options parameter.
componentDidMount () {
const script = document.createElement("script");
script.src = "//amp.azure.net/libs/amp/2.1.5/azuremediaplayer.min.js";
script.async = true;
document.body.appendChild(script);
}
render() {
var myOptions = {
"nativeControlsForTouch": false,
controls: true,
autoplay: true,
width: "640",
height: "400",
}
var myPlayer = amp("azuremediaplayer", myOptions);
myPlayer.src([
{
"src": "//amssamples.streaming.mediaservices.windows.net/91492735-c523-432b-ba01-faba6c2206a2/AzureMediaServicesPromo.ism/manifest",
"type": "application/vnd.ms-sstr+xml"
}
]);
return (
<div className="form-horizontal">
<div className="form-group">
<div className="col-sm-4">Azure Media Player</div>
<div className="col-sm-6">
<video id="azuremediaplayer" class="azuremediaplayer amp-default-skin amp-big-play-centered" tabindex="0"></video>
</div>
</div>
</div>
);
}
}
export default AddItemForm;
And console gives this error
** Line 26: 'amp' is not defined no-undef**
I think if you load the player's script in a sync way like script.async = false;, it would work properly .. I know it would harm the performance, but unfortunately this is the way to go with loading this weirdly packaged player! .. I hate the fact that they didn't make an npm package for it!!
You could provide onload callback for your script like this:
script.onload = () => this.setState({libraryLoaded: true})
And then you can react on the state inside render method
render() {
if (!this.state.libraryLoaded) {
return <span>Loading...</span>
} else {
return ... // your component
}
}
Do not forget to initiate the state with libraryLoaded: false
You can also check my package which is basically doing this loading under the hood.
I have an Electron app + Vue for rooting. I am having problems loading the content into a newly opened window. The window is launched from a Vue component. When it opens I get a blank window and:
Not allowed to load local resource: file:///app/src/Products.vue
I have tried different methods mentioned on stackoverflow but the error still persists.
<style scoped>
</style>
<template>
<div class="container-fluid">
Parent window...
<button type="submit" class="btn btn-primary" v-on:click="add">+ Add Product</button>
</div>
</template>
<script>
export default {
methods: {
add: function () {
const remote = require('electron').remote
const BrowserWindow = remote.BrowserWindow
let win
win = new BrowserWindow({
height: 600,
width: 800
})
win.loadURL(`file://${__dirname}/app/src/Products.vue`)
win.openDevTools()
}
}
}
</script>
In your case, child window must be created from the main process to launch a child window with local resources in Electron. You can use ipc (ipcMain, ipcRenderer) for this.
For example,
In main process :
function createChildWindow(payload) {
let child = new BrowserWindow({ parent :mainWindow
});
child.loadURL(url.format({
pathname: path.join(__dirname, 'child.html'),
protocol: 'file:',
slashes: true,
}));
child.once('ready-to-show', () => {
child.show()
});
}
ipcMain.on('asynchronous-message', (event, arg) => {
console.log(arg) // prints "ping"
createChildWindow(arg);
});
In renderer process(web page) :
const {ipcRenderer} = window.require('electron')
async launchChildWindow(){
ipcRenderer.send('asynchronous-message', '<payload>');
}
You can also write custom events like this,
// Renderer process
ipcRenderer.invoke('some-name', someArgument).then((result) => {
// ...
})
// Main process
ipcMain.handle('some-name', async (event, someArgument) => {
const result = await doSomeWork(someArgument)
return result
})
I am trying to unit test an angular dart decorator but cannot pass the component compile phase.
I am trying to follow this example : https://github.com/vsavkin/angulardart-sample-app/blob/master/test/unit/agenda_item_component_test.dart
The problem is that karma doesn't seem to wait for the compile phase to finish and just skips the test.
part of webpuzzle_spec;
digest() {
inject((TestBed tb) {
tb.rootScope.apply();
});
}
compileComponent(String html, Map scope, callback) {
print("This logs");
return async(() {
inject((TestBed tb) {
print("this should log but doesn't");
final s = tb.rootScope.createChild(scope);
final el = tb.compile(html, scope: s);
microLeap();
digest();
callback(el.shadowRoot);
});
});
}
testWpDropdownMenu() {
group("[WpDropdownMenu]", () {
setUp(setUpInjector);
tearDown(tearDownInjector);
setUp((){
module((Module _) => _..type(TestBed)..type(WpDropdownMenu));
});
html() => '''<span class="dropdown-toggle">
<button type="button" class="btn btn-default">menu to click</button>
<ul class="dropdown-menu">
<li>menu item</li>
</ul>
</span>''';
test("should open menu on click", compileComponent(html(), {}, (shadowRoot) {
print("this never logs :(");
shadowRoot.click();
digest();
var toggleableMenu = shadowRoot.querySelector('.dropdown-menu');
expect(toggleableMenu.style.display, equals('none'));
expect(true, equals(false)); // this should make the test fail
}));
});
}
What is the problem with this code ? Is there a nice example somewhere that explains how to test a component/decorator, only using angular.dart and karma ?