project initialized
This commit is contained in:
commit
c17f98928c
13
.editorconfig
Normal file
13
.editorconfig
Normal file
|
@ -0,0 +1,13 @@
|
|||
# Editor configuration, see https://editorconfig.org
|
||||
root = true
|
||||
|
||||
[*]
|
||||
charset = utf-8
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[*.md]
|
||||
max_line_length = off
|
||||
trim_trailing_whitespace = false
|
46
.gitignore
vendored
Normal file
46
.gitignore
vendored
Normal file
|
@ -0,0 +1,46 @@
|
|||
# See http://help.github.com/ignore-files/ for more about ignoring files.
|
||||
|
||||
# compiled output
|
||||
/dist
|
||||
/tmp
|
||||
/out-tsc
|
||||
# Only exists if Bazel was run
|
||||
/bazel-out
|
||||
|
||||
# dependencies
|
||||
/node_modules
|
||||
|
||||
# profiling files
|
||||
chrome-profiler-events*.json
|
||||
speed-measure-plugin*.json
|
||||
|
||||
# IDEs and editors
|
||||
/.idea
|
||||
.project
|
||||
.classpath
|
||||
.c9/
|
||||
*.launch
|
||||
.settings/
|
||||
*.sublime-workspace
|
||||
|
||||
# IDE - VSCode
|
||||
.vscode/*
|
||||
!.vscode/settings.json
|
||||
!.vscode/tasks.json
|
||||
!.vscode/launch.json
|
||||
!.vscode/extensions.json
|
||||
.history/*
|
||||
|
||||
# misc
|
||||
/.sass-cache
|
||||
/connect.lock
|
||||
/coverage
|
||||
/libpeerconnection.log
|
||||
npm-debug.log
|
||||
yarn-error.log
|
||||
testem.log
|
||||
/typings
|
||||
|
||||
# System Files
|
||||
.DS_Store
|
||||
Thumbs.db
|
5
.prettierrc
Normal file
5
.prettierrc
Normal file
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"trailingComma": "none",
|
||||
"tabWidth": 2,
|
||||
"singleQuote": true
|
||||
}
|
11
.vscode/extensions.json
vendored
Normal file
11
.vscode/extensions.json
vendored
Normal file
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
"recommendations": [
|
||||
"Angular.ng-template",
|
||||
"msjsdiag.debugger-for-chrome",
|
||||
"eamodio.gitlens",
|
||||
"esbenp.prettier-vscode",
|
||||
"ms-vscode.vscode-typescript-tslint-plugin",
|
||||
"VisualStudioExptTeam.vscodeintellicode",
|
||||
"nkokhelox.svg-font-previewer"
|
||||
]
|
||||
}
|
7
.vscode/launch.json
vendored
Normal file
7
.vscode/launch.json
vendored
Normal file
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
// Use IntelliSense to learn about possible attributes.
|
||||
// Hover to view descriptions of existing attributes.
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": []
|
||||
}
|
16
.vscode/settings.json
vendored
Normal file
16
.vscode/settings.json
vendored
Normal file
|
@ -0,0 +1,16 @@
|
|||
{
|
||||
"editor.tabSize": 2,
|
||||
"editor.insertSpaces": true,
|
||||
"editor.formatOnSave": true,
|
||||
"editor.formatOnPaste": true,
|
||||
"editor.autoClosingBrackets": "languageDefined",
|
||||
"editor.trimAutoWhitespace": true,
|
||||
"files.trimTrailingWhitespace": true,
|
||||
"files.trimFinalNewlines": true,
|
||||
"files.watcherExclude": {
|
||||
"**/dist": true
|
||||
},
|
||||
"go.testFlags": ["-v"],
|
||||
"go.testTimeout": "100s",
|
||||
"debug.node.autoAttach": "on"
|
||||
}
|
15
.vscode/tasks.json
vendored
Normal file
15
.vscode/tasks.json
vendored
Normal file
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
// See https://go.microsoft.com/fwlink/?LinkId=733558
|
||||
// for the documentation about the tasks.json format
|
||||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"type": "npm",
|
||||
"script": "build:main:dev",
|
||||
"group": {
|
||||
"kind": "build",
|
||||
"isDefault": true
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
27
README.md
Normal file
27
README.md
Normal file
|
@ -0,0 +1,27 @@
|
|||
# MMessengerLg
|
||||
|
||||
This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 9.0.6.
|
||||
|
||||
## Development server
|
||||
|
||||
Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The app will automatically reload if you change any of the source files.
|
||||
|
||||
## Code scaffolding
|
||||
|
||||
Run `ng generate component component-name` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module`.
|
||||
|
||||
## Build
|
||||
|
||||
Run `ng build` to build the project. The build artifacts will be stored in the `dist/` directory. Use the `--prod` flag for a production build.
|
||||
|
||||
## Running unit tests
|
||||
|
||||
Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io).
|
||||
|
||||
## Running end-to-end tests
|
||||
|
||||
Run `ng e2e` to execute the end-to-end tests via [Protractor](http://www.protractortest.org/).
|
||||
|
||||
## Further help
|
||||
|
||||
To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI README](https://github.com/angular/angular-cli/blob/master/README.md).
|
37
config/webpack.config.js
Normal file
37
config/webpack.config.js
Normal file
|
@ -0,0 +1,37 @@
|
|||
const path = require('path');
|
||||
const webpackNodeExternals = require('webpack-node-externals');
|
||||
|
||||
const rootPath = path.join(__dirname, '..');
|
||||
|
||||
module.exports = [
|
||||
{
|
||||
mode: process.env.ENV || 'development',
|
||||
entry: path.join(rootPath, 'src', 'main'),
|
||||
target: 'electron-main',
|
||||
devtool: 'source-map',
|
||||
externals: [webpackNodeExternals()],
|
||||
resolve: {
|
||||
extensions: ['.ts', '.js']
|
||||
},
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.ts$/,
|
||||
use: [
|
||||
{
|
||||
loader: 'ts-loader',
|
||||
options: {
|
||||
configFile: path.join(rootPath, 'tsconfig.app.json')
|
||||
}
|
||||
}
|
||||
],
|
||||
exclude: /node_modules/
|
||||
}
|
||||
]
|
||||
},
|
||||
output: {
|
||||
path: path.join(rootPath, 'dist'),
|
||||
filename: 'electron-main.js'
|
||||
}
|
||||
}
|
||||
];
|
9256
package-lock.json
generated
Normal file
9256
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
55
package.json
Normal file
55
package.json
Normal file
|
@ -0,0 +1,55 @@
|
|||
{
|
||||
"name": "ucap-lg-desktop",
|
||||
"version": "0.0.0",
|
||||
"scripts": {
|
||||
"start": "npm run build && electron --nolazy --inspect-brk=9229 ./dist/electron-main.js",
|
||||
"build": "webpack --config ./config/webpack.config.js"
|
||||
},
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@tsed/core": "^5.44.11",
|
||||
"@tsed/di": "^5.44.11",
|
||||
"@ucap/electron-core": "~0.0.1",
|
||||
"auto-launch": "^5.0.5",
|
||||
"electron-log": "^4.1.0",
|
||||
"electron-store": "^5.1.1",
|
||||
"electron-updater": "^4.2.5",
|
||||
"electron-window-state": "^5.0.3",
|
||||
"fs-extra": "^9.0.0",
|
||||
"rxjs": "^6.5.4",
|
||||
"semver": "^7.1.3",
|
||||
"tmp": "^0.1.0",
|
||||
"tslib": "^1.10.0",
|
||||
"v8-compile-cache": "^2.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^12.11.1",
|
||||
"@types/jasmine": "~3.5.0",
|
||||
"@types/jasminewd2": "~2.0.3",
|
||||
"cross-env": "^7.0.2",
|
||||
"devtron": "^1.4.0",
|
||||
"electron": "^8.1.1",
|
||||
"electron-builder": "^22.4.1",
|
||||
"electron-debug": "^3.0.1",
|
||||
"electron-devtools-installer": "^2.2.4",
|
||||
"electron-reload": "^1.5.0",
|
||||
"i18next": "^19.3.3",
|
||||
"jasmine-core": "~3.5.0",
|
||||
"jasmine-spec-reporter": "~4.2.1",
|
||||
"karma": "~4.3.0",
|
||||
"karma-chrome-launcher": "~3.1.0",
|
||||
"karma-coverage-istanbul-reporter": "~2.1.0",
|
||||
"karma-jasmine": "~2.0.1",
|
||||
"karma-jasmine-html-reporter": "^1.4.2",
|
||||
"npm-run-all": "^4.1.5",
|
||||
"protractor": "~5.4.3",
|
||||
"ts-loader": "^6.2.1",
|
||||
"ts-node": "~8.3.0",
|
||||
"tslint": "~5.18.0",
|
||||
"typescript": "~3.7.5",
|
||||
"webpack": "^4.42.0",
|
||||
"webpack-cli": "^3.3.11",
|
||||
"webpack-merge": "^4.2.2",
|
||||
"webpack-node-externals": "^1.7.2"
|
||||
}
|
||||
}
|
51
src/app/app.ts
Normal file
51
src/app/app.ts
Normal file
|
@ -0,0 +1,51 @@
|
|||
import * as Electron from 'electron';
|
||||
|
||||
import log from 'electron-log';
|
||||
|
||||
import { AppChannel } from '@ucap/electron-core';
|
||||
import { AppLoader } from '../common/app/app-loader';
|
||||
import { AppSettings } from '../common/app/decorators/app-settings';
|
||||
import { On } from '../common/app/decorators/on';
|
||||
|
||||
import { AppWindow } from './app.window';
|
||||
import { BrowserWindowRegistry } from '../common/browser-window/registries/browser-window.registry';
|
||||
|
||||
@AppSettings({
|
||||
bootstrap: AppWindow
|
||||
})
|
||||
export class App extends AppLoader {
|
||||
constructor() {
|
||||
super();
|
||||
}
|
||||
|
||||
@On(AppChannel.SecondInstance)
|
||||
onSecondInstance(event: Event, argv: string[], workingDirectory: string) {
|
||||
log.info('AppChannel.SecondInstance');
|
||||
}
|
||||
|
||||
@On(AppChannel.Ready)
|
||||
onReady(launchInfo: any) {
|
||||
log.info('AppChannel.Ready');
|
||||
|
||||
this.createMainWindow();
|
||||
}
|
||||
|
||||
@On(AppChannel.Activate)
|
||||
onActivate(event: Event, hasVisibleWindows: boolean) {
|
||||
log.info('AppChannel.Activate');
|
||||
}
|
||||
|
||||
@On(AppChannel.WindowAllClosed)
|
||||
onWindowAllClosed() {
|
||||
log.info('AppChannel.WindowAllClosed');
|
||||
}
|
||||
|
||||
private createMainWindow() {
|
||||
const bootstrap = this.settings.get('bootstrap');
|
||||
|
||||
const provider = BrowserWindowRegistry.get(bootstrap);
|
||||
const i = provider.useFactory(this.electronApp);
|
||||
}
|
||||
|
||||
private createTrayIcon() {}
|
||||
}
|
106
src/app/app.window.ts
Normal file
106
src/app/app.window.ts
Normal file
|
@ -0,0 +1,106 @@
|
|||
import * as Electron from 'electron';
|
||||
import log from 'electron-log';
|
||||
import * as windowStateKeeper from 'electron-window-state';
|
||||
|
||||
import { BrowserWindow } from '../common/browser-window/decorators/browser-window';
|
||||
import { On } from '../common/browser-window/decorators/on';
|
||||
import { BrowserWindowChannel, AppChannel } from '@ucap/electron-core';
|
||||
|
||||
const MIN_WIDTH = 700;
|
||||
const MIN_HEIGHT = 600;
|
||||
const DEFAULT_WIDTH = 1160;
|
||||
const DEFAULT_HEIGHT = 800;
|
||||
|
||||
let savedWindowState: windowStateKeeper.State;
|
||||
|
||||
@BrowserWindow({
|
||||
constructorOptions: {
|
||||
minWidth: MIN_WIDTH,
|
||||
minHeight: MIN_HEIGHT,
|
||||
center: true,
|
||||
backgroundColor: '#fff',
|
||||
webPreferences: {
|
||||
// Disable auxclick event
|
||||
// See https://developers.google.com/web/updates/2016/10/auxclick
|
||||
disableBlinkFeatures: 'Auxclick',
|
||||
// Enable, among other things, the ResizeObserver
|
||||
experimentalFeatures: true,
|
||||
nodeIntegration: true
|
||||
},
|
||||
acceptFirstMouse: true
|
||||
},
|
||||
beforeConstructor: constructorOptions => {
|
||||
savedWindowState = windowStateKeeper({
|
||||
defaultWidth: DEFAULT_WIDTH,
|
||||
defaultHeight: DEFAULT_HEIGHT
|
||||
});
|
||||
|
||||
return {
|
||||
...constructorOptions,
|
||||
x: savedWindowState.x,
|
||||
y: savedWindowState.y,
|
||||
width: savedWindowState.width,
|
||||
height: savedWindowState.height
|
||||
};
|
||||
}
|
||||
})
|
||||
export class AppWindow {
|
||||
constructor(
|
||||
private app: Electron.App,
|
||||
private window: Electron.BrowserWindow
|
||||
) {
|
||||
savedWindowState.manage(this.window);
|
||||
|
||||
this.attachHandlers();
|
||||
}
|
||||
|
||||
@On(BrowserWindowChannel.ReadyToShow)
|
||||
onReadyToShow() {
|
||||
log.info('BrowserWindowChannel.ReadyToShow');
|
||||
}
|
||||
|
||||
@On(BrowserWindowChannel.Close)
|
||||
onClose(event: Event) {
|
||||
log.info('BrowserWindowChannel.Close');
|
||||
}
|
||||
|
||||
@On(BrowserWindowChannel.Focus)
|
||||
onFocus() {
|
||||
log.info('BrowserWindowChannel.Focus');
|
||||
}
|
||||
|
||||
@On(BrowserWindowChannel.Blur)
|
||||
onBlur() {
|
||||
log.info('BrowserWindowChannel.Blur');
|
||||
}
|
||||
|
||||
@On(BrowserWindowChannel.Minimize)
|
||||
onMinimize() {
|
||||
log.info('BrowserWindowChannel.Minimize');
|
||||
}
|
||||
|
||||
@On(BrowserWindowChannel.Maximize)
|
||||
onMaximize() {
|
||||
log.info('BrowserWindowChannel.Maximize');
|
||||
}
|
||||
|
||||
@On(BrowserWindowChannel.Unmaximize)
|
||||
onUnmaximize() {
|
||||
log.info('BrowserWindowChannel.Unmaximize');
|
||||
}
|
||||
|
||||
@On(BrowserWindowChannel.Closed)
|
||||
onClosed() {
|
||||
log.info('BrowserWindowChannel.Closed');
|
||||
}
|
||||
|
||||
private attachHandlers() {
|
||||
this.attachAppHandlers();
|
||||
}
|
||||
|
||||
private attachAppHandlers() {
|
||||
this.app.on(AppChannel.BeforeQuit, (event: Electron.Event) => {
|
||||
log.info('AppChannel.BeforeQuit');
|
||||
});
|
||||
}
|
||||
}
|
114
src/common/app/app-loader.ts
Normal file
114
src/common/app/app-loader.ts
Normal file
|
@ -0,0 +1,114 @@
|
|||
import { Type, constructorOf, Store } from '@tsed/core';
|
||||
import { GlobalProviders, InjectorService, registerProvider } from '@tsed/di';
|
||||
|
||||
import * as Electron from 'electron';
|
||||
|
||||
import { AppOptions } from './decorators/app-settings';
|
||||
import { AppSettingsService } from './services/app-settings.service';
|
||||
import { ELECTRON_APP } from './types/electron-app';
|
||||
import {
|
||||
AppProviderMetadata,
|
||||
AppEventHandlerMetadata
|
||||
} from './models/app-provider.metadata';
|
||||
import { createElectronApp } from './utils/electron';
|
||||
import { ElectronApp } from './decorators/electron-app';
|
||||
|
||||
export abstract class AppLoader {
|
||||
readonly injector: InjectorService;
|
||||
private startedAt = new Date();
|
||||
|
||||
constructor(settings: Partial<AppOptions> = {}) {
|
||||
// create injector with initial configuration
|
||||
this.injector = this.createInjector(this.getConfiguration(this, settings));
|
||||
|
||||
createElectronApp(this.injector);
|
||||
this.attachEventHandler();
|
||||
}
|
||||
|
||||
get settings(): AppSettingsService {
|
||||
return this.injector.settings as AppSettingsService;
|
||||
}
|
||||
|
||||
get electronApp(): Electron.App {
|
||||
return this.injector.get<ElectronApp>(ElectronApp);
|
||||
}
|
||||
|
||||
static async bootstrap<App extends AppLoader>(
|
||||
module: Type<App>,
|
||||
settings: Partial<AppOptions> = {}
|
||||
): Promise<App> {
|
||||
const app = new module(settings);
|
||||
|
||||
return app;
|
||||
}
|
||||
|
||||
async start(): Promise<any> {
|
||||
try {
|
||||
} catch (err) {
|
||||
return Promise.reject(err);
|
||||
}
|
||||
}
|
||||
|
||||
private createInjector(settings: Partial<AppOptions> = {}) {
|
||||
const injector = new InjectorService();
|
||||
injector.settings = this.createSettingsService(injector);
|
||||
// injector.logger = $log;
|
||||
|
||||
// @ts-ignore
|
||||
injector.settings.set(settings);
|
||||
|
||||
/* istanbul ignore next */
|
||||
if (injector.settings.env === 'test') {
|
||||
injector.logger.stop();
|
||||
}
|
||||
|
||||
return injector;
|
||||
}
|
||||
|
||||
private createSettingsService(injector: InjectorService): AppSettingsService {
|
||||
const provider = GlobalProviders.get(AppSettingsService)!.clone();
|
||||
|
||||
provider.instance = injector.invoke<AppSettingsService>(provider.useClass);
|
||||
injector.addProvider(AppSettingsService, provider);
|
||||
|
||||
return provider.instance as any;
|
||||
}
|
||||
|
||||
private getConfiguration(module: any, configuration: any = {}) {
|
||||
const provider = GlobalProviders.get(constructorOf(module))!;
|
||||
|
||||
return { ...provider.configuration, ...configuration };
|
||||
}
|
||||
|
||||
private async invoke(
|
||||
instance: any,
|
||||
handlerMetadata: AppEventHandlerMetadata,
|
||||
args: any[]
|
||||
): Promise<any> {
|
||||
const { methodClassName } = handlerMetadata;
|
||||
|
||||
return await instance[methodClassName](...args);
|
||||
}
|
||||
|
||||
private attachEventHandler() {
|
||||
const handlerMetadata: AppProviderMetadata = Store.from(this).get(
|
||||
ELECTRON_APP
|
||||
);
|
||||
|
||||
if (!handlerMetadata || !handlerMetadata.handlers) {
|
||||
return;
|
||||
}
|
||||
|
||||
const __this = this;
|
||||
|
||||
for (const handler in handlerMetadata.handlers) {
|
||||
if (handlerMetadata.handlers.hasOwnProperty(handler)) {
|
||||
const metadata = handlerMetadata.handlers[handler];
|
||||
|
||||
Electron.app.on(metadata.channel as any, (...args: any[]) => {
|
||||
__this.invoke(__this, metadata, args);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
12
src/common/app/decorators/app-settings.ts
Normal file
12
src/common/app/decorators/app-settings.ts
Normal file
|
@ -0,0 +1,12 @@
|
|||
import { Type, Store } from '@tsed/core';
|
||||
import { IModuleOptions, registerProvider, Module } from '@tsed/di';
|
||||
|
||||
export const APP_OPTIONS = Symbol.for('APP_OPTIONS');
|
||||
|
||||
export interface AppOptions extends IModuleOptions {
|
||||
bootstrap?: Type<any>;
|
||||
}
|
||||
|
||||
export function AppSettings(options?: AppOptions): Function {
|
||||
return Module({ ...options, root: true });
|
||||
}
|
19
src/common/app/decorators/electron-app.ts
Normal file
19
src/common/app/decorators/electron-app.ts
Normal file
|
@ -0,0 +1,19 @@
|
|||
import * as Electron from 'electron';
|
||||
import { Type } from '@tsed/core';
|
||||
import { Inject } from '@tsed/di';
|
||||
|
||||
declare global {
|
||||
namespace Electron {
|
||||
interface App {}
|
||||
}
|
||||
}
|
||||
|
||||
export type ElectronApp = Electron.App;
|
||||
|
||||
export function ElectronApp(
|
||||
target: Type<any>,
|
||||
targetKey: string,
|
||||
descriptor: TypedPropertyDescriptor<Function> | number
|
||||
) {
|
||||
return Inject(ElectronApp)(target, targetKey, descriptor);
|
||||
}
|
18
src/common/app/decorators/on.ts
Normal file
18
src/common/app/decorators/on.ts
Normal file
|
@ -0,0 +1,18 @@
|
|||
import { Store } from '@tsed/core';
|
||||
|
||||
import { AppChannel } from '@ucap/electron-core';
|
||||
|
||||
import { ELECTRON_APP } from '../types/electron-app';
|
||||
|
||||
export function On(channel: AppChannel) {
|
||||
return (target: any, propertyKey: string, descriptor: PropertyDescriptor) => {
|
||||
Store.from(target).merge(ELECTRON_APP, {
|
||||
handlers: {
|
||||
[propertyKey]: {
|
||||
channel,
|
||||
methodClassName: propertyKey
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
12
src/common/app/models/app-provider.metadata.ts
Normal file
12
src/common/app/models/app-provider.metadata.ts
Normal file
|
@ -0,0 +1,12 @@
|
|||
import { AppChannel } from '@ucap/electron-core';
|
||||
|
||||
export interface AppEventHandlerMetadata {
|
||||
channel: AppChannel;
|
||||
methodClassName: string;
|
||||
}
|
||||
|
||||
export interface AppProviderMetadata {
|
||||
handlers: {
|
||||
[propertyKey: string]: AppEventHandlerMetadata;
|
||||
};
|
||||
}
|
16
src/common/app/services/app-settings.service.ts
Normal file
16
src/common/app/services/app-settings.service.ts
Normal file
|
@ -0,0 +1,16 @@
|
|||
import {
|
||||
DIConfiguration,
|
||||
Injectable,
|
||||
ProviderScope,
|
||||
ProviderType
|
||||
} from '@tsed/di';
|
||||
|
||||
@Injectable({
|
||||
scope: ProviderScope.SINGLETON,
|
||||
global: true
|
||||
})
|
||||
export class AppSettingsService extends DIConfiguration {
|
||||
constructor() {
|
||||
super();
|
||||
}
|
||||
}
|
1
src/common/app/types/electron-app.ts
Normal file
1
src/common/app/types/electron-app.ts
Normal file
|
@ -0,0 +1 @@
|
|||
export const ELECTRON_APP = Symbol.for('ELECTRON_APP');
|
20
src/common/app/utils/electron.ts
Normal file
20
src/common/app/utils/electron.ts
Normal file
|
@ -0,0 +1,20 @@
|
|||
import { InjectorService, ProviderScope, registerProvider } from '@tsed/di';
|
||||
|
||||
import * as Electron from 'electron';
|
||||
|
||||
import { ElectronApp } from '../decorators/electron-app';
|
||||
|
||||
export function createElectronApp(injector: InjectorService): void {
|
||||
injector.forkProvider(ElectronApp);
|
||||
}
|
||||
|
||||
registerProvider({
|
||||
provide: ElectronApp,
|
||||
scope: ProviderScope.SINGLETON,
|
||||
global: true,
|
||||
useFactory() {
|
||||
const app = Electron.app;
|
||||
app.allowRendererProcessReuse = true;
|
||||
return app;
|
||||
}
|
||||
});
|
64
src/common/browser-window/decorators/browser-window.ts
Normal file
64
src/common/browser-window/decorators/browser-window.ts
Normal file
|
@ -0,0 +1,64 @@
|
|||
import * as Electron from 'electron';
|
||||
import { registerBrowserWindow } from '../registries/browser-window.registry';
|
||||
import { Store } from '@tsed/core';
|
||||
import { ELECTRON_BROWSER_WINDOW } from '../types/electron-browser-window';
|
||||
import {
|
||||
BrowserWindowEventHandlerMetadata,
|
||||
BrowserWindowProviderMetadata
|
||||
} from '../models/browser-window-provider.metadata';
|
||||
|
||||
export interface BrowserWindowOptions {
|
||||
constructorOptions?: Electron.BrowserWindowConstructorOptions;
|
||||
beforeConstructor?: (
|
||||
constructorOptions: Electron.BrowserWindowConstructorOptions
|
||||
) => Electron.BrowserWindowConstructorOptions;
|
||||
}
|
||||
|
||||
export function BrowserWindow(options?: BrowserWindowOptions): Function {
|
||||
return (target: any): void => {
|
||||
registerBrowserWindow({
|
||||
provide: target,
|
||||
useFactory(app: Electron.App) {
|
||||
options = options || {};
|
||||
let constructorOptions = options.constructorOptions || {};
|
||||
|
||||
if (!!options.beforeConstructor) {
|
||||
constructorOptions = options.beforeConstructor(constructorOptions);
|
||||
}
|
||||
|
||||
const window = new Electron.BrowserWindow(constructorOptions);
|
||||
|
||||
const w = new target(app, window);
|
||||
|
||||
const providerMetadata: BrowserWindowProviderMetadata = Store.from(
|
||||
w
|
||||
).get(ELECTRON_BROWSER_WINDOW);
|
||||
|
||||
if (!!providerMetadata && !!providerMetadata.handlers) {
|
||||
const __this = w;
|
||||
const invoke = async (
|
||||
instance: any,
|
||||
handlerMetadata: BrowserWindowEventHandlerMetadata,
|
||||
args: any[]
|
||||
) => {
|
||||
const { methodClassName } = handlerMetadata;
|
||||
|
||||
return await instance[methodClassName](...args);
|
||||
};
|
||||
|
||||
for (const handler in providerMetadata.handlers) {
|
||||
if (providerMetadata.handlers.hasOwnProperty(handler)) {
|
||||
const metadata = providerMetadata.handlers[handler];
|
||||
|
||||
window.on(metadata.channel as any, (...args: any[]) => {
|
||||
invoke(__this, metadata, args);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return w;
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
18
src/common/browser-window/decorators/on.ts
Normal file
18
src/common/browser-window/decorators/on.ts
Normal file
|
@ -0,0 +1,18 @@
|
|||
import { Store } from '@tsed/core';
|
||||
|
||||
import { BrowserWindowChannel } from '@ucap/electron-core';
|
||||
|
||||
import { ELECTRON_BROWSER_WINDOW } from '../types/electron-browser-window';
|
||||
|
||||
export function On(channel: BrowserWindowChannel) {
|
||||
return (target: any, propertyKey: string, descriptor: PropertyDescriptor) => {
|
||||
Store.from(target).merge(ELECTRON_BROWSER_WINDOW, {
|
||||
handlers: {
|
||||
[propertyKey]: {
|
||||
channel,
|
||||
methodClassName: propertyKey
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
import { BrowserWindowChannel } from '@ucap/electron-core';
|
||||
|
||||
export interface BrowserWindowEventHandlerMetadata {
|
||||
channel: BrowserWindowChannel;
|
||||
methodClassName: string;
|
||||
}
|
||||
|
||||
export interface BrowserWindowProviderMetadata {
|
||||
handlers: {
|
||||
[propertyKey: string]: BrowserWindowEventHandlerMetadata;
|
||||
};
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
import { Provider, GlobalProviders, TypedProvidersRegistry } from '@tsed/di';
|
||||
|
||||
export const PROVIDER_TYPE_BROWSER_WINDOW = 'BrowserWindow';
|
||||
|
||||
export const BrowserWindowRegistry: TypedProvidersRegistry = GlobalProviders.createRegistry(
|
||||
PROVIDER_TYPE_BROWSER_WINDOW,
|
||||
Provider
|
||||
);
|
||||
|
||||
export const registerBrowserWindow = GlobalProviders.createRegisterFn(
|
||||
PROVIDER_TYPE_BROWSER_WINDOW
|
||||
);
|
|
@ -0,0 +1 @@
|
|||
export const ELECTRON_BROWSER_WINDOW = Symbol.for('ELECTRON_BROWSER_WINDOW');
|
17
src/main.ts
Normal file
17
src/main.ts
Normal file
|
@ -0,0 +1,17 @@
|
|||
import log from 'electron-log';
|
||||
import { AppLoader } from './common/app/app-loader';
|
||||
import { App } from './app/app';
|
||||
|
||||
async function bootstrap() {
|
||||
try {
|
||||
log.debug('Start app...');
|
||||
const app = await AppLoader.bootstrap(App);
|
||||
|
||||
await app.start();
|
||||
log.debug('App initialized');
|
||||
} catch (er) {
|
||||
log.error(er);
|
||||
}
|
||||
}
|
||||
|
||||
bootstrap();
|
9
tsconfig.app.json
Normal file
9
tsconfig.app.json
Normal file
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "./out-tsc/app",
|
||||
"types": []
|
||||
},
|
||||
"files": ["src/main.ts"],
|
||||
"include": ["src/**/*.d.ts"]
|
||||
}
|
24
tsconfig.json
Normal file
24
tsconfig.json
Normal file
|
@ -0,0 +1,24 @@
|
|||
{
|
||||
"compileOnSave": false,
|
||||
"compilerOptions": {
|
||||
"baseUrl": "./",
|
||||
"outDir": "./dist/out-tsc",
|
||||
"sourceMap": true,
|
||||
"declaration": false,
|
||||
"downlevelIteration": true,
|
||||
"experimentalDecorators": true,
|
||||
"module": "esnext",
|
||||
"moduleResolution": "node",
|
||||
"importHelpers": true,
|
||||
"target": "es2015",
|
||||
"lib": ["es2018", "dom"],
|
||||
"types": ["node"],
|
||||
"paths": {
|
||||
"@app/*": ["src/app/*"]
|
||||
}
|
||||
},
|
||||
"angularCompilerOptions": {
|
||||
"fullTemplateTypeCheck": true,
|
||||
"strictInjectionParameters": true
|
||||
}
|
||||
}
|
18
tsconfig.spec.json
Normal file
18
tsconfig.spec.json
Normal file
|
@ -0,0 +1,18 @@
|
|||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "./out-tsc/spec",
|
||||
"types": [
|
||||
"jasmine",
|
||||
"node"
|
||||
]
|
||||
},
|
||||
"files": [
|
||||
"src/test.ts",
|
||||
"src/polyfills.ts"
|
||||
],
|
||||
"include": [
|
||||
"src/**/*.spec.ts",
|
||||
"src/**/*.d.ts"
|
||||
]
|
||||
}
|
91
tslint.json
Normal file
91
tslint.json
Normal file
|
@ -0,0 +1,91 @@
|
|||
{
|
||||
"extends": "tslint:recommended",
|
||||
"rules": {
|
||||
"array-type": false,
|
||||
"arrow-parens": false,
|
||||
"deprecation": {
|
||||
"severity": "warning"
|
||||
},
|
||||
"component-class-suffix": true,
|
||||
"contextual-lifecycle": true,
|
||||
"directive-class-suffix": true,
|
||||
"directive-selector": [
|
||||
true,
|
||||
"attribute",
|
||||
"app",
|
||||
"camelCase"
|
||||
],
|
||||
"component-selector": [
|
||||
true,
|
||||
"element",
|
||||
"app",
|
||||
"kebab-case"
|
||||
],
|
||||
"import-blacklist": [
|
||||
true,
|
||||
"rxjs/Rx"
|
||||
],
|
||||
"interface-name": false,
|
||||
"max-classes-per-file": false,
|
||||
"max-line-length": [
|
||||
true,
|
||||
140
|
||||
],
|
||||
"member-access": false,
|
||||
"member-ordering": [
|
||||
true,
|
||||
{
|
||||
"order": [
|
||||
"static-field",
|
||||
"instance-field",
|
||||
"static-method",
|
||||
"instance-method"
|
||||
]
|
||||
}
|
||||
],
|
||||
"no-consecutive-blank-lines": false,
|
||||
"no-console": [
|
||||
true,
|
||||
"debug",
|
||||
"info",
|
||||
"time",
|
||||
"timeEnd",
|
||||
"trace"
|
||||
],
|
||||
"no-empty": false,
|
||||
"no-inferrable-types": [
|
||||
true,
|
||||
"ignore-params"
|
||||
],
|
||||
"no-non-null-assertion": true,
|
||||
"no-redundant-jsdoc": true,
|
||||
"no-switch-case-fall-through": true,
|
||||
"no-var-requires": false,
|
||||
"object-literal-key-quotes": [
|
||||
true,
|
||||
"as-needed"
|
||||
],
|
||||
"object-literal-sort-keys": false,
|
||||
"ordered-imports": false,
|
||||
"quotemark": [
|
||||
true,
|
||||
"single"
|
||||
],
|
||||
"trailing-comma": false,
|
||||
"no-conflicting-lifecycle": true,
|
||||
"no-host-metadata-property": true,
|
||||
"no-input-rename": true,
|
||||
"no-inputs-metadata-property": true,
|
||||
"no-output-native": true,
|
||||
"no-output-on-prefix": true,
|
||||
"no-output-rename": true,
|
||||
"no-outputs-metadata-property": true,
|
||||
"template-banana-in-box": true,
|
||||
"template-no-negated-async": true,
|
||||
"use-lifecycle-interface": true,
|
||||
"use-pipe-transform-interface": true
|
||||
},
|
||||
"rulesDirectory": [
|
||||
"codelyzer"
|
||||
]
|
||||
}
|
Loading…
Reference in New Issue
Block a user