System to handle IPC communication

This commit is contained in:
Geomitron
2020-02-03 23:24:15 -05:00
parent 95c46cad39
commit a4becd92aa
10 changed files with 150 additions and 22 deletions

View File

@@ -17,9 +17,6 @@
},
"plugins": ["@typescript-eslint"],
"rules": {
"@typescript-eslint/no-empty-function": 0,
"@typescript-eslint/no-var-requires": 0,
"@typescript-eslint/no-explicit-any": 0,
"eol-last": ["error", "never"],
"semi": ["off", "never"],
"brace-style": "off",
@@ -29,6 +26,23 @@
"@typescript-eslint/brace-style": ["error"],
"@typescript-eslint/indent": ["error", 2],
"@typescript-eslint/space-before-function-paren": ["error", "never"],
"@typescript-eslint/no-var-requires": ["off"],
"@typescript-eslint/no-empty-function": ["error", {
"allow": [
"constructors"
]
}],
"@typescript-eslint/no-explicit-any": ["error"],
"@typescript-eslint/interface-name-prefix": ["off"],
"@typescript-eslint/member-delimiter-style": ["error", {
"multiline": {
"delimiter": "none"
},
"singleline": {
"delimiter": "semi",
"requireLast": false
}
}],
"@typescript-eslint/explicit-function-return-type": "off",
"@typescript-eslint/no-use-before-define": ["error", {
"functions": false,

View File

@@ -1,4 +1,5 @@
import { Component } from '@angular/core'
import { Component, OnInit } from '@angular/core'
import { ElectronService } from './core/services/electron.service'
@Component({
selector: 'app-root',
@@ -6,28 +7,25 @@ import { Component } from '@angular/core'
<!--The content below is only a placeholder and can be replaced.-->
<div style="text-align:center" class="content">
<h1>
Welcome to {{title}}!
{{title}}
</h1>
<span style="display: block">{{ title }} app is running!</span>
<img width="300" alt="Angular Logo" src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNTAgMjUwIj4KICAgIDxwYXRoIGZpbGw9IiNERDAwMzEiIGQ9Ik0xMjUgMzBMMzEuOSA2My4ybDE0LjIgMTIzLjFMMTI1IDIzMGw3OC45LTQzLjcgMTQuMi0xMjMuMXoiIC8+CiAgICA8cGF0aCBmaWxsPSIjQzMwMDJGIiBkPSJNMTI1IDMwdjIyLjItLjFWMjMwbDc4LjktNDMuNyAxNC4yLTEyMy4xTDEyNSAzMHoiIC8+CiAgICA8cGF0aCAgZmlsbD0iI0ZGRkZGRiIgZD0iTTEyNSA1Mi4xTDY2LjggMTgyLjZoMjEuN2wxMS43LTI5LjJoNDkuNGwxMS43IDI5LjJIMTgzTDEyNSA1Mi4xem0xNyA4My4zaC0zNGwxNy00MC45IDE3IDQwLjl6IiAvPgogIDwvc3ZnPg==">
</div>
<h2>Here are some links to help you start: </h2>
<button class="ui button">Fomantic UI test</button>
<ul>
<li>
<h2><a target="_blank" rel="noopener" href="https://angular.io/tutorial">Tour of Heroes</a></h2>
</li>
<li>
<h2><a target="_blank" rel="noopener" href="https://angular.io/cli">CLI Documentation</a></h2>
</li>
<li>
<h2><a target="_blank" rel="noopener" href="https://blog.angular.io/">Angular blog</a></h2>
</li>
</ul>
<router-outlet></router-outlet>
`,
styles: []
})
export class AppComponent {
title = 'NewBridge'
export class AppComponent implements OnInit {
title = 'Loading title...'
constructor(private electronService: ElectronService) { }
async ngOnInit() {
const response = await this.electronService.invoke('test-event-A', { value1: 'AAAAA', value2: 42 })
this.title = response
}
}

View File

@@ -0,0 +1,9 @@
import { Injectable } from '@angular/core'
@Injectable({
providedIn: 'root'
})
export class DownloadService {
constructor() { }
}

View File

@@ -0,0 +1,48 @@
import { Injectable } from '@angular/core'
// If you import a module but never use any of the imported values other than as TypeScript types,
// the resulting javascript file will look as if you never imported the module at all.
import { ipcRenderer, webFrame, remote } from 'electron'
import * as childProcess from 'child_process'
import * as fs from 'fs'
import * as util from 'util'
import { IPCEvents } from '../../../electron/shared/IPCHandler'
@Injectable({
providedIn: 'root'
})
export class ElectronService {
ipcRenderer: typeof ipcRenderer
webFrame: typeof webFrame
remote: typeof remote
childProcess: typeof childProcess
fs: typeof fs
util: typeof util
get isElectron() {
return !!(window && window.process && window.process.type)
}
constructor() {
// Conditional imports
if (this.isElectron) {
this.ipcRenderer = window.require('electron').ipcRenderer
this.webFrame = window.require('electron').webFrame
this.remote = window.require('electron').remote
this.childProcess = window.require('child_process')
this.fs = window.require('fs')
this.util = window.require('util')
}
}
/**
* Calls an async function in the main process.
* @param event The name of the IPC event to invoke.
* @param data The data object to send across IPC.
* @returns A promise that resolves to the output data.
*/
async invoke<E extends keyof IPCEvents>(event: E, data: IPCEvents[E]['input']) {
return this.ipcRenderer.invoke(event, data) as Promise<IPCEvents[E]['output']>
}
}

View File

@@ -0,0 +1,11 @@
import { IPCHandler } from '../shared/IPCHandler'
import { TestInput } from '../shared/interfaces/test.interface'
export default class TestHandler implements IPCHandler<'test-event-A'> {
event = 'test-event-A' as 'test-event-A'
async handler(data: TestInput) {
await new Promise<void>((resolve) => setTimeout(() => resolve(), 3000))
return `Processed data with value1 = ${data.value1} and value2 + 5 = ${data.value2 + 5}`
}
}

View File

@@ -3,7 +3,7 @@ import * as path from 'path'
import * as url from 'url'
// IPC Handlers
// import { getIPCHandlers } from './src/assets/electron/shared/IPCHandler'
import { getIPCHandlers } from './shared/IPCHandler'
let mainWindow: BrowserWindow
const args = process.argv.slice(1)
@@ -60,7 +60,7 @@ function createBridgeWindow() {
mainWindow.setMenu(null)
// IPC handlers
// getIPCHandlers().map(handler => ipcMain.handle(handler.event, (_event, ...args) => handler.handler(args[0])))
getIPCHandlers().map(handler => ipcMain.handle(handler.event, (_event, ...args) => handler.handler(args[0])))
// Load angular app
mainWindow.loadURL(getLoadUrl())

View File

@@ -0,0 +1,32 @@
import TestHandler from '../ipc/TestHandler.ipc'
import { TestInput } from './interfaces/test.interface'
/**
* To add a new IPC listener:
* 1.) Write input/output interfaces
* 2.) Add the event to IPCEvents
* 3.) Write a class that implements IPCHandler
* 4.) Add the class to getIPCHandlers
*/
export function getIPCHandlers(): IPCHandler<keyof IPCEvents>[] {
return [
new TestHandler()
]
}
export type IPCEvents = {
['test-event-A']: {
input: TestInput
output: string
}
['test-event-B']: {
input: number
output: number
}
}
export interface IPCHandler<E extends keyof IPCEvents> {
event: E
handler(data: IPCEvents[E]['input']): Promise<IPCEvents[E]['output']> | IPCEvents[E]['output']
}

View File

@@ -0,0 +1,4 @@
export interface TestInput {
value1: string
value2: number
}

View File

@@ -2,10 +2,9 @@
<html lang="en">
<head>
<meta charset="utf-8">
<title>NewBridge</title>
<title>Bridge</title>
<base href="/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="favicon.ico">
</head>
<body>
<app-root></app-root>

13
src/typings.d.ts vendored Normal file
View File

@@ -0,0 +1,13 @@
/* SystemJS module definition */
declare var nodeModule: NodeModule
interface NodeModule {
id: string
}
// @ts-ignore
declare var window: Window
interface Window {
process: any
require: any
jQuery: any
}