Electron Builder Vue cli 3 application on Windows throwing error registerStandardSchemes undefined - vue.js

Background
We are building an Electron application and have been able to work on it, and build it using Linux and Mac OS. When we move it to a Windows machine in development or when build on a Mac OS machine then ran on the Windows machine, it fails.
When we follow the instructions here it says,
vue add electron-builder
yarn electron:serve
should run the application. On a fresh install using Windows this fails for us.
Problem
When we try and start the application on Windows we get an error,
TypeError
electron__WEBPACK_IMPORTED_MODULE_0__.protocol.registerStandardSchemes
is not a function
Example
This line comes with the boilerplate when we add Electron Builder to the app that seems to be throwing the error.
protocol.registerStandardSchemes(['app'], { secure: true })
It is being used like this,
import { protocol} from 'electron'
protocol.registerStandardSchemes(['app'], { secure: true })
// Helper to create our main view BrowserWindow
function createWindow() {
// Create the browser window.
win = new BrowserWindow({ width: 800, height: 600 })
if (process.env.WEBPACK_DEV_SERVER_URL) {
// Load the url of the dev server if in development mode
win.loadURL(process.env.WEBPACK_DEV_SERVER_URL)
if (!process.env.IS_TEST) win.webContents.openDevTools()
} else {
createProtocol('app')
// Load the index.html when not in development
win.loadURL('app://./index.html')
}
}
What We Tried
When I console.log protocol the only key available is, registerSchemesAsPrivileged which is in the docs but not what came with the boiler and nor does it work. I can see at this page that the registerStandardSchemes is referenced in a paragraph but it is not well explained in it's own section like the rest of the methods on that page.
Question
What does one need to do to access the method, protocol.registerStandardSchemes(['app'], { secure: true }) when running an Electron-Builder application scaffold with Vue CLI 3 on Windows 10?

I recently had this issue - if you're just looking to get back to development, running vue add electron-builder again fixed it for me.

Related

Running html only if running in Electron.js [duplicate]

I'm trying to serve real react app on electron app. It doesn't mean I'm developing electron app with react. I've created a react app and injected it into electron app. (Like slack, it will serve as a web application and desktop application.) But I'm confused that send desktop notifications.
Now the main question is:
How can I get the application type. I mean, is user using my app on web or on desktop. How can I get this?
Thank you :)
There are many ways to detect whether you are running in a desktop environment or not.
You can check the User-Agent and you can set the userAgent value in Electron when you call loadURL.
Another way is declaring a global variable using a preload script.
// main process
new BrowserWindow({
webPreferences: {
preload: "preload.js",
},
});
// preload.js
// you don't need to use contextBridge if contextIsolation is false
// but it's true by default in Electron 12
const { contextBridge } = require("electron");
contextBridge.exposeInMainWorld("IN_DESKTOP_ENV", true);
// renderer process (your React world)
if (globalThis.IN_DESKTOP_ENV) {
// do something...
}

PWA InjectManifest workbox console / debug output suddenly disabled (Vue.js / Quasar Framework)

I'm building a PWA with Vue.js / Quasar Framework and recently added the PWA capability. I changed the "workboxPluginMode" property to "InjectManifest" and at first Workbox gave me debug / console as expected.
Also, the "custom-service-worker.js" definetly gets picked up by the process because it displays an error when i remove this line:
precacheAndRoute(self.__WB_MANIFEST)
So the file is recognized and actively using the defined caching strategies (i think), but it won't provide me any debug info or console.log's on console anymore. I really don't know what i have changed to do that.
My "custom-service-worker.js" looks like this:
import { precacheAndRoute } from 'workbox-precaching'
import { registerRoute } from 'workbox-routing'
import { StaleWhileRevalidate } from 'workbox-strategies'
console.log('custom service worker active')
// Use with precache injection
precacheAndRoute(self.__WB_MANIFEST)
// Caching strategies
registerRoute(
({url}) => {
console.log(url)
// url.pathname.startsWith('/images')
},
new StaleWhileRevalidate()
);
self.addEventListener('fetch', function(event) {
console.log(event)
event.respondWith(fetch(event.request));
})
I have no clue why, but the console debug output of workbox was only displayed in my default browser (Vivaldi). I wanted to work on plain Chromium because I couldn't install my PWA with Vivaldi (no installation prompt popped up), but that also works now. Have literally no explanation for this, but this is PWA development I guess, it is what it is. Anyways, problem solved for me.

Unifying localhost dev api server access for expo app across Android, IOS, and web?

I'm setting up a simple React Native learning app for several students on Expo, that also talks to an API server the student is learning to code.
The student's API server is run via node server.js, and serves on localhost:3000 on the student's machine. It has nothing to do with expo.
I want students to be able to run their app via any of expo start --android, expo start --ios, or expo start --web, on the same machine that runs their API server. Each student runs from home on a different home wifi network, and doesn't necessarily know the ins and outs of ip addresses or networking.
When using expo start --web, we get CORS exceptions, unless we use the custom webpack.config.js work around (first create webpack.config.js via https://docs.expo.io/guides/customizing-webpack/, then put this in webpack.config.js):
const createExpoWebpackConfigAsync = require('#expo/webpack-config');
module.exports = async function(env, argv) {
const config = await createExpoWebpackConfigAsync(env, argv);
if (config.mode === 'development') {
config.devServer.proxy = {
'/**': {
target: {
host: 'localhost',
protocol: 'http:',
port: 3000,
},
secure: false,
changeOrigin: true,
logLevel: 'info',
},
};
}
return config;
};
This is great, because we can make api calls to ./end/point without knowing the student's ip address, and the webpack devServer launched by expo-cli effectively proxies around to http://localhost:3000/end/point on the student's development machine.
Meanwhile, for iOS and Android, I've found this snippet:
import Constants from "expo-constants";
const { manifest } = Constants;
const SERVER_URL = "http://"+manifest.debuggerHost.split(`:`).shift().concat(`:3000`)+"/";
and then using SERVER_URL when using fetch().
But, we're missing a unified solution that works agnostic of which environment we're in (web, ios, or android). The webpack proxy only appears to be on and work when using the expo web client (expo-cli doesn't launch webpack for ios or android), and the 2nd option (A) doesn't work out of the box on web and (B) would trigger a CORS exception anyway.
How can I elegantly write one bit of code, or otherwise set up the project for the students, so that (A) they don't need to know their dev machine's ip address, or what that means and (B) it will work regardless of whether they're in the web, android, or ios expo client?
Don't like this as an answer and would prefer someone who knows better to point out better, but this is what I ended up using that seems to work, at least in development:
// Some chatter that Contants.manifest needs to come from a different package?
import Constants from "expo-constants";
const { manifest } = Constants;
const SERVER_URL = (() => {
// TODO - put a "prod" api server somewhere
// Android / IOS - no CORS issue.
if (!!manifest.debuggerHost) {
return "http://"+manifest.debuggerHost.split(`:`).shift().concat(`:3000/`);
}
// Expo Web client, making use of webpack.config.js (see original question) for devServer proxy.
else {
return "./";
}
})();
...
fetch(SERVER_URL + 'some_endpoint/').then(...)

How to refer other html file to load in production mode of application that are developed using electron?

I have problem in building electron application, which is made using electron.js and vue.js.
The development is almost done, so I need to build it and make production.
Basically, my project has license system, so when the program starts, users should activate it by entering license key. I wrote this part inside activate.html. So, inside public folder, there are two html files, one is default index.html, and the other is activate.html
Inside activate.html, when activation is success, startMain() javascript function is called. Inside this function, the program is navigated to main program, especially to index.html. This html file is Vue application, and then main program is started.
All this process is working fine in the development mode. But when it
comes to production, this is not working anymore. I probably know why this
happens, this is just because index.html is not available in
production mode when all these are built up.
Alternatively, I tried to load localhost:8080 inside
startMain(). But also this works fine in development mode, but unluckily, we don't have localhost server on production mode, so this
doesn't solve the problem.
This is startMain() inside activate.html
function startMain() {
window.__static = "index.html";
// Alternatively, we can use location.href on development mode.
// window.location.href = "http://localhost:8080/";
}
This is background.js ( electron main engine)
function createWindow() {
// Create the browser window.
win = new BrowserWindow({
width: 1400,
height: 900,
titleBarStyle: "hiddenInset"
});
win.setMenuBarVisibility(false);
if (isDevelopment) {
// Load the url of the dev server if in development mode
// win.loadURL(process.env.WEBPACK_DEV_SERVER_URL);
win.loadURL(`file://${process.cwd()}/public/activate.html`);
// if (!process.env.IS_TEST) win.webContents.openDevTools()
} else {
createProtocol("app");
// Load the index.html when not in development
win.loadFile("activate.html");
}
win.on("closed", () => {
win = null;
});
}
What I want is to make it run correctly in production mode.
Specifically, when the user finishes activation flow ( activate.html),
it should start main program ( index.html )
Please help me with this issue. I welcome any comments.
I built this application using vue-cli-plugin-electron-builder package
In Vue usually you use vue-router to switch between views. You set the BrowserWindow.location the first time, in background.js, but after that you are in the Vue app and you make router calls like this:
router.replace({ name: "index" }).catch(() => { });
It's hard to guess what to do in your case, without seeing the rest of your activate.html. You need to define router in your App and probably want to convert your activate.html into an activate.vue component and make it the proper first page of your App.
I think the cli-plugin boilerplate will call main.js where you will define your app and bootstraps it. You add router there:
import router from "./router";
window.$app = new Vue({
router,
In your bootstrap function you can also call something like router.replace({ name: "activate"}) to start your app with your activate vue component.

Fatal error when registering global shortcut in Electron

I have tried to register global keyboard shortcut using Electron's global-shortcut module, as per the documentation page. (https://github.com/atom/electron/blob/master/docs/api/global-shortcut.md)
However, I received the following error in my console when I run electron:
[20097:0608/181936:FATAL:global_shortcut_listener_x11.cc(49)] Check failed: BrowserThread::CurrentlyOn(BrowserThread::UI).
I am running Electron on Ubuntu 14.04 LTS. I would like to ask if this error is platform-specific. Are there any steps I missed out from the documentation page? If there isn't, is there any way to get around this error? Thanks.
Your application should be ready before you register your shortcuts.
Here is an example:
var app = require('app');
var globalShortcut = require('global-shortcut');
// Your app must be ready before the registration
app.on('ready', function() {
console.log('Your app is ready!');
// You can now register your shortcuts
globalShortcut.register('ctrl+alt+j', function() {
console.log('You fired ctrl+alt+j !!!');
});
});