Can I call Ionic 4 / Capacitor Electron code from the Ionic part of the application?

扶醉桌前 提交于 2020-01-15 10:14:37

问题


I am investigating using Ionic 4/ Capacitor to target Windows via the Electron option, for an application where I want to use SQLite.

Using the Ionic Native SQLite plugin, which wraps this Cordova plugin, out of the box, as far as I can see, the Windows support is for UWP, and not Desktop, which runs using Electron in Ionic Capacitor wrapper.

My plan, was to see if I could use Electron SQLite package, and then call this from my Ionic application by making a wrapper class for the Ionic native similar to what I used to get browser support by following this tutoral

If I can call the Electron code from my Ionic app, then I can't see why this wouldn't work.

So, my question here is, can I call code (I will add functions to use the SQlite) I add to the hosting Electron application from within the Ionic (web) code? And if so, how?

Thanks in advance for any help

[UPDATE1]

Tried the following...

From an Ionic page, I have a button click handler where I raise an event..

export class HomePage {

 public devtools() : void {
  let emit = new EventEmitter(true);
  emit.emit('myEvent');

   var evt = new CustomEvent('myEvent');
   window.dispatchEvent(evt);
  }

Then within the Electron projects index.js, I tried..

    mainWindow.webContents.on('myEvent', () => {
      mainWindow.openDevTools();
    });

    const ipc = require('electron').ipcMain
    ipc.on('myEvent', (ev, arg) => {
      mainWindow.openDevTools();
    });

But neither worked.

I should mention I know very little about Electron. This is my first exposure to it (via Capacitor)


回答1:


Yes you can! Remember electron use a chromium and you have support 😁




回答2:


I dug into this yesterday and have an example for you using angular(this should apply to ionic too). in your service declare require so we can use it

  //Below your imports
  declare function require(name:string);

Then in whatever function you want to use it in:

// Require the ipcRenderer so we can emit to the ipc to call a function
// Use ts-ignore or else angular wont compile
// @ts-ignore
const ipc = window.require('electron').ipcRenderer;
// Send a message to the ipc
// @ts-ignore
ipc.send('test', 'google');

Then in the created index.js within the electron folder

// Listening for the emitted event
ipc.addListener('test', (ev, arg) => {
    // console.log('ev', ev);
    console.log('arg', arg);
});

Its probably not the correct way to access it but its the best way i could find. From my understanding the ipcRenderer is used for when you have multiple browsers talking to each other within electron. so in our situation it enables our web layer to communicate with the electron stuff




回答3:


In case someone is interested, this is how I solved this. Im am using Ionic 4 / Capacitor + Vue 3.

In my entry file (app.ts) I have declared a global interface called Window as follows:

// app.ts
declare global { interface Window { require: any; } }

Then, I have written the following class:

// electron.ts
import { isPlatform } from '@ionic/core';

export class Electron
{
    public static isElectron = isPlatform(window, 'electron');
    public static getElectron()
    {
        if (this.isElectron)
        {
            return window.require('electron');
        }
        else
        {
            return null;
        }
    }
    public static getIpcRenderer()
    {
        if (this.isElectron)
        {
            return window.require('electron').ipcRenderer;
        }
        else
        {
            return null;
        }
    }
    public static getOs()
    {
        if (this.isElectron)
        {
            return window.require('os');
        }
        else
        {
            return null;
        }
    }
}

And I use it like this:

//electronabout.ts
import { IAbout } from './iabout';
import { Plugins } from '@capacitor/core';
import { Electron } from '../utils/electron';

export class ElectronAbout implements IAbout
{
  constructor() { }
  public async getDeviceInfo()
  {
    let os = Electron.getOs();
    let devInfo =
    {
      arch: os.arch(),
      platform: os.platform(),
      type: os.type(),
      userInfo: os.userInfo()
    };

    return devInfo;
  }
  public async showDeviceInfo()
  {
    const devInfo = await this.getDeviceInfo();
    await Plugins.Modals.alert({ title: 'Info from Electron', message: JSON.stringify(devInfo) });
  }
}

This is working but, of course, I still need to refactor the Electron class (electron.ts). Probably using the singleton pattern is a better idea.

I hope this helps.

Update

You can communicate from the render process with your main process (index.js) like this:

//somefile.ts
if (Electron.isElectron)
{
     let ipc = Electron.getIpcRenderer();
     ipc.once('hide-menu-button', (event) => { this.isMenuButtonVisible = false; });
 }

//index.js
let newWindow = new BrowserWindow(windowOptions);
newWindow.loadURL(`file://${__dirname}/app/index.html`);
newWindow.webContents.on('dom-ready', () => {
         newWindow.webContents.send('hide-menu-button');
         newWindow.show();
});


来源:https://stackoverflow.com/questions/53976737/can-i-call-ionic-4-capacitor-electron-code-from-the-ionic-part-of-the-applicat

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!