diff --git a/eslintrc.json b/eslintrc.json index aba528c..a7e5774 100644 --- a/eslintrc.json +++ b/eslintrc.json @@ -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, diff --git a/src/app/app.component.ts b/src/app/app.component.ts index a0e6fd9..191bd1d 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -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'

- Welcome to {{title}}! + {{title}}

{{ title }} app is running! Angular Logo

Here are some links to help you start:

- + `, 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 + } } \ No newline at end of file diff --git a/src/app/core/services/download.service.ts b/src/app/core/services/download.service.ts new file mode 100644 index 0000000..fd78287 --- /dev/null +++ b/src/app/core/services/download.service.ts @@ -0,0 +1,9 @@ +import { Injectable } from '@angular/core' + +@Injectable({ + providedIn: 'root' +}) +export class DownloadService { + + constructor() { } +} \ No newline at end of file diff --git a/src/app/core/services/electron.service.ts b/src/app/core/services/electron.service.ts new file mode 100644 index 0000000..b72d1f9 --- /dev/null +++ b/src/app/core/services/electron.service.ts @@ -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(event: E, data: IPCEvents[E]['input']) { + return this.ipcRenderer.invoke(event, data) as Promise + } +} \ No newline at end of file diff --git a/src/electron/ipc/TestHandler.ipc.ts b/src/electron/ipc/TestHandler.ipc.ts new file mode 100644 index 0000000..2d097e4 --- /dev/null +++ b/src/electron/ipc/TestHandler.ipc.ts @@ -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((resolve) => setTimeout(() => resolve(), 3000)) + + return `Processed data with value1 = ${data.value1} and value2 + 5 = ${data.value2 + 5}` + } +} \ No newline at end of file diff --git a/src/electron/main.ts b/src/electron/main.ts index ed8a82e..2e86c2b 100644 --- a/src/electron/main.ts +++ b/src/electron/main.ts @@ -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()) diff --git a/src/electron/shared/IPCHandler.ts b/src/electron/shared/IPCHandler.ts new file mode 100644 index 0000000..fe67095 --- /dev/null +++ b/src/electron/shared/IPCHandler.ts @@ -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[] { + return [ + new TestHandler() + ] +} + +export type IPCEvents = { + ['test-event-A']: { + input: TestInput + output: string + } + ['test-event-B']: { + input: number + output: number + } +} + +export interface IPCHandler { + event: E + handler(data: IPCEvents[E]['input']): Promise | IPCEvents[E]['output'] +} \ No newline at end of file diff --git a/src/electron/shared/interfaces/test.interface.ts b/src/electron/shared/interfaces/test.interface.ts new file mode 100644 index 0000000..2e54d30 --- /dev/null +++ b/src/electron/shared/interfaces/test.interface.ts @@ -0,0 +1,4 @@ +export interface TestInput { + value1: string + value2: number +} \ No newline at end of file diff --git a/src/index.html b/src/index.html index d242d29..3dae072 100644 --- a/src/index.html +++ b/src/index.html @@ -2,10 +2,9 @@ - NewBridge + Bridge - diff --git a/src/typings.d.ts b/src/typings.d.ts new file mode 100644 index 0000000..660225e --- /dev/null +++ b/src/typings.d.ts @@ -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 +} \ No newline at end of file