refactoring
316
angular.json
|
@ -30,16 +30,102 @@
|
|||
"styles": ["projects/ucap-webmessenger-app/src/styles.scss"],
|
||||
"scripts": [],
|
||||
"customWebpackConfig": {
|
||||
"path": "./config/renderer.webpack.config.js",
|
||||
"mergeStrategies": { "externals": "replace" }
|
||||
"path": "./config/angular.webpack.config.js"
|
||||
}
|
||||
},
|
||||
"configurations": {
|
||||
"production": {
|
||||
"browser-development": {
|
||||
"fileReplacements": [
|
||||
{
|
||||
"replace": "projects/ucap-webmessenger-app/src/environments/environment.ts",
|
||||
"with": "projects/ucap-webmessenger-app/src/environments/environment.prod.ts"
|
||||
"with": "projects/ucap-webmessenger-app/src/environments/environment-browser.dev.ts"
|
||||
}
|
||||
],
|
||||
"optimization": false,
|
||||
"outputHashing": "all",
|
||||
"sourceMap": true,
|
||||
"extractCss": true,
|
||||
"namedChunks": false,
|
||||
"aot": false,
|
||||
"extractLicenses": true,
|
||||
"vendorChunk": false,
|
||||
"buildOptimizer": false,
|
||||
"budgets": [
|
||||
{
|
||||
"type": "initial",
|
||||
"maximumWarning": "2mb",
|
||||
"maximumError": "5mb"
|
||||
},
|
||||
{
|
||||
"type": "anyComponentStyle",
|
||||
"maximumWarning": "6kb",
|
||||
"maximumError": "10kb"
|
||||
}
|
||||
]
|
||||
},
|
||||
"browser-production": {
|
||||
"fileReplacements": [
|
||||
{
|
||||
"replace": "projects/ucap-webmessenger-app/src/environments/environment.ts",
|
||||
"with": "projects/ucap-webmessenger-app/src/environments/environment-browser.prod.ts"
|
||||
}
|
||||
],
|
||||
"optimization": true,
|
||||
"outputHashing": "all",
|
||||
"sourceMap": false,
|
||||
"extractCss": true,
|
||||
"namedChunks": false,
|
||||
"aot": true,
|
||||
"extractLicenses": true,
|
||||
"vendorChunk": false,
|
||||
"buildOptimizer": true,
|
||||
"budgets": [
|
||||
{
|
||||
"type": "initial",
|
||||
"maximumWarning": "2mb",
|
||||
"maximumError": "5mb"
|
||||
},
|
||||
{
|
||||
"type": "anyComponentStyle",
|
||||
"maximumWarning": "6kb",
|
||||
"maximumError": "10kb"
|
||||
}
|
||||
]
|
||||
},
|
||||
"renderer-development": {
|
||||
"fileReplacements": [
|
||||
{
|
||||
"replace": "projects/ucap-webmessenger-app/src/environments/environment.ts",
|
||||
"with": "projects/ucap-webmessenger-app/src/environments/environment-renderer.dev.ts"
|
||||
}
|
||||
],
|
||||
"optimization": false,
|
||||
"outputHashing": "all",
|
||||
"sourceMap": true,
|
||||
"extractCss": true,
|
||||
"namedChunks": false,
|
||||
"aot": false,
|
||||
"extractLicenses": true,
|
||||
"vendorChunk": false,
|
||||
"buildOptimizer": false,
|
||||
"budgets": [
|
||||
{
|
||||
"type": "initial",
|
||||
"maximumWarning": "2mb",
|
||||
"maximumError": "5mb"
|
||||
},
|
||||
{
|
||||
"type": "anyComponentStyle",
|
||||
"maximumWarning": "6kb",
|
||||
"maximumError": "10kb"
|
||||
}
|
||||
]
|
||||
},
|
||||
"renderer-production": {
|
||||
"fileReplacements": [
|
||||
{
|
||||
"replace": "projects/ucap-webmessenger-app/src/environments/environment.ts",
|
||||
"with": "projects/ucap-webmessenger-app/src/environments/environment-renderer.prod.ts"
|
||||
}
|
||||
],
|
||||
"optimization": true,
|
||||
|
@ -72,8 +158,17 @@
|
|||
"browserTarget": "ucap-webmessenger-app:build"
|
||||
},
|
||||
"configurations": {
|
||||
"production": {
|
||||
"browserTarget": "ucap-webmessenger-app:build:production"
|
||||
"browser-development": {
|
||||
"browserTarget": "ucap-webmessenger-app:build:browser-development"
|
||||
},
|
||||
"browser-production": {
|
||||
"browserTarget": "ucap-webmessenger-app:build:browser-production"
|
||||
},
|
||||
"renderer-development": {
|
||||
"browserTarget": "ucap-webmessenger-app:build:renderer-development"
|
||||
},
|
||||
"renderer-production": {
|
||||
"browserTarget": "ucap-webmessenger-app:build:renderer-production"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -84,7 +179,7 @@
|
|||
}
|
||||
},
|
||||
"test": {
|
||||
"builder": "@angular-devkit/build-angular:karma",
|
||||
"builder": "@angular-builders/custom-webpack:karma",
|
||||
"options": {
|
||||
"main": "projects/ucap-webmessenger-app/src/test.ts",
|
||||
"polyfills": "projects/ucap-webmessenger-app/src/polyfills.ts",
|
||||
|
@ -95,7 +190,10 @@
|
|||
"projects/ucap-webmessenger-app/src/assets"
|
||||
],
|
||||
"styles": ["projects/ucap-webmessenger-app/src/styles.scss"],
|
||||
"scripts": []
|
||||
"scripts": [],
|
||||
"customWebpackConfig": {
|
||||
"path": "./config/angular.webpack.config.js"
|
||||
}
|
||||
}
|
||||
},
|
||||
"lint": {
|
||||
|
@ -1182,72 +1280,6 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"ucap-webmessenger-native": {
|
||||
"projectType": "library",
|
||||
"root": "projects/ucap-webmessenger-native",
|
||||
"sourceRoot": "projects/ucap-webmessenger-native/src",
|
||||
"prefix": "ucap-native",
|
||||
"architect": {
|
||||
"build": {
|
||||
"builder": "@angular-devkit/build-ng-packagr:build",
|
||||
"options": {
|
||||
"tsConfig": "projects/ucap-webmessenger-native/tsconfig.lib.json",
|
||||
"project": "projects/ucap-webmessenger-native/ng-package.json"
|
||||
}
|
||||
},
|
||||
"test": {
|
||||
"builder": "@angular-devkit/build-angular:karma",
|
||||
"options": {
|
||||
"main": "projects/ucap-webmessenger-native/src/test.ts",
|
||||
"tsConfig": "projects/ucap-webmessenger-native/tsconfig.spec.json",
|
||||
"karmaConfig": "projects/ucap-webmessenger-native/karma.conf.js"
|
||||
}
|
||||
},
|
||||
"lint": {
|
||||
"builder": "@angular-devkit/build-angular:tslint",
|
||||
"options": {
|
||||
"tsConfig": [
|
||||
"projects/ucap-webmessenger-native/tsconfig.lib.json",
|
||||
"projects/ucap-webmessenger-native/tsconfig.spec.json"
|
||||
],
|
||||
"exclude": ["**/node_modules/**"]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"ucap-webmessenger-native-electron": {
|
||||
"projectType": "library",
|
||||
"root": "projects/ucap-webmessenger-native-electron",
|
||||
"sourceRoot": "projects/ucap-webmessenger-native-electron/src",
|
||||
"prefix": "ucap-native-electron",
|
||||
"architect": {
|
||||
"build": {
|
||||
"builder": "@angular-devkit/build-ng-packagr:build",
|
||||
"options": {
|
||||
"tsConfig": "projects/ucap-webmessenger-native-electron/tsconfig.lib.json",
|
||||
"project": "projects/ucap-webmessenger-native-electron/ng-package.json"
|
||||
}
|
||||
},
|
||||
"test": {
|
||||
"builder": "@angular-devkit/build-angular:karma",
|
||||
"options": {
|
||||
"main": "projects/ucap-webmessenger-native-electron/src/test.ts",
|
||||
"tsConfig": "projects/ucap-webmessenger-native-electron/tsconfig.spec.json",
|
||||
"karmaConfig": "projects/ucap-webmessenger-native-electron/karma.conf.js"
|
||||
}
|
||||
},
|
||||
"lint": {
|
||||
"builder": "@angular-devkit/build-angular:tslint",
|
||||
"options": {
|
||||
"tsConfig": [
|
||||
"projects/ucap-webmessenger-native-electron/tsconfig.lib.json",
|
||||
"projects/ucap-webmessenger-native-electron/tsconfig.spec.json"
|
||||
],
|
||||
"exclude": ["**/node_modules/**"]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"ucap-webmessenger-web-socket": {
|
||||
"projectType": "library",
|
||||
"root": "projects/ucap-webmessenger-web-socket",
|
||||
|
@ -1413,6 +1445,72 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"ucap-webmessenger-native": {
|
||||
"projectType": "library",
|
||||
"root": "projects/ucap-webmessenger-native",
|
||||
"sourceRoot": "projects/ucap-webmessenger-native/src",
|
||||
"prefix": "ucap-native",
|
||||
"architect": {
|
||||
"build": {
|
||||
"builder": "@angular-devkit/build-ng-packagr:build",
|
||||
"options": {
|
||||
"tsConfig": "projects/ucap-webmessenger-native/tsconfig.lib.json",
|
||||
"project": "projects/ucap-webmessenger-native/ng-package.json"
|
||||
}
|
||||
},
|
||||
"test": {
|
||||
"builder": "@angular-devkit/build-angular:karma",
|
||||
"options": {
|
||||
"main": "projects/ucap-webmessenger-native/src/test.ts",
|
||||
"tsConfig": "projects/ucap-webmessenger-native/tsconfig.spec.json",
|
||||
"karmaConfig": "projects/ucap-webmessenger-native/karma.conf.js"
|
||||
}
|
||||
},
|
||||
"lint": {
|
||||
"builder": "@angular-devkit/build-angular:tslint",
|
||||
"options": {
|
||||
"tsConfig": [
|
||||
"projects/ucap-webmessenger-native/tsconfig.lib.json",
|
||||
"projects/ucap-webmessenger-native/tsconfig.spec.json"
|
||||
],
|
||||
"exclude": ["**/node_modules/**"]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"ucap-webmessenger-native-electron": {
|
||||
"projectType": "library",
|
||||
"root": "projects/ucap-webmessenger-native-electron",
|
||||
"sourceRoot": "projects/ucap-webmessenger-native-electron/src",
|
||||
"prefix": "ucap-native-electron",
|
||||
"architect": {
|
||||
"build": {
|
||||
"builder": "@angular-devkit/build-ng-packagr:build",
|
||||
"options": {
|
||||
"tsConfig": "projects/ucap-webmessenger-native-electron/tsconfig.lib.json",
|
||||
"project": "projects/ucap-webmessenger-native-electron/ng-package.json"
|
||||
}
|
||||
},
|
||||
"test": {
|
||||
"builder": "@angular-devkit/build-angular:karma",
|
||||
"options": {
|
||||
"main": "projects/ucap-webmessenger-native-electron/src/test.ts",
|
||||
"tsConfig": "projects/ucap-webmessenger-native-electron/tsconfig.spec.json",
|
||||
"karmaConfig": "projects/ucap-webmessenger-native-electron/karma.conf.js"
|
||||
}
|
||||
},
|
||||
"lint": {
|
||||
"builder": "@angular-devkit/build-angular:tslint",
|
||||
"options": {
|
||||
"tsConfig": [
|
||||
"projects/ucap-webmessenger-native-electron/tsconfig.lib.json",
|
||||
"projects/ucap-webmessenger-native-electron/tsconfig.spec.json"
|
||||
],
|
||||
"exclude": ["**/node_modules/**"]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"ucap-webmessenger-native-browser": {
|
||||
"projectType": "library",
|
||||
"root": "projects/ucap-webmessenger-native-browser",
|
||||
|
@ -1445,76 +1543,6 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"ucap-webmessenger-electron-notification": {
|
||||
"projectType": "library",
|
||||
"root": "projects/ucap-webmessenger-electron-notification",
|
||||
"sourceRoot": "projects/ucap-webmessenger-electron-notification/src",
|
||||
"prefix": "ucap-electron-notification",
|
||||
"architect": {
|
||||
"build": {
|
||||
"builder": "@angular-devkit/build-ng-packagr:build",
|
||||
"options": {
|
||||
"tsConfig": "projects/ucap-webmessenger-electron-notification/tsconfig.lib.json",
|
||||
"project": "projects/ucap-webmessenger-electron-notification/ng-package.json"
|
||||
}
|
||||
},
|
||||
"test": {
|
||||
"builder": "@angular-devkit/build-angular:karma",
|
||||
"options": {
|
||||
"main": "projects/ucap-webmessenger-electron-notification/src/test.ts",
|
||||
"tsConfig": "projects/ucap-webmessenger-electron-notification/tsconfig.spec.json",
|
||||
"karmaConfig": "projects/ucap-webmessenger-electron-notification/karma.conf.js"
|
||||
}
|
||||
},
|
||||
"lint": {
|
||||
"builder": "@angular-devkit/build-angular:tslint",
|
||||
"options": {
|
||||
"tsConfig": [
|
||||
"projects/ucap-webmessenger-electron-notification/tsconfig.lib.json",
|
||||
"projects/ucap-webmessenger-electron-notification/tsconfig.spec.json"
|
||||
],
|
||||
"exclude": [
|
||||
"**/node_modules/**"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"ucap-webmessenger-electron-core": {
|
||||
"projectType": "library",
|
||||
"root": "projects/ucap-webmessenger-electron-core",
|
||||
"sourceRoot": "projects/ucap-webmessenger-electron-core/src",
|
||||
"prefix": "ucap-electron-core",
|
||||
"architect": {
|
||||
"build": {
|
||||
"builder": "@angular-devkit/build-ng-packagr:build",
|
||||
"options": {
|
||||
"tsConfig": "projects/ucap-webmessenger-electron-core/tsconfig.lib.json",
|
||||
"project": "projects/ucap-webmessenger-electron-core/ng-package.json"
|
||||
}
|
||||
},
|
||||
"test": {
|
||||
"builder": "@angular-devkit/build-angular:karma",
|
||||
"options": {
|
||||
"main": "projects/ucap-webmessenger-electron-core/src/test.ts",
|
||||
"tsConfig": "projects/ucap-webmessenger-electron-core/tsconfig.spec.json",
|
||||
"karmaConfig": "projects/ucap-webmessenger-electron-core/karma.conf.js"
|
||||
}
|
||||
},
|
||||
"lint": {
|
||||
"builder": "@angular-devkit/build-angular:tslint",
|
||||
"options": {
|
||||
"tsConfig": [
|
||||
"projects/ucap-webmessenger-electron-core/tsconfig.lib.json",
|
||||
"projects/ucap-webmessenger-electron-core/tsconfig.spec.json"
|
||||
],
|
||||
"exclude": [
|
||||
"**/node_modules/**"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"defaultProject": "ucap-webmessenger-app"
|
||||
|
|
|
@ -2,8 +2,18 @@ const path = require('path');
|
|||
|
||||
module.exports = (config, options) => {
|
||||
const PRODUCTION = process.env.NODE_ENV === 'production';
|
||||
const BROWSER = process.env.UCAP_ENV_RUNTIME === 'BROWSER';
|
||||
|
||||
config.target = 'electron-renderer';
|
||||
console.log('BROWSER', BROWSER, config.target);
|
||||
|
||||
if (!BROWSER) {
|
||||
config.target = 'electron-renderer';
|
||||
} else {
|
||||
config.target = 'web';
|
||||
config.node = {
|
||||
fs: 'empty'
|
||||
};
|
||||
}
|
||||
|
||||
config.resolve.alias = {
|
||||
...config.resolve.alias,
|
|
@ -1,4 +1,3 @@
|
|||
import * as fs from 'fs';
|
||||
import * as Path from 'path';
|
||||
|
||||
const projectRoot = Path.dirname(__dirname);
|
||||
|
|
|
@ -12,10 +12,16 @@ export const externals = [nodeExternals()];
|
|||
// externals.push('devtron');
|
||||
// }
|
||||
|
||||
const outputDir = 'dist/main';
|
||||
const outputDir = 'dist/ucap-webmessenger-electron';
|
||||
|
||||
const mainConfig: webpack.Configuration = {
|
||||
entry: { main: path.resolve(__dirname, '..', 'main/src/index') },
|
||||
entry: {
|
||||
main: path.resolve(
|
||||
__dirname,
|
||||
'..',
|
||||
'electron-projects/ucap-webmessenger-electron/src/index'
|
||||
)
|
||||
},
|
||||
target: 'electron-main',
|
||||
mode: enviroments.__DEV__ ? 'development' : 'production',
|
||||
devtool: 'source-map',
|
||||
|
@ -32,7 +38,12 @@ const mainConfig: webpack.Configuration = {
|
|||
{
|
||||
test: /\.tsx?$/,
|
||||
include: [
|
||||
path.resolve(__dirname, '..', 'main/src'),
|
||||
path.resolve(
|
||||
__dirname,
|
||||
'..',
|
||||
'electron-projects/ucap-webmessenger-electron/src'
|
||||
),
|
||||
path.resolve(__dirname, '..', 'electron-projects'),
|
||||
path.resolve(__dirname, '..', 'projects')
|
||||
],
|
||||
use: [
|
||||
|
@ -43,7 +54,7 @@ const mainConfig: webpack.Configuration = {
|
|||
configFileName: path.resolve(
|
||||
__dirname,
|
||||
'..',
|
||||
'main/tsconfig.main.json'
|
||||
'electron-projects/ucap-webmessenger-electron/tsconfig.electron.json'
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -71,8 +82,9 @@ const mainConfig: webpack.Configuration = {
|
|||
),
|
||||
new CopyWebpackPlugin([
|
||||
{
|
||||
from: 'main/resources/**/*',
|
||||
to: path.resolve(__dirname, '..', 'dist')
|
||||
from: 'ucap-webmessenger-electron/resources/**/*',
|
||||
to: path.resolve(__dirname, '..', 'dist'),
|
||||
context: 'electron-projects'
|
||||
}
|
||||
])
|
||||
],
|
||||
|
@ -82,12 +94,12 @@ const mainConfig: webpack.Configuration = {
|
|||
'@ucap-webmessenger/electron-core': path.resolve(
|
||||
__dirname,
|
||||
'..',
|
||||
'projects/ucap-webmessenger-electron-core/src/public-api'
|
||||
'electron-projects/ucap-webmessenger-electron-core/src/public-api'
|
||||
),
|
||||
'@ucap-webmessenger/electron-notification': path.resolve(
|
||||
__dirname,
|
||||
'..',
|
||||
'projects/ucap-webmessenger-electron-notification/src/public-api'
|
||||
'electron-projects/ucap-webmessenger-electron-notification/src/public-api'
|
||||
),
|
||||
'@ucap-webmessenger/native': path.resolve(
|
||||
__dirname,
|
||||
|
@ -98,6 +110,11 @@ const mainConfig: webpack.Configuration = {
|
|||
__dirname,
|
||||
'..',
|
||||
'projects/ucap-webmessenger-native-electron/src/public-api'
|
||||
),
|
||||
'@ucap-webmessenger/electron': path.resolve(
|
||||
__dirname,
|
||||
'..',
|
||||
'electron-projects/ucap-webmessenger-electron/src/public-api'
|
||||
)
|
||||
},
|
||||
modules: [path.resolve(__dirname, '..', 'node_modules/')]
|
||||
|
|
|
@ -1,22 +1,24 @@
|
|||
// Karma configuration file, see link for more information
|
||||
// https://karma-runner.github.io/1.0/config/configuration-file.html
|
||||
|
||||
module.exports = function (config) {
|
||||
module.exports = function(config) {
|
||||
config.set({
|
||||
basePath: '',
|
||||
frameworks: ['jasmine', '@angular-devkit/build-angular'],
|
||||
frameworks: ['jasmine'],
|
||||
plugins: [
|
||||
require('karma-jasmine'),
|
||||
require('karma-chrome-launcher'),
|
||||
require('karma-jasmine-html-reporter'),
|
||||
require('karma-coverage-istanbul-reporter'),
|
||||
require('@angular-devkit/build-angular/plugins/karma')
|
||||
require('karma-coverage-istanbul-reporter')
|
||||
],
|
||||
client: {
|
||||
clearContext: false // leave Jasmine Spec Runner output visible in browser
|
||||
},
|
||||
coverageIstanbulReporter: {
|
||||
dir: require('path').join(__dirname, '../../coverage/ucap-webmessenger-electron-core'),
|
||||
dir: require('path').join(
|
||||
__dirname,
|
||||
'../../coverage/ucap-webmessenger-electron-core'
|
||||
),
|
||||
reports: ['html', 'lcovonly', 'text-summary'],
|
||||
fixWebpackSourcePaths: true
|
||||
},
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"name": "@ucap-webmessenger/electron-core",
|
||||
"version": "0.0.1",
|
||||
"peerDependencies": {}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
{
|
||||
"extends": "../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "../../out-tsc/lib",
|
||||
"target": "es2015",
|
||||
"declaration": true,
|
||||
"inlineSources": true,
|
||||
"types": [],
|
||||
"lib": ["dom", "es2018"]
|
||||
},
|
||||
|
||||
"exclude": ["src/test.ts", "**/*.spec.ts"]
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"extends": "../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "../../out-tsc/spec",
|
||||
"types": ["jasmine", "node"]
|
||||
},
|
||||
"files": ["src/test.ts"],
|
||||
"include": ["**/*.spec.ts", "**/*.d.ts"]
|
||||
}
|
|
@ -1,22 +1,24 @@
|
|||
// Karma configuration file, see link for more information
|
||||
// https://karma-runner.github.io/1.0/config/configuration-file.html
|
||||
|
||||
module.exports = function (config) {
|
||||
module.exports = function(config) {
|
||||
config.set({
|
||||
basePath: '',
|
||||
frameworks: ['jasmine', '@angular-devkit/build-angular'],
|
||||
frameworks: ['jasmine'],
|
||||
plugins: [
|
||||
require('karma-jasmine'),
|
||||
require('karma-chrome-launcher'),
|
||||
require('karma-jasmine-html-reporter'),
|
||||
require('karma-coverage-istanbul-reporter'),
|
||||
require('@angular-devkit/build-angular/plugins/karma')
|
||||
require('karma-coverage-istanbul-reporter')
|
||||
],
|
||||
client: {
|
||||
clearContext: false // leave Jasmine Spec Runner output visible in browser
|
||||
},
|
||||
coverageIstanbulReporter: {
|
||||
dir: require('path').join(__dirname, '../../coverage/ucap-webmessenger-electron-notification'),
|
||||
dir: require('path').join(
|
||||
__dirname,
|
||||
'../../coverage/ucap-webmessenger-electron-notification'
|
||||
),
|
||||
reports: ['html', 'lcovonly', 'text-summary'],
|
||||
fixWebpackSourcePaths: true
|
||||
},
|
|
@ -1,5 +1,6 @@
|
|||
import * as path from 'path';
|
||||
import * as url from 'url';
|
||||
import * as fse from 'fs-extra';
|
||||
|
||||
import { AnimationQueue } from '../utils/animation-queue';
|
||||
import {
|
||||
|
@ -211,19 +212,13 @@ export class ElectronNotificationService {
|
|||
|
||||
private updateTemplatePath() {
|
||||
try {
|
||||
import('fs')
|
||||
.then(fs => {
|
||||
fs.statSync(this.customOptions.templatePath).isFile();
|
||||
fse.statSync(this.customOptions.templatePath).isFile();
|
||||
|
||||
this.templateUrl = url.format({
|
||||
pathname: this.customOptions.templatePath,
|
||||
protocol: 'file:',
|
||||
slashes: true
|
||||
});
|
||||
})
|
||||
.catch(reason => {
|
||||
throw reason;
|
||||
});
|
||||
this.templateUrl = url.format({
|
||||
pathname: this.customOptions.templatePath,
|
||||
protocol: 'file:',
|
||||
slashes: true
|
||||
});
|
||||
} catch (e) {
|
||||
console.log(
|
||||
'electron-notify: Could not find template ("' +
|
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"extends": "../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "../../out-tsc/lib",
|
||||
"target": "es2015",
|
||||
"declaration": true,
|
||||
"inlineSources": true,
|
||||
"types": [],
|
||||
"lib": ["dom", "es2018"]
|
||||
},
|
||||
"exclude": ["src/test.ts", "**/*.spec.ts"]
|
||||
}
|
24
electron-projects/ucap-webmessenger-electron/README.md
Normal file
|
@ -0,0 +1,24 @@
|
|||
# UcapWebmessengerElectron
|
||||
|
||||
This library was generated with [Angular CLI](https://github.com/angular/angular-cli) version 8.2.11.
|
||||
|
||||
## Code scaffolding
|
||||
|
||||
Run `ng generate component component-name --project ucap-webmessenger-electron` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module --project ucap-webmessenger-electron`.
|
||||
> Note: Don't forget to add `--project ucap-webmessenger-electron` or else it will be added to the default project in your `angular.json` file.
|
||||
|
||||
## Build
|
||||
|
||||
Run `ng build ucap-webmessenger-electron` to build the project. The build artifacts will be stored in the `dist/` directory.
|
||||
|
||||
## Publishing
|
||||
|
||||
After building your library with `ng build ucap-webmessenger-electron`, go to the dist folder `cd dist/ucap-webmessenger-electron` and run `npm publish`.
|
||||
|
||||
## Running unit tests
|
||||
|
||||
Run `ng test ucap-webmessenger-electron` to execute the unit tests via [Karma](https://karma-runner.github.io).
|
||||
|
||||
## 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).
|
34
electron-projects/ucap-webmessenger-electron/karma.conf.js
Normal file
|
@ -0,0 +1,34 @@
|
|||
// Karma configuration file, see link for more information
|
||||
// https://karma-runner.github.io/1.0/config/configuration-file.html
|
||||
|
||||
module.exports = function(config) {
|
||||
config.set({
|
||||
basePath: '',
|
||||
frameworks: ['jasmine'],
|
||||
plugins: [
|
||||
require('karma-jasmine'),
|
||||
require('karma-chrome-launcher'),
|
||||
require('karma-jasmine-html-reporter'),
|
||||
require('karma-coverage-istanbul-reporter')
|
||||
],
|
||||
client: {
|
||||
clearContext: false // leave Jasmine Spec Runner output visible in browser
|
||||
},
|
||||
coverageIstanbulReporter: {
|
||||
dir: require('path').join(
|
||||
__dirname,
|
||||
'../../coverage/ucap-webmessenger-electron'
|
||||
),
|
||||
reports: ['html', 'lcovonly', 'text-summary'],
|
||||
fixWebpackSourcePaths: true
|
||||
},
|
||||
reporters: ['progress', 'kjhtml'],
|
||||
port: 9876,
|
||||
colors: true,
|
||||
logLevel: config.LOG_INFO,
|
||||
autoWatch: true,
|
||||
browsers: ['Chrome'],
|
||||
singleRun: false,
|
||||
restartOnFileChange: true
|
||||
});
|
||||
};
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"name": "@ucap-webmessenger/electron",
|
||||
"version": "0.0.1",
|
||||
"peerDependencies": {}
|
||||
}
|
After Width: | Height: | Size: 3.8 KiB |
After Width: | Height: | Size: 504 B |
After Width: | Height: | Size: 7.2 KiB |
After Width: | Height: | Size: 897 B |
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 1.9 KiB |
After Width: | Height: | Size: 3.1 KiB |
After Width: | Height: | Size: 117 KiB |
After Width: | Height: | Size: 3.1 KiB |
After Width: | Height: | Size: 105 KiB |
After Width: | Height: | Size: 1.9 KiB |
After Width: | Height: | Size: 31 KiB |
After Width: | Height: | Size: 20 KiB |
After Width: | Height: | Size: 18 KiB |
After Width: | Height: | Size: 18 KiB |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 842 B |
After Width: | Height: | Size: 643 B |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 226 B |
After Width: | Height: | Size: 3.5 KiB |
After Width: | Height: | Size: 5.1 KiB |
After Width: | Height: | Size: 2.3 KiB |
|
@ -0,0 +1,143 @@
|
|||
'use strict';
|
||||
|
||||
const electron = require('electron');
|
||||
const ipc = electron.ipcRenderer;
|
||||
const winId = electron.remote.getCurrentWindow().id;
|
||||
|
||||
function setStyle(config) {
|
||||
// Style it
|
||||
let notiDoc = global.window.document;
|
||||
let container = notiDoc.getElementById('container');
|
||||
let appIcon = notiDoc.getElementById('appIcon');
|
||||
let image = notiDoc.getElementById('image');
|
||||
let close = notiDoc.getElementById('close');
|
||||
let message = notiDoc.getElementById('message');
|
||||
// Default style
|
||||
setStyleOnDomElement(config.defaultStyleContainer, container);
|
||||
// Size and radius
|
||||
let style = {
|
||||
height:
|
||||
config.height -
|
||||
2 * config.borderRadius -
|
||||
2 * config.defaultStyleContainer.padding,
|
||||
width:
|
||||
config.width -
|
||||
2 * config.borderRadius -
|
||||
2 * config.defaultStyleContainer.padding,
|
||||
borderRadius: config.borderRadius + 'px'
|
||||
};
|
||||
setStyleOnDomElement(style, container);
|
||||
// Style appIcon or hide
|
||||
if (config.appIcon) {
|
||||
setStyleOnDomElement(config.defaultStyleAppIcon, appIcon);
|
||||
appIcon.src = config.appIcon;
|
||||
} else {
|
||||
setStyleOnDomElement(
|
||||
{
|
||||
display: 'none'
|
||||
},
|
||||
appIcon
|
||||
);
|
||||
}
|
||||
// Style image
|
||||
setStyleOnDomElement(config.defaultStyleImage, image);
|
||||
// Style close button
|
||||
setStyleOnDomElement(config.defaultStyleClose, close);
|
||||
// Remove margin from text p
|
||||
setStyleOnDomElement(config.defaultStyleText, message);
|
||||
}
|
||||
|
||||
function setContents(event, notificationObj) {
|
||||
// sound
|
||||
if (notificationObj.sound) {
|
||||
// Check if file is accessible
|
||||
try {
|
||||
// If it's a local file, check it's existence
|
||||
// Won't check remote files e.g. http://
|
||||
if (
|
||||
notificationObj.sound.match(/^file\:/) !== null ||
|
||||
notificationObj.sound.match(/^\//) !== null
|
||||
) {
|
||||
let audio = new global.window.Audio(notificationObj.sound);
|
||||
audio.play();
|
||||
}
|
||||
} catch (e) {
|
||||
log(
|
||||
'electron-notify: ERROR could not find sound file: ' +
|
||||
notificationObj.sound.replace('file://', ''),
|
||||
e,
|
||||
e.stack
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
let notiDoc = global.window.document;
|
||||
// Title
|
||||
let titleDoc = notiDoc.getElementById('title');
|
||||
titleDoc.innerHTML = notificationObj.title || '';
|
||||
// message
|
||||
let messageDoc = notiDoc.getElementById('message');
|
||||
messageDoc.innerHTML = notificationObj.text || '';
|
||||
// Image
|
||||
let imageDoc = notiDoc.getElementById('image');
|
||||
if (notificationObj.image) {
|
||||
imageDoc.src = notificationObj.image;
|
||||
} else {
|
||||
setStyleOnDomElement({ display: 'none' }, imageDoc);
|
||||
}
|
||||
|
||||
// Close button
|
||||
let closeButton = notiDoc.getElementById('close');
|
||||
closeButton.addEventListener('click', function(event) {
|
||||
event.stopPropagation();
|
||||
ipc.send('UCAP::ElectronNotification::close', winId, notificationObj);
|
||||
});
|
||||
|
||||
// URL
|
||||
let container = notiDoc.getElementById('container');
|
||||
container.addEventListener('click', function() {
|
||||
ipc.send('UCAP::ElectronNotification::click', winId, notificationObj);
|
||||
});
|
||||
}
|
||||
|
||||
function setStyleOnDomElement(styleObj, domElement) {
|
||||
try {
|
||||
for (let styleAttr in styleObj) {
|
||||
domElement.style[styleAttr] = styleObj[styleAttr];
|
||||
}
|
||||
} catch (e) {
|
||||
throw new Error(
|
||||
'electron-notify: Could not set style on domElement',
|
||||
styleObj,
|
||||
domElement
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function loadConfig(event, conf) {
|
||||
setStyle(conf || {});
|
||||
}
|
||||
|
||||
function reset() {
|
||||
let notiDoc = global.window.document;
|
||||
let container = notiDoc.getElementById('container');
|
||||
let closeButton = notiDoc.getElementById('close');
|
||||
|
||||
// Remove event listener
|
||||
let newContainer = container.cloneNode(true);
|
||||
container.parentNode.replaceChild(newContainer, container);
|
||||
let newCloseButton = closeButton.cloneNode(true);
|
||||
closeButton.parentNode.replaceChild(newCloseButton, closeButton);
|
||||
}
|
||||
|
||||
ipc.on('UCAP::ElectronNotification::BrowserWindowSetContents', setContents);
|
||||
ipc.on('UCAP::ElectronNotification::loadConfig', loadConfig);
|
||||
ipc.on('UCAP::ElectronNotification::reset', reset);
|
||||
|
||||
function log() {
|
||||
console.log.apply(console, arguments);
|
||||
}
|
||||
|
||||
delete global.require;
|
||||
delete global.exports;
|
||||
delete global.module;
|
|
@ -0,0 +1,130 @@
|
|||
html {
|
||||
height: 100%;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
body {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
color: #333;
|
||||
font-family: '나눔고딕', Malgun Gothic, '맑은고딕', Arial, Dotum, '돋움',
|
||||
Gulim, '굴림';
|
||||
font-size: 12px;
|
||||
line-height: 18px !important;
|
||||
-webkit-box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
body * {
|
||||
-webkit-box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
ul,
|
||||
ol {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
-webkit-box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
img {
|
||||
border: none;
|
||||
}
|
||||
a:link,
|
||||
a:visited,
|
||||
a:hover,
|
||||
a:active {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.noti_messege {
|
||||
width: 340px;
|
||||
height: 100px;
|
||||
border: 1px solid #666;
|
||||
background-color: #fff;
|
||||
box-shadow: 0px 0px 3px 0px #e7e7e7;
|
||||
}
|
||||
.info {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
box-sizing: border-box;
|
||||
padding: 16px 14px;
|
||||
color: #fff;
|
||||
}
|
||||
.btn_close {
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
right: 6px;
|
||||
top: 6px;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
background: url(../image/btn_close_gray.png) no-repeat 50% 50%;
|
||||
}
|
||||
.btn_close:hover {
|
||||
opacity: 0.7;
|
||||
}
|
||||
.photo {
|
||||
position: relative;
|
||||
top: 0px;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
margin: 4px 0;
|
||||
width: 54px;
|
||||
height: 54px;
|
||||
border-radius: 50%;
|
||||
background: #5bc1ff url(../image/img_nophoto_50.png) no-repeat 50% 50%;
|
||||
border: 2px solid #ddd;
|
||||
}
|
||||
.info .profile {
|
||||
position: absolute;
|
||||
width: 60px;
|
||||
text-align: center;
|
||||
}
|
||||
.photo img {
|
||||
overflow: hidden;
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
border-radius: 50px;
|
||||
}
|
||||
.noti_messege .info .profile + div {
|
||||
padding-left: 70px;
|
||||
position: relative;
|
||||
line-height: 180%;
|
||||
height: 100%;
|
||||
}
|
||||
.sender {
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
margin-bottom: 4px;
|
||||
color: #333;
|
||||
width: 94%;
|
||||
}
|
||||
.sender .name {
|
||||
color: #2e7fb5;
|
||||
}
|
||||
.message {
|
||||
color: #666;
|
||||
}
|
||||
.ellipsis {
|
||||
display: block;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
word-wrap: normal;
|
||||
overflow: hidden;
|
||||
}
|
||||
.ellipsis_row2 {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 2;
|
||||
-webkit-box-orient: vertical;
|
||||
word-wrap: break-word;
|
||||
line-height: 1.6em;
|
||||
height: 3.2em;
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
||||
<HTML>
|
||||
<HEAD>
|
||||
<title>[개발]M Messenger - 메시지 알림</title>
|
||||
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<meta charset="UTF-8" />
|
||||
<link
|
||||
type="text/css"
|
||||
rel="stylesheet"
|
||||
href="styles/noti_messege.css"
|
||||
/>
|
||||
</HEAD>
|
||||
<style>
|
||||
html,
|
||||
body {
|
||||
overflow-y: hidden;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
</style>
|
||||
<BODY>
|
||||
<div class="noti_messege" id="container">
|
||||
<div class="info">
|
||||
<a class="btn_close" id="close"></a>
|
||||
<div class="profile">
|
||||
<div class="photo">
|
||||
<img src="" id="appIcon" />
|
||||
<img
|
||||
src=""
|
||||
id="image"
|
||||
onerror="this.src='image/img_nophoto_50.png';"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<ul id="text">
|
||||
<li class="sender ellipsis" id="title">
|
||||
<span class="name">김 수안무 거북이와 두루미</span>님이 메시지를
|
||||
보냈습니다.
|
||||
</li>
|
||||
<li class="message ellipsis_row2" id="message">
|
||||
홍길동 대리(솔루션사업팀)홍길동 대리(솔루션사업팀)홍길동
|
||||
대리(솔루션사업팀)홍길동 대리(솔루션사업팀)
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</BODY>
|
||||
</HTML>
|
|
@ -0,0 +1,229 @@
|
|||
import * as path from 'path';
|
||||
import * as url from 'url';
|
||||
|
||||
import { app, BrowserWindow, screen, ipcMain, IpcMainEvent } from 'electron';
|
||||
import windowStateKeeper from 'electron-window-state';
|
||||
import { EventEmitter } from 'events';
|
||||
|
||||
import { now } from '../util/now';
|
||||
import { registerWindowStateChangedEvents } from '../lib/window-state';
|
||||
import {
|
||||
ElectronAppChannel,
|
||||
ElectronBrowserWindowChannel,
|
||||
ElectronWebContentsChannel
|
||||
} from '@ucap-webmessenger/electron-core';
|
||||
|
||||
export class AppWindow {
|
||||
private window: BrowserWindow | null = null;
|
||||
|
||||
private eventEmitter = new EventEmitter();
|
||||
|
||||
// tslint:disable-next-line: variable-name
|
||||
private _loadTime: number | null = null;
|
||||
// tslint:disable-next-line: variable-name
|
||||
private _rendererReadyTime: number | null = null;
|
||||
|
||||
private minWidth = 960;
|
||||
private minHeight = 660;
|
||||
|
||||
public constructor() {
|
||||
const savedWindowState = windowStateKeeper({
|
||||
defaultWidth: this.minWidth,
|
||||
defaultHeight: this.minHeight
|
||||
});
|
||||
|
||||
const windowOptions: Electron.BrowserWindowConstructorOptions = {
|
||||
x: savedWindowState.x,
|
||||
y: savedWindowState.y,
|
||||
width: savedWindowState.width,
|
||||
height: savedWindowState.height,
|
||||
minWidth: this.minWidth,
|
||||
minHeight: this.minHeight,
|
||||
center: true,
|
||||
// This fixes subpixel aliasing on Windows
|
||||
// See https://github.com/atom/atom/commit/683bef5b9d133cb194b476938c77cc07fd05b972
|
||||
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,
|
||||
icon: path.join(__dirname, 'resources/image', 'ico_64_64.png')
|
||||
};
|
||||
|
||||
if (__DARWIN__) {
|
||||
windowOptions.titleBarStyle = 'hidden';
|
||||
} else if (__WIN32__) {
|
||||
windowOptions.frame = false;
|
||||
} else if (__LINUX__) {
|
||||
windowOptions.icon = path.join(__dirname, 'static', 'icon-logo.png');
|
||||
}
|
||||
|
||||
this.window = new BrowserWindow(windowOptions);
|
||||
savedWindowState.manage(this.window);
|
||||
|
||||
let quitting = false;
|
||||
app.on(ElectronAppChannel.BeforeQuit, () => {
|
||||
quitting = true;
|
||||
});
|
||||
|
||||
ipcMain.on(ElectronAppChannel.WillQuit, (event: IpcMainEvent) => {
|
||||
quitting = true;
|
||||
event.returnValue = true;
|
||||
});
|
||||
|
||||
// on macOS, when the user closes the window we really just hide it. This
|
||||
// lets us activate quickly and keep all our interesting logic in the
|
||||
// renderer.
|
||||
if (__DARWIN__) {
|
||||
this.window.on(ElectronBrowserWindowChannel.Close, e => {
|
||||
if (!quitting) {
|
||||
e.preventDefault();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (__WIN32__) {
|
||||
// workaround for known issue with fullscreen-ing the app and restoring
|
||||
// is that some Chromium API reports the incorrect bounds, so that it
|
||||
// will leave a small space at the top of the screen on every other
|
||||
// maximize
|
||||
//
|
||||
// adapted from https://github.com/electron/electron/issues/12971#issuecomment-403956396
|
||||
//
|
||||
// can be tidied up once https://github.com/electron/electron/issues/12971
|
||||
// has been confirmed as resolved
|
||||
this.window.once(ElectronBrowserWindowChannel.ReadyToShow, () => {
|
||||
this.window.on(ElectronBrowserWindowChannel.Unmaximize, () => {
|
||||
setTimeout(() => {
|
||||
const bounds = this.window.getBounds();
|
||||
bounds.width += 1;
|
||||
this.window.setBounds(bounds);
|
||||
bounds.width -= 1;
|
||||
this.window.setBounds(bounds);
|
||||
}, 5);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public load(): void {
|
||||
let startLoad = 0;
|
||||
|
||||
this.window.webContents.once(
|
||||
ElectronWebContentsChannel.DidStartLoading,
|
||||
() => {
|
||||
this._rendererReadyTime = null;
|
||||
this._loadTime = null;
|
||||
|
||||
startLoad = now();
|
||||
}
|
||||
);
|
||||
|
||||
this.window.webContents.once(
|
||||
ElectronWebContentsChannel.DidFinishLoad,
|
||||
() => {
|
||||
this.window.webContents.setVisualZoomLevelLimits(1, 1);
|
||||
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
this.window.webContents.openDevTools();
|
||||
}
|
||||
|
||||
this._loadTime = now() - startLoad;
|
||||
}
|
||||
);
|
||||
|
||||
this.window.webContents.on(ElectronWebContentsChannel.DidFailLoad, () => {
|
||||
this.window.webContents.openDevTools();
|
||||
this.window.show();
|
||||
});
|
||||
|
||||
registerWindowStateChangedEvents(this.window);
|
||||
|
||||
if (__DEV__) {
|
||||
this.window.loadURL('http://localhost:4200');
|
||||
} else {
|
||||
this.window.loadURL(
|
||||
url.format({
|
||||
pathname: path.join(
|
||||
__dirname,
|
||||
'..',
|
||||
'ucap-webmessenger-app/index.html'
|
||||
),
|
||||
protocol: 'file:',
|
||||
slashes: true
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/** Is the page loaded and has the renderer signalled it's ready? */
|
||||
private get rendererLoaded(): boolean {
|
||||
return !!this.loadTime && !!this.rendererReadyTime;
|
||||
}
|
||||
|
||||
public onClose(fn: () => void) {
|
||||
this.window.on(ElectronBrowserWindowChannel.Closed, fn);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a function to call when the window is done loading. At that point
|
||||
* the page has loaded and the renderer has signalled that it is ready.
|
||||
*/
|
||||
public onDidLoad(fn: () => void): EventEmitter {
|
||||
return this.eventEmitter.on('did-load', fn);
|
||||
}
|
||||
|
||||
public isMinimized() {
|
||||
return this.window.isMinimized();
|
||||
}
|
||||
|
||||
/** Is the window currently visible? */
|
||||
public isVisible() {
|
||||
return this.window.isVisible();
|
||||
}
|
||||
|
||||
public restore() {
|
||||
this.window.restore();
|
||||
}
|
||||
|
||||
public focus() {
|
||||
this.window.focus();
|
||||
}
|
||||
|
||||
/** Show the window. */
|
||||
public show() {
|
||||
this.window.show();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the time (in milliseconds) spent loading the page.
|
||||
*
|
||||
* This will be `null` until `onDidLoad` is called.
|
||||
*/
|
||||
public get loadTime(): number | null {
|
||||
return this._loadTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the time (in milliseconds) elapsed from the renderer being loaded to it
|
||||
* signaling it was ready.
|
||||
*
|
||||
* This will be `null` until `onDidLoad` is called.
|
||||
*/
|
||||
public get rendererReadyTime(): number | null {
|
||||
return this._rendererReadyTime;
|
||||
}
|
||||
|
||||
public destroy() {
|
||||
this.window.destroy();
|
||||
}
|
||||
|
||||
public get browserWindow(): BrowserWindow | null {
|
||||
return this.window;
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
export function showUncaughtException(isLaunchError: boolean, error: Error) {}
|
18
electron-projects/ucap-webmessenger-electron/src/global.d.ts
vendored
Normal file
|
@ -0,0 +1,18 @@
|
|||
/* eslint-disable @typescript-eslint/interface-name-prefix */
|
||||
/** Is the app running in dev mode? */
|
||||
declare const __DEV__: boolean;
|
||||
|
||||
/** Is the app being built to run on Darwin? */
|
||||
declare const __DARWIN__: boolean;
|
||||
|
||||
/** Is the app being built to run on Win32? */
|
||||
declare const __WIN32__: boolean;
|
||||
|
||||
/** Is the app being built to run on Linux? */
|
||||
declare const __LINUX__: boolean;
|
||||
|
||||
/**
|
||||
* The currently executing process kind, this is specific to desktop
|
||||
* and identifies the processes that we have.
|
||||
*/
|
||||
declare const __PROCESS_KIND__: 'main' | 'ui';
|
304
electron-projects/ucap-webmessenger-electron/src/index.ts
Normal file
|
@ -0,0 +1,304 @@
|
|||
import { app, ipcMain, IpcMainEvent, remote } from 'electron';
|
||||
import * as path from 'path';
|
||||
import * as url from 'url';
|
||||
import * as fse from 'fs-extra';
|
||||
import * as fs from 'fs';
|
||||
|
||||
import { AppWindow } from './app/AppWindow';
|
||||
import { now } from './util/now';
|
||||
import { showUncaughtException } from './crash/show-uncaught-exception';
|
||||
|
||||
import {
|
||||
UpdaterChannel,
|
||||
FileChannel,
|
||||
IdleStateChannel,
|
||||
NotificationChannel
|
||||
} from '@ucap-webmessenger/native-electron';
|
||||
import { ElectronNotificationService } from '@ucap-webmessenger/electron-notification';
|
||||
|
||||
import { root } from './util/root';
|
||||
import { DefaultFolder } from './lib/default-folder';
|
||||
import { FileUtil } from './lib/file-util';
|
||||
|
||||
import { IdleChecker } from './lib/idle-checker';
|
||||
import { NotificationRequest } from '@ucap-webmessenger/native';
|
||||
import { ElectronAppChannel } from '@ucap-webmessenger/electron-core';
|
||||
|
||||
let appWindow: AppWindow | null = null;
|
||||
|
||||
const launchTime = now();
|
||||
let readyTime: number | null = null;
|
||||
|
||||
type OnDidLoadFn = (window: AppWindow) => void;
|
||||
let onDidLoadFns: Array<OnDidLoadFn> | null = [];
|
||||
|
||||
let preventQuit = false;
|
||||
|
||||
let notificationService: ElectronNotificationService | null;
|
||||
|
||||
function handleUncaughtException(error: Error) {
|
||||
preventQuit = true;
|
||||
|
||||
// If we haven't got a window we'll assume it's because
|
||||
// we've just launched and haven't created it yet.
|
||||
// It could also be because we're encountering an unhandled
|
||||
// exception on shutdown but that's less likely and since
|
||||
// this only affects the presentation of the crash dialog
|
||||
// it's a safe assumption to make.
|
||||
const isLaunchError = appWindow === null;
|
||||
|
||||
if (appWindow) {
|
||||
appWindow.destroy();
|
||||
appWindow = null;
|
||||
}
|
||||
|
||||
showUncaughtException(isLaunchError, error);
|
||||
}
|
||||
|
||||
function getUptimeInSeconds() {
|
||||
return (now() - launchTime) / 1000;
|
||||
}
|
||||
|
||||
process.on('uncaughtException', (error: Error) => {
|
||||
// error = withSourceMappedStack(error);
|
||||
// reportError(error, getExtraErrorContext());
|
||||
handleUncaughtException(error);
|
||||
});
|
||||
|
||||
let isDuplicateInstance = false;
|
||||
const gotSingleInstanceLock = app.requestSingleInstanceLock();
|
||||
isDuplicateInstance = !gotSingleInstanceLock;
|
||||
let idle: IdleChecker | null;
|
||||
|
||||
app.on(ElectronAppChannel.SecondInstance, (event, args, workingDirectory) => {
|
||||
// Someone tried to run a second instance, we should focus our window.
|
||||
if (appWindow) {
|
||||
if (appWindow.isMinimized()) {
|
||||
appWindow.restore();
|
||||
}
|
||||
|
||||
if (!appWindow.isVisible()) {
|
||||
appWindow.show();
|
||||
}
|
||||
|
||||
appWindow.focus();
|
||||
}
|
||||
});
|
||||
|
||||
if (isDuplicateInstance) {
|
||||
app.quit();
|
||||
}
|
||||
|
||||
function createWindow() {
|
||||
const window = new AppWindow();
|
||||
|
||||
if (__DEV__) {
|
||||
// const {
|
||||
// default: installExtension,
|
||||
// REDUX_DEVTOOLS
|
||||
// } = require('electron-devtools-installer');
|
||||
|
||||
import('electron-debug').then(ed => {
|
||||
ed.default({ showDevTools: true });
|
||||
});
|
||||
|
||||
import('electron-devtools-installer').then(edi => {
|
||||
const ChromeLens = {
|
||||
id: 'idikgljglpfilbhaboonnpnnincjhjkd',
|
||||
electron: '>=1.2.1'
|
||||
};
|
||||
|
||||
const extensions = [edi.REDUX_DEVTOOLS, ChromeLens];
|
||||
|
||||
for (const extension of extensions) {
|
||||
try {
|
||||
edi.default(extension);
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
window.onClose(() => {
|
||||
appWindow = null;
|
||||
if (!__DARWIN__ && !preventQuit) {
|
||||
app.quit();
|
||||
}
|
||||
});
|
||||
|
||||
window.onDidLoad(() => {
|
||||
window.show();
|
||||
|
||||
const fns = onDidLoadFns;
|
||||
onDidLoadFns = null;
|
||||
for (const fn of fns) {
|
||||
fn(window);
|
||||
}
|
||||
});
|
||||
|
||||
window.load();
|
||||
|
||||
appWindow = window;
|
||||
}
|
||||
|
||||
// This method will be called when Electron has finished
|
||||
// initialization and is ready to create browser windows.
|
||||
// Some APIs can only be used after this event occurs.
|
||||
app.on(ElectronAppChannel.Ready, () => {
|
||||
if (isDuplicateInstance) {
|
||||
return;
|
||||
}
|
||||
|
||||
readyTime = now() - launchTime;
|
||||
|
||||
createWindow();
|
||||
|
||||
notificationService = new ElectronNotificationService({
|
||||
width: 340,
|
||||
height: 100,
|
||||
padding: 0,
|
||||
borderRadius: 0,
|
||||
// appIcon: iconPath,
|
||||
displayTime: 5000,
|
||||
defaultStyleContainer: {},
|
||||
defaultStyleAppIcon: { display: 'none' },
|
||||
defaultStyleImage: {},
|
||||
defaultStyleClose: {},
|
||||
defaultStyleText: {}
|
||||
});
|
||||
|
||||
notificationService.options.defaultWindow.webPreferences.preload = path.join(
|
||||
__dirname,
|
||||
'resources/notification/preload.js'
|
||||
);
|
||||
|
||||
notificationService.templatePath = path.join(
|
||||
__dirname,
|
||||
'resources/notification/template.html'
|
||||
);
|
||||
|
||||
ipcMain.on('uncaught-exception', (event: IpcMainEvent, error: Error) => {
|
||||
handleUncaughtException(error);
|
||||
});
|
||||
|
||||
ipcMain.on(
|
||||
'send-error-report',
|
||||
(
|
||||
event: IpcMainEvent,
|
||||
{ error, extra }: { error: Error; extra: { [key: string]: string } }
|
||||
) => {}
|
||||
);
|
||||
});
|
||||
|
||||
// Quit when all windows are closed.
|
||||
app.on(ElectronAppChannel.WindowAllClosed, () => {
|
||||
// On OS X it is common for applications and their menu bar
|
||||
// to stay active until the user quits explicitly with Cmd + Q
|
||||
if (process.platform !== 'darwin') {
|
||||
app.quit();
|
||||
}
|
||||
});
|
||||
|
||||
app.on(ElectronAppChannel.Activate, () => {
|
||||
onDidLoad(window => {
|
||||
window.show();
|
||||
});
|
||||
});
|
||||
|
||||
function onDidLoad(fn: OnDidLoadFn) {
|
||||
if (onDidLoadFns) {
|
||||
onDidLoadFns.push(fn);
|
||||
} else {
|
||||
if (appWindow) {
|
||||
fn(appWindow);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ipcMain.on(UpdaterChannel.Check, (event: IpcMainEvent, ...args: any[]) => {
|
||||
event.returnValue = false;
|
||||
});
|
||||
|
||||
ipcMain.on(FileChannel.ReadFile, (event: IpcMainEvent, ...args: any[]) => {
|
||||
try {
|
||||
fse.readFile(root(args[0]), (err, data) => {
|
||||
if (!!err) {
|
||||
event.returnValue = null;
|
||||
} else {
|
||||
event.returnValue = new Blob([data]);
|
||||
}
|
||||
});
|
||||
} catch (error) {
|
||||
event.returnValue = null;
|
||||
}
|
||||
});
|
||||
|
||||
ipcMain.on(
|
||||
FileChannel.SaveFile,
|
||||
async (event: IpcMainEvent, ...args: any[]) => {
|
||||
try {
|
||||
const buffer: Buffer = args[0];
|
||||
const fileName: string = args[1];
|
||||
let savePath: string = path.join(
|
||||
!!args[2] ? args[2] : DefaultFolder.downloads(),
|
||||
fileName
|
||||
);
|
||||
savePath = await FileUtil.uniqueFileName(savePath);
|
||||
|
||||
fse.writeFile(savePath, buffer, err => {
|
||||
if (!err) {
|
||||
event.returnValue = savePath;
|
||||
} else {
|
||||
event.returnValue = undefined;
|
||||
}
|
||||
});
|
||||
} catch (error) {
|
||||
event.returnValue = undefined;
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
ipcMain.on(
|
||||
IdleStateChannel.StartCheck,
|
||||
(event: IpcMainEvent, ...args: any[]) => {
|
||||
if (!!idle) {
|
||||
idle.destoryChecker();
|
||||
idle = null;
|
||||
}
|
||||
idle = new IdleChecker(appWindow.browserWindow); // default 10min
|
||||
idle.startChecker();
|
||||
}
|
||||
);
|
||||
|
||||
ipcMain.on(
|
||||
NotificationChannel.Notify,
|
||||
(event: IpcMainEvent, ...args: any[]) => {
|
||||
const noti: NotificationRequest = args[0];
|
||||
|
||||
notificationService.notify({
|
||||
title: noti.title,
|
||||
text: noti.contents,
|
||||
image:
|
||||
noti.image ||
|
||||
path.join(__dirname, 'resources/notification/image/img_nophoto_50.png'),
|
||||
sound: noti.useSound
|
||||
? path.join(
|
||||
'file://',
|
||||
__dirname,
|
||||
'resources/notification/sound/messageAlarm.mp3'
|
||||
)
|
||||
: '',
|
||||
onClick: () => {
|
||||
console.log('onClick');
|
||||
}
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
ipcMain.on(
|
||||
NotificationChannel.CloseAllNotify,
|
||||
(event: IpcMainEvent, ...args: any[]) => {
|
||||
console.log('Channel.closeAllNotify', args);
|
||||
}
|
||||
);
|
|
@ -0,0 +1,37 @@
|
|||
import * as os from 'os';
|
||||
import { execSync } from 'child_process';
|
||||
import * as fse from 'fs-extra';
|
||||
|
||||
export class DefaultFolder {
|
||||
static downloads(): string {
|
||||
switch (os.platform()) {
|
||||
case 'win32':
|
||||
return `${process.env.USERPROFILE}/Downloads`;
|
||||
case 'darwin':
|
||||
return `${process.env.HOME}/Downloads`;
|
||||
case 'linux': {
|
||||
let dir: Buffer;
|
||||
try {
|
||||
dir = execSync('xdg-user-dir DOWNLOAD', { stdio: [0, 3, 3] });
|
||||
} catch (_) {}
|
||||
|
||||
if (dir) {
|
||||
return dir.toString('utf-8');
|
||||
}
|
||||
|
||||
let stat: fse.Stats;
|
||||
const homeDownloads = `${process.env.HOME}/Downloads`;
|
||||
try {
|
||||
stat = fse.statSync(homeDownloads);
|
||||
} catch (_) {}
|
||||
if (stat) {
|
||||
return homeDownloads;
|
||||
}
|
||||
return '/tmp/';
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,222 @@
|
|||
import * as path from 'path';
|
||||
import * as fse from 'fs-extra';
|
||||
|
||||
/**
|
||||
*
|
||||
* separator
|
||||
* If the specified filename exists, the separator will be added before the incremental value such as: file{separator}2.jpg
|
||||
* The default value is '-'.
|
||||
*
|
||||
* mode
|
||||
* The mode allows you to specify which characters to use to generate the incremental value (the string after the separator)
|
||||
* The default value is 'numeric'.
|
||||
* 'numeric' Using the following characters: 1234567890
|
||||
* 'alpha' Using the following characters: abcdefghijklmnopqrstuvwxyz
|
||||
* 'ALPHA' Using the following characters: ABCDEFGHIJKLMNOPQRSTUVWXYZ
|
||||
* 'alphanumeric' Using the following characters: 0123456789abcdefghijklmnopqrstuvwxyz
|
||||
* 'ALPHANUMERIC' Using the following characters: 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ
|
||||
* 'charset' You must specify the characters you wish to use in the charset option
|
||||
*
|
||||
* paddingCharacter && paddingSize
|
||||
* If you wish to left-pad the incremental values with a character, use this option. Here's an example :
|
||||
* var uniquefilename = require('uniquefilename');
|
||||
* options = {mode: 'alpha', paddingCharacter: '0', paddingSize: 3};
|
||||
* uniquefilename.get('/path/to/dir/file.jpg', options, function(filename) {
|
||||
* // filename might be "/path/to/dir/file.jpg",
|
||||
* // "/path/to/dir/file-002.jpg", "/path/to/dir/file-045.jpg", etc...
|
||||
* // depending on the files that exist on your filesystem
|
||||
* });
|
||||
*
|
||||
* alwaysAppend
|
||||
* If alwaysAppend is true filenames will include the separator and attachment from the first request.
|
||||
* So instead of file.jpg, file-2.jpg you'd get file-1.jpg, file-2.jpg.
|
||||
*/
|
||||
export interface UniqueFileNameOption {
|
||||
separator?: string;
|
||||
mode?:
|
||||
| 'numeric'
|
||||
| 'alpha'
|
||||
| 'ALPHA'
|
||||
| 'alphanumeric'
|
||||
| 'ALPHANUMERIC'
|
||||
| 'charset';
|
||||
paddingCharacter?: string;
|
||||
paddingSize?: number;
|
||||
alwaysAppend?: boolean;
|
||||
charset?: string;
|
||||
}
|
||||
|
||||
const charsets = {
|
||||
alpha: 'abcdefghijklmnopqrstuvwxyz',
|
||||
alphanumeric: '0123456789abcdefghijklmnopqrstuvwxyz',
|
||||
ALPHA: 'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
|
||||
ALPHANUMERIC: '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'
|
||||
};
|
||||
|
||||
interface UniqueFile {
|
||||
dir?: string;
|
||||
ext?: string;
|
||||
base?: string;
|
||||
increment?: number;
|
||||
}
|
||||
|
||||
export class FileUtil {
|
||||
static blobToBuffer(blob: Blob): Promise<Buffer> {
|
||||
if (typeof Blob === 'undefined' || !(blob instanceof Blob)) {
|
||||
throw new Error('first argument must be a Blob');
|
||||
}
|
||||
|
||||
return new Promise<Buffer>((resolve, reject) => {
|
||||
const reader = new FileReader();
|
||||
reader.onloadend = () => {
|
||||
resolve(Buffer.from(reader.result as ArrayBuffer));
|
||||
};
|
||||
reader.onerror = () => {
|
||||
reader.abort();
|
||||
reject(reader.error);
|
||||
};
|
||||
reader.readAsArrayBuffer(blob);
|
||||
});
|
||||
}
|
||||
|
||||
static uniqueFileName(
|
||||
filePath: string,
|
||||
options?: UniqueFileNameOption
|
||||
): Promise<string> {
|
||||
return new Promise<string>((resolve, reject) => {
|
||||
const dir = path.dirname(filePath);
|
||||
const ext = path.extname(filePath);
|
||||
const base = path.basename(filePath, ext);
|
||||
|
||||
const uniqueFile: UniqueFile = {
|
||||
dir,
|
||||
ext,
|
||||
base
|
||||
};
|
||||
|
||||
options = options || {};
|
||||
options.separator = options.separator || '-';
|
||||
options.mode = options.mode || 'numeric';
|
||||
|
||||
if ('numeric' !== options.mode) {
|
||||
if (charsets[options.mode]) {
|
||||
options.charset = charsets[options.mode];
|
||||
options.mode = 'charset';
|
||||
} else if (
|
||||
'charset' !== options.mode ||
|
||||
('charset' === options.mode && !options.charset)
|
||||
) {
|
||||
options.mode = 'numeric';
|
||||
}
|
||||
}
|
||||
|
||||
if (options.paddingSize && !options.paddingCharacter) {
|
||||
options.paddingCharacter = '0';
|
||||
}
|
||||
|
||||
FileUtil.uniqueFileNameProcess(
|
||||
uniqueFile,
|
||||
options,
|
||||
(fileName: string) => {
|
||||
resolve(fileName);
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
private static uniqueFileNameProcess(
|
||||
uniqueFile: UniqueFile,
|
||||
options: UniqueFileNameOption,
|
||||
callback: (fileName: string) => void
|
||||
) {
|
||||
let fileName: string;
|
||||
let append = '';
|
||||
|
||||
if (options.alwaysAppend && !uniqueFile.increment) {
|
||||
uniqueFile.increment = 1;
|
||||
}
|
||||
|
||||
if (uniqueFile.increment) {
|
||||
if ('numeric' === options.mode) {
|
||||
append = '' + uniqueFile.increment;
|
||||
} else {
|
||||
append = FileUtil.numberToString(uniqueFile.increment, options.charset);
|
||||
}
|
||||
|
||||
if (options.paddingSize) {
|
||||
while (append.length < options.paddingSize) {
|
||||
append = options.paddingCharacter + append;
|
||||
}
|
||||
}
|
||||
|
||||
append = options.separator + append;
|
||||
}
|
||||
|
||||
fileName = path.join(
|
||||
uniqueFile.dir,
|
||||
uniqueFile.base + append + uniqueFile.ext
|
||||
);
|
||||
if (fse.existsSync(fileName)) {
|
||||
if (uniqueFile.increment) {
|
||||
uniqueFile.increment += 1;
|
||||
} else {
|
||||
uniqueFile.increment = 'numeric' === options.mode ? 2 : 1;
|
||||
}
|
||||
return FileUtil.uniqueFileNameProcess(uniqueFile, options, callback);
|
||||
} else {
|
||||
return callback(fileName);
|
||||
}
|
||||
}
|
||||
|
||||
private static numberToString(nbr: number, charset: string) {
|
||||
const charsetLen = charset.length;
|
||||
let strLen = 0;
|
||||
let strThisLen = 0;
|
||||
let tmp: number;
|
||||
|
||||
for (let maxpower = 20; maxpower >= 0; maxpower--) {
|
||||
const maxvalue = FileUtil.sumOfPowerFromOne(charsetLen, maxpower);
|
||||
|
||||
if (maxvalue < nbr) {
|
||||
strLen = maxpower + 1;
|
||||
strThisLen = maxvalue + Math.pow(charsetLen, maxpower + 1) - maxvalue;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (0 === strLen) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let str = '';
|
||||
while (--strLen >= 0) {
|
||||
if (strLen === 0) {
|
||||
str += charset.charAt(nbr - 1);
|
||||
break;
|
||||
}
|
||||
|
||||
strThisLen = Math.pow(charsetLen, strLen);
|
||||
const initial = FileUtil.sumOfPowerFromOne(charsetLen, strLen - 1);
|
||||
|
||||
for (tmp = charsetLen; tmp >= 1; tmp--) {
|
||||
if (initial + tmp * strThisLen < nbr) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
nbr -= tmp * strThisLen;
|
||||
str += charset.charAt(tmp - 1);
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
private static sumOfPowerFromOne(base: number, maxpower: number) {
|
||||
let value = 0;
|
||||
for (let tmp = maxpower; tmp >= 1; tmp--) {
|
||||
value += Math.pow(base, tmp);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,72 @@
|
|||
import { powerMonitor, BrowserWindow } from 'electron';
|
||||
import { IdleStateChannel } from '@ucap-webmessenger/native-electron';
|
||||
import { setInterval } from 'timers';
|
||||
|
||||
export enum IdleType {
|
||||
ACTIVE = 'ACT',
|
||||
IDLE = 'IDLE'
|
||||
}
|
||||
|
||||
export class IdleChecker {
|
||||
private limitSec: number;
|
||||
private intervalObject: any;
|
||||
private status: IdleType;
|
||||
private window: BrowserWindow | null;
|
||||
|
||||
public constructor(window: BrowserWindow, limitedMin?: number) {
|
||||
limitedMin = limitedMin || 10;
|
||||
|
||||
this.limitSec = limitedMin * 60;
|
||||
this.intervalObject = null;
|
||||
this.status = IdleType.ACTIVE;
|
||||
this.window = window;
|
||||
}
|
||||
|
||||
private doCheckIdle(): void {
|
||||
const idle: number = powerMonitor.getSystemIdleTime();
|
||||
if (idle > this.limitSec) {
|
||||
if (this.status === IdleType.ACTIVE) {
|
||||
this.status = IdleType.IDLE;
|
||||
// TODO :: USER_STATUS change away
|
||||
this.window.webContents.send(IdleStateChannel.Changed, this.status);
|
||||
}
|
||||
} else {
|
||||
if (this.status === IdleType.IDLE) {
|
||||
this.status = IdleType.ACTIVE;
|
||||
// TODO :: USER_STATUS chage online
|
||||
this.window.webContents.send(IdleStateChannel.Changed, this.status);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public resetIdleTime(limitedMin: number): void {
|
||||
limitedMin = limitedMin || 10;
|
||||
|
||||
if (!!this.intervalObject) {
|
||||
clearInterval(this.intervalObject);
|
||||
}
|
||||
this.limitSec = limitedMin * 60;
|
||||
|
||||
// storage.setIdleTimeLimit(limitedMin);
|
||||
// global.opt_idleTimeLimit = limitedMin;
|
||||
|
||||
this.startChecker();
|
||||
console.log('RESET IDLE TIMER in ' + limitedMin + 'm');
|
||||
}
|
||||
|
||||
public startChecker() {
|
||||
console.log('Idle Checker Start');
|
||||
if (!this.intervalObject) {
|
||||
this.intervalObject = setInterval(() => {
|
||||
this.doCheckIdle();
|
||||
}, 1000);
|
||||
}
|
||||
}
|
||||
|
||||
public destoryChecker() {
|
||||
console.log('Idle Checker Destory');
|
||||
if (!!this.intervalObject) {
|
||||
clearInterval(this.intervalObject);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,99 @@
|
|||
import Store from 'electron-store';
|
||||
|
||||
const STORE_KEY_AUTORUN = 'options.autoRun';
|
||||
const STORE_KEY_AUTOLOGIN = 'options.autoLogin';
|
||||
const STORE_KEY_STARTUPHIDEWINDOW = 'options.startupHideWindow';
|
||||
const STORE_KEY_LOGINCOMPANY = 'login.loginCompany';
|
||||
const STORE_KEY_LOGINID = 'login.loginId';
|
||||
const STORE_KEY_LOGINPW = 'login.loginPw';
|
||||
|
||||
export class Storage extends Store<any> {
|
||||
constructor() {
|
||||
super({
|
||||
schema: {
|
||||
options: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
autoRun: {
|
||||
type: 'boolean'
|
||||
},
|
||||
autoLogin: {
|
||||
type: 'boolean'
|
||||
},
|
||||
startupHideWindow: {
|
||||
type: 'boolean'
|
||||
}
|
||||
},
|
||||
default: {
|
||||
autoRun: false,
|
||||
autoLogin: false,
|
||||
startupHideWindow: false
|
||||
}
|
||||
},
|
||||
login: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
loginCompany: {
|
||||
type: 'string'
|
||||
},
|
||||
loginId: {
|
||||
type: 'string'
|
||||
},
|
||||
loginPw: {
|
||||
type: 'string'
|
||||
}
|
||||
},
|
||||
default: {
|
||||
loginCompany: '',
|
||||
loginId: '',
|
||||
loginPw: ''
|
||||
}
|
||||
}
|
||||
},
|
||||
encryptionKey: 'ucap',
|
||||
fileExtension: 'dat'
|
||||
});
|
||||
}
|
||||
|
||||
get autoRun(): boolean {
|
||||
return this.get(STORE_KEY_AUTORUN, false);
|
||||
}
|
||||
set autoRun(autoRun: boolean) {
|
||||
this.set(STORE_KEY_AUTORUN, autoRun);
|
||||
}
|
||||
|
||||
get autoLogin(): boolean {
|
||||
return this.get(STORE_KEY_AUTOLOGIN, false);
|
||||
}
|
||||
set autoLogin(autoLogin: boolean) {
|
||||
this.set(STORE_KEY_AUTOLOGIN, autoLogin);
|
||||
}
|
||||
|
||||
get startupHideWindow(): boolean {
|
||||
return this.get(STORE_KEY_STARTUPHIDEWINDOW, false);
|
||||
}
|
||||
set startupHideWindow(startupHideWindow: boolean) {
|
||||
this.set(STORE_KEY_STARTUPHIDEWINDOW, startupHideWindow);
|
||||
}
|
||||
|
||||
get loginCompany(): string {
|
||||
return this.get(STORE_KEY_LOGINCOMPANY, false);
|
||||
}
|
||||
set loginCompany(loginCompany: string) {
|
||||
this.set(STORE_KEY_LOGINCOMPANY, loginCompany);
|
||||
}
|
||||
|
||||
get loginId(): string {
|
||||
return this.get(STORE_KEY_LOGINID, false);
|
||||
}
|
||||
set loginId(loginId: string) {
|
||||
this.set(STORE_KEY_LOGINID, loginId);
|
||||
}
|
||||
|
||||
get loginPw(): string {
|
||||
return this.get(STORE_KEY_LOGINPW, false);
|
||||
}
|
||||
set loginPw(loginPw: string) {
|
||||
this.set(STORE_KEY_LOGINPW, loginPw);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
import { BrowserWindow } from 'electron';
|
||||
import { WindowState } from '@ucap-webmessenger/native';
|
||||
import { WindowStateChannel } from '@ucap-webmessenger/native-electron';
|
||||
import { ElectronBrowserWindowChannel } from '@ucap-webmessenger/electron-core';
|
||||
|
||||
export function getWindowState(window: Electron.BrowserWindow): WindowState {
|
||||
if (window.isFullScreen()) {
|
||||
return WindowState.FullScreen;
|
||||
} else if (window.isMaximized()) {
|
||||
return WindowState.Maximized;
|
||||
} else if (window.isMinimized()) {
|
||||
return WindowState.Minimized;
|
||||
} else if (!window.isVisible()) {
|
||||
return WindowState.Hidden;
|
||||
} else {
|
||||
return WindowState.Normal;
|
||||
}
|
||||
}
|
||||
|
||||
export function registerWindowStateChangedEvents(window: BrowserWindow) {
|
||||
window.on(ElectronBrowserWindowChannel.EnterFullScreen, () =>
|
||||
sendWindowStateEvent(window, WindowState.FullScreen)
|
||||
);
|
||||
|
||||
window.on(ElectronBrowserWindowChannel.LeaveFullScreen, () =>
|
||||
sendWindowStateEvent(window, WindowState.Normal)
|
||||
);
|
||||
|
||||
window.on(ElectronBrowserWindowChannel.Maximize, () =>
|
||||
sendWindowStateEvent(window, WindowState.Maximized)
|
||||
);
|
||||
window.on(ElectronBrowserWindowChannel.Minimize, () =>
|
||||
sendWindowStateEvent(window, WindowState.Minimized)
|
||||
);
|
||||
window.on(ElectronBrowserWindowChannel.Unmaximize, () =>
|
||||
sendWindowStateEvent(window, WindowState.Normal)
|
||||
);
|
||||
window.on(ElectronBrowserWindowChannel.Restore, () =>
|
||||
sendWindowStateEvent(window, WindowState.Normal)
|
||||
);
|
||||
window.on(ElectronBrowserWindowChannel.Hide, () =>
|
||||
sendWindowStateEvent(window, WindowState.Hidden)
|
||||
);
|
||||
window.on(ElectronBrowserWindowChannel.Show, () => {
|
||||
// because the app can be maximized before being closed - which will restore it
|
||||
// maximized on the next launch - this function should inspect the current state
|
||||
// rather than always assume it is a 'normal' launch
|
||||
sendWindowStateEvent(window, getWindowState(window));
|
||||
});
|
||||
}
|
||||
|
||||
function sendWindowStateEvent(window: BrowserWindow, windowState: WindowState) {
|
||||
window.webContents.send(WindowStateChannel.Changed, windowState);
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
export function now(): number {
|
||||
const time = process.hrtime();
|
||||
return time[0] * 1000 + time[1] / 1000000;
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
import * as path from 'path';
|
||||
|
||||
// tslint:disable-next-line: variable-name
|
||||
const _root = __DEV__
|
||||
? path.resolve(__dirname, '..', '..')
|
||||
: path.resolve(__dirname);
|
||||
|
||||
export function root(...paths: string[]) {
|
||||
const args = Array.prototype.slice.call(paths, 0);
|
||||
return path.join.apply(path, [_root].concat(args));
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"baseUrl": "./",
|
||||
"outDir": "../../dist/main",
|
||||
"sourceMap": true,
|
||||
"declaration": false,
|
||||
"module": "commonjs",
|
||||
"moduleResolution": "node",
|
||||
"emitDecoratorMetadata": true,
|
||||
"experimentalDecorators": true,
|
||||
"esModuleInterop": true,
|
||||
"target": "es5",
|
||||
"types": ["node"],
|
||||
"lib": ["es2017", "es2016", "es2015", "dom"],
|
||||
"paths": {
|
||||
"@ucap-webmessenger/electron-core": [
|
||||
"../ucap-webmessenger-electron-core/src/public-api"
|
||||
],
|
||||
"@ucap-webmessenger/electron-notification": [
|
||||
"../ucap-webmessenger-electron-notification/src/public-api"
|
||||
],
|
||||
"@ucap-webmessenger/native": [
|
||||
"../../projects/ucap-webmessenger-native/src/public-api"
|
||||
],
|
||||
"@ucap-webmessenger/native-electron": [
|
||||
"../../projects/ucap-webmessenger-native-electron/src/public-api"
|
||||
],
|
||||
"@ucap-webmessenger/electron": [
|
||||
"../../projects/ucap-webmessenger-electron/src/public-api"
|
||||
]
|
||||
}
|
||||
},
|
||||
"exclude": ["../../node_modules", "**/*.spec.ts"]
|
||||
}
|
7
electron-projects/ucap-webmessenger-electron/tslint.json
Normal file
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"extends": "../../tslint.json",
|
||||
"rules": {
|
||||
"directive-selector": [true, "attribute", "ucapElectron", "camelCase"],
|
||||
"component-selector": [true, "element", "ucap-electron", "kebab-case"]
|
||||
}
|
||||
}
|
|
@ -24,6 +24,9 @@
|
|||
],
|
||||
"@ucap-webmessenger/native-electron": [
|
||||
"../projects/ucap-webmessenger-native-electron/src/public-api"
|
||||
],
|
||||
"@ucap-webmessenger/electron": [
|
||||
"../projects/ucap-webmessenger-electron/src/public-api"
|
||||
]
|
||||
}
|
||||
},
|
||||
|
|
13
package.json
|
@ -4,13 +4,12 @@
|
|||
"scripts": {
|
||||
"ng": "ng",
|
||||
"start": "npm-run-all -p start:renderer start:main",
|
||||
"start:main": "wait-on http-get://localhost:4200/ && npm run build:main:dev && electron --nolazy --inspect-brk=9229 .",
|
||||
"start:renderer": "ng serve",
|
||||
"start:web": "cross-env UCAP_ENV=WEB ng serve",
|
||||
"start:production": "npm run build:renderer && npm run build:main:prod && electron --nolazy --inspect-brk=9229 .",
|
||||
"start:main": "wait-on http-get://localhost:4200/ && npm run build:main:development && electron --nolazy --inspect-brk=9229 .",
|
||||
"start:renderer": "cross-env UCAP_ENV_RUNTIME=ELECTRON ng serve -c renderer-development",
|
||||
"start:browser": "cross-env UCAP_ENV_RUNTIME=BROWSER ng serve -c browser-development -o",
|
||||
"build:renderer": "cross-env NODE_ENV=production ng build --base-href ./",
|
||||
"build:main:dev": "cross-env NODE_ENV=development TS_NODE_PROJECT='./config/tsconfig.webpack.json' parallel-webpack --config=config/main.webpack.config.ts",
|
||||
"build:main:prod": "cross-env NODE_ENV=production TS_NODE_PROJECT='./config/tsconfig.webpack.json' NODE_OPTIONS='--max_old_space_size=4096' parallel-webpack --config=config/main.webpack.config.ts",
|
||||
"build:main:development": "cross-env NODE_ENV=development TS_NODE_PROJECT='./config/tsconfig.webpack.json' parallel-webpack --config=config/main.webpack.config.ts",
|
||||
"build:main:production": "cross-env NODE_ENV=production TS_NODE_PROJECT='./config/tsconfig.webpack.json' NODE_OPTIONS='--max_old_space_size=4096' parallel-webpack --config=config/main.webpack.config.ts",
|
||||
"test": "ng test",
|
||||
"lint": "ng lint",
|
||||
"e2e": "ng e2e"
|
||||
|
@ -112,5 +111,5 @@
|
|||
"webpack-node-externals": "^1.7.2",
|
||||
"zone.js": "~0.9.1"
|
||||
},
|
||||
"main": "./dist/main/main.js"
|
||||
"main": "./dist/ucap-webmessenger-electron/main.js"
|
||||
}
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
import { NgModule, APP_INITIALIZER } from '@angular/core';
|
||||
|
||||
import { UCAP_NATIVE_SERVICE } from '@ucap-webmessenger/native';
|
||||
import { ElectronNativeService } from '@ucap-webmessenger/native-electron';
|
||||
|
||||
import { RESOLVERS } from './resolvers';
|
||||
import { SERVICES } from './services';
|
||||
import { AppService } from './services/app.service';
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { UCAP_NATIVE_SERVICE } from '@ucap-webmessenger/native';
|
||||
import { environment } from '../environments/environment';
|
||||
|
||||
export function initializeApp(appService: AppService) {
|
||||
return (): Promise<any> => {
|
||||
|
@ -19,13 +19,17 @@ export function initializeApp(appService: AppService) {
|
|||
providers: [
|
||||
...SERVICES,
|
||||
...RESOLVERS,
|
||||
{
|
||||
provide: UCAP_NATIVE_SERVICE,
|
||||
useClass: environment.modules.native.serviceClass,
|
||||
deps: [HttpClient]
|
||||
},
|
||||
{
|
||||
provide: APP_INITIALIZER,
|
||||
useFactory: initializeApp,
|
||||
deps: [AppService],
|
||||
multi: true
|
||||
},
|
||||
{ provide: UCAP_NATIVE_SERVICE, useClass: ElectronNativeService }
|
||||
}
|
||||
]
|
||||
})
|
||||
export class AppProviderModule {}
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
import { Injectable } from '@angular/core';
|
||||
import { AppNotificationService } from './notification.service';
|
||||
import { SessionStorageService } from '@ucap-webmessenger/web-storage';
|
||||
import { EnviromentUtilService } from '@ucap-webmessenger/util';
|
||||
import { DeviceType } from '@ucap-webmessenger/core';
|
||||
import { EnvironmentsInfo, KEY_ENVIRONMENTS_INFO } from '@app/types';
|
||||
import { AppNotificationService } from './notification.service';
|
||||
|
||||
@Injectable()
|
||||
export class AppService {
|
||||
|
@ -13,8 +13,8 @@ export class AppService {
|
|||
private appNotificationService: AppNotificationService
|
||||
) {}
|
||||
|
||||
public postInit(): Promise<void> {
|
||||
return new Promise<void>((resolve, reject) => {
|
||||
public postInit(): Promise<any> {
|
||||
const initPromise = new Promise<void>((resolve, reject) => {
|
||||
try {
|
||||
let deviceType: DeviceType;
|
||||
if (this.enviromentUtilService.nodeWebkit()) {
|
||||
|
@ -40,5 +40,7 @@ export class AppService {
|
|||
reject();
|
||||
}
|
||||
});
|
||||
|
||||
return Promise.all([initPromise]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
import { Environment, build } from './environment.type';
|
||||
import { BrowserNativeService } from '@ucap-webmessenger/native-browser';
|
||||
|
||||
// This file can be replaced during build by using the `fileReplacements` array.
|
||||
// `ng build --prod` replaces `environment.ts` with `environment.prod.ts`.
|
||||
// The list of file replacements can be found in `angular.json`.
|
||||
|
||||
export const environment: Environment = build(false);
|
||||
environment.modules.native.serviceClass = BrowserNativeService;
|
||||
|
||||
/*
|
||||
* For easier debugging in development mode, you can import the following file
|
||||
* to ignore zone related error stack frames such as `zone.run`, `zoneDelegate.invokeTask`.
|
||||
*
|
||||
* This import should be commented out in production mode because it will have a negative impact
|
||||
* on performance if an error is thrown.
|
||||
*/
|
||||
// import 'zone.js/dist/zone-error'; // Included with Angular CLI.
|
|
@ -0,0 +1,5 @@
|
|||
import { Environment, build } from './environment.type';
|
||||
import { BrowserNativeService } from '@ucap-webmessenger/native-browser';
|
||||
|
||||
export const environment: Environment = build(true);
|
||||
environment.modules.native.serviceClass = BrowserNativeService;
|
|
@ -0,0 +1,18 @@
|
|||
import { Environment, build } from './environment.type';
|
||||
import { ElectronNativeService } from '@ucap-webmessenger/native-electron';
|
||||
|
||||
// This file can be replaced during build by using the `fileReplacements` array.
|
||||
// `ng build --prod` replaces `environment.ts` with `environment.prod.ts`.
|
||||
// The list of file replacements can be found in `angular.json`.
|
||||
|
||||
export const environment: Environment = build(false);
|
||||
environment.modules.native.serviceClass = ElectronNativeService;
|
||||
|
||||
/*
|
||||
* For easier debugging in development mode, you can import the following file
|
||||
* to ignore zone related error stack frames such as `zone.run`, `zoneDelegate.invokeTask`.
|
||||
*
|
||||
* This import should be commented out in production mode because it will have a negative impact
|
||||
* on performance if an error is thrown.
|
||||
*/
|
||||
// import 'zone.js/dist/zone-error'; // Included with Angular CLI.
|
|
@ -0,0 +1,5 @@
|
|||
import { Environment, build } from './environment.type';
|
||||
import { ElectronNativeService } from '@ucap-webmessenger/native-electron';
|
||||
|
||||
export const environment: Environment = build(true);
|
||||
environment.modules.native.serviceClass = ElectronNativeService;
|
|
@ -1,3 +0,0 @@
|
|||
import { Environment, build } from './environment.type';
|
||||
|
||||
export const environment: Environment = build(true);
|
|
@ -1,3 +1,6 @@
|
|||
import { Type } from '@angular/core';
|
||||
import { NativeService } from '@ucap-webmessenger/native';
|
||||
|
||||
export abstract class UrlConfig {
|
||||
constructor(
|
||||
protected useSsl: boolean,
|
||||
|
@ -334,6 +337,9 @@ export interface Environment {
|
|||
};
|
||||
};
|
||||
modules: {
|
||||
native: {
|
||||
serviceClass?: Type<NativeService>;
|
||||
};
|
||||
event: {
|
||||
acceptableFileExtensions: string[];
|
||||
};
|
||||
|
@ -381,6 +387,7 @@ export function build(production: boolean): Environment {
|
|||
}
|
||||
},
|
||||
modules: {
|
||||
native: {},
|
||||
event: {
|
||||
acceptableFileExtensions: [
|
||||
// 문서1
|
||||
|
|
|
@ -1,7 +0,0 @@
|
|||
{
|
||||
"$schema": "../../node_modules/ng-packagr/ng-package.schema.json",
|
||||
"dest": "../../dist/ucap-webmessenger-electron-core",
|
||||
"lib": {
|
||||
"entryFile": "src/public-api.ts"
|
||||
}
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
{
|
||||
"name": "@ucap-webmessenger/electron-core",
|
||||
"version": "0.0.1",
|
||||
"peerDependencies": {
|
||||
"@angular/common": "^8.2.11",
|
||||
"@angular/core": "^8.2.11"
|
||||
}
|
||||
}
|
|
@ -1,26 +0,0 @@
|
|||
{
|
||||
"extends": "../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "../../out-tsc/lib",
|
||||
"target": "es2015",
|
||||
"declaration": true,
|
||||
"inlineSources": true,
|
||||
"types": [],
|
||||
"lib": [
|
||||
"dom",
|
||||
"es2018"
|
||||
]
|
||||
},
|
||||
"angularCompilerOptions": {
|
||||
"annotateForClosureCompiler": true,
|
||||
"skipTemplateCodegen": true,
|
||||
"strictMetadataEmit": true,
|
||||
"fullTemplateTypeCheck": true,
|
||||
"strictInjectionParameters": true,
|
||||
"enableResourceInlining": true
|
||||
},
|
||||
"exclude": [
|
||||
"src/test.ts",
|
||||
"**/*.spec.ts"
|
||||
]
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
{
|
||||
"$schema": "../../node_modules/ng-packagr/ng-package.schema.json",
|
||||
"dest": "../../dist/ucap-webmessenger-electron-notification",
|
||||
"lib": {
|
||||
"entryFile": "src/public-api.ts"
|
||||
}
|
||||
}
|
|
@ -1,26 +0,0 @@
|
|||
{
|
||||
"extends": "../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "../../out-tsc/lib",
|
||||
"target": "es2015",
|
||||
"declaration": true,
|
||||
"inlineSources": true,
|
||||
"types": [],
|
||||
"lib": [
|
||||
"dom",
|
||||
"es2018"
|
||||
]
|
||||
},
|
||||
"angularCompilerOptions": {
|
||||
"annotateForClosureCompiler": true,
|
||||
"skipTemplateCodegen": true,
|
||||
"strictMetadataEmit": true,
|
||||
"fullTemplateTypeCheck": true,
|
||||
"strictInjectionParameters": true,
|
||||
"enableResourceInlining": true
|
||||
},
|
||||
"exclude": [
|
||||
"src/test.ts",
|
||||
"**/*.spec.ts"
|
||||
]
|
||||
}
|
|
@ -8,7 +8,11 @@ import {
|
|||
} from '@ucap-webmessenger/native';
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { map } from 'rxjs/operators';
|
||||
import { Injectable } from '@angular/core';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class BrowserNativeService implements NativeService {
|
||||
notify(noti: NotificationRequest): void {}
|
||||
closeAllNotify(): void {}
|
||||
|
|
|
@ -1,12 +1,16 @@
|
|||
import { TranslateLoader } from '@ngx-translate/core';
|
||||
import { Observable } from 'rxjs';
|
||||
import { NativeService } from '@ucap-webmessenger/native';
|
||||
import { NativeService, UCAP_NATIVE_SERVICE } from '@ucap-webmessenger/native';
|
||||
import { take, map } from 'rxjs/operators';
|
||||
import { FileUtil } from '@ucap-webmessenger/core';
|
||||
import { Injectable, Inject } from '@angular/core';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class TranslateBrowserLoader implements TranslateLoader {
|
||||
constructor(
|
||||
private nativeService: NativeService,
|
||||
@Inject(UCAP_NATIVE_SERVICE) private nativeService: NativeService,
|
||||
private prefix: string = '/assets/i18n/',
|
||||
private suffix: string = '.json'
|
||||
) {}
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
import { NgModule, ModuleWithProviders } from '@angular/core';
|
||||
|
||||
import { BrowserNativeService } from './services/browser-native.service';
|
||||
|
||||
const SERVICES = [BrowserNativeService];
|
||||
|
||||
@NgModule({
|
||||
declarations: [],
|
||||
imports: [],
|
||||
exports: []
|
||||
})
|
||||
export class UCapBrowserNativeModule {
|
||||
public static forRoot(): ModuleWithProviders<UCapBrowserNativeModule> {
|
||||
return {
|
||||
ngModule: UCapBrowserNativeModule,
|
||||
providers: [...SERVICES]
|
||||
};
|
||||
}
|
||||
}
|
|
@ -5,3 +5,5 @@
|
|||
export * from './lib/services/browser-native.service';
|
||||
|
||||
export * from './lib/translate/browser-loader';
|
||||
|
||||
export * from './lib/ucap-browser-native.module';
|
||||
|
|
|
@ -16,7 +16,11 @@ import {
|
|||
WindowStateChannel,
|
||||
IdleStateChannel
|
||||
} from '../types/channel.type';
|
||||
import { Injectable } from '@angular/core';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class ElectronNativeService implements NativeService {
|
||||
private windowStateChangedSubject: Subject<WindowState> | null = null;
|
||||
private windowStateChanged$: Observable<WindowState> | null = null;
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
import { TranslateLoader } from '@ngx-translate/core';
|
||||
import { Observable } from 'rxjs';
|
||||
import { NativeService } from '@ucap-webmessenger/native';
|
||||
import { NativeService, UCAP_NATIVE_SERVICE } from '@ucap-webmessenger/native';
|
||||
import { take, map } from 'rxjs/operators';
|
||||
import { Inject } from '@angular/core';
|
||||
|
||||
export class TranslateElectronLoader implements TranslateLoader {
|
||||
constructor(
|
||||
private nativeService: NativeService,
|
||||
@Inject(UCAP_NATIVE_SERVICE) private nativeService: NativeService,
|
||||
private prefix: string = '/assets/i18n/',
|
||||
private suffix: string = '.json'
|
||||
) {}
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
import { NgModule, ModuleWithProviders } from '@angular/core';
|
||||
|
||||
import { ElectronNativeService } from './services/electron-native.service';
|
||||
|
||||
const SERVICES = [ElectronNativeService];
|
||||
|
||||
@NgModule({
|
||||
declarations: [],
|
||||
imports: [],
|
||||
exports: []
|
||||
})
|
||||
export class UCapElectronNativeModule {
|
||||
public static forRoot(): ModuleWithProviders<UCapElectronNativeModule> {
|
||||
return {
|
||||
ngModule: UCapElectronNativeModule,
|
||||
providers: [...SERVICES]
|
||||
};
|
||||
}
|
||||
}
|
|
@ -7,3 +7,5 @@ export * from './lib/services/electron-native.service';
|
|||
export * from './lib/translate/electron-loader';
|
||||
|
||||
export * from './lib/types/channel.type';
|
||||
|
||||
export * from './lib/ucap-electron-native.module';
|
||||
|
|
|
@ -127,10 +127,13 @@
|
|||
"projects/ucap-webmessenger-util/src/public-api"
|
||||
],
|
||||
"@ucap-webmessenger/electron-core": [
|
||||
"projects/ucap-webmessenger-electron-core/src/public-api"
|
||||
"electron-projects/ucap-webmessenger-electron-core/src/public-api"
|
||||
],
|
||||
"@ucap-webmessenger/electron-notification": [
|
||||
"projects/ucap-webmessenger-electron-notification/src/public-api"
|
||||
"electron-projects/ucap-webmessenger-electron-notification/src/public-api"
|
||||
],
|
||||
"@ucap-webmessenger/electron": [
|
||||
"electron-projects/ucap-webmessenger-electron/src/public-api"
|
||||
]
|
||||
}
|
||||
},
|
||||
|
|