renderer update is implemented
This commit is contained in:
parent
bc037c6d52
commit
e84d47540d
@ -27,9 +27,9 @@
|
|||||||
"icon": "./dist/ucap-webmessenger-electron/resources/linuxicon"
|
"icon": "./dist/ucap-webmessenger-electron/resources/linuxicon"
|
||||||
},
|
},
|
||||||
"nsis": {
|
"nsis": {
|
||||||
"oneClick": false,
|
"oneClick": true,
|
||||||
"allowToChangeInstallationDirectory": true,
|
"allowToChangeInstallationDirectory": false,
|
||||||
"perMachine": true,
|
"perMachine": false,
|
||||||
"differentialPackage": true
|
"differentialPackage": true
|
||||||
},
|
},
|
||||||
"directories": {
|
"directories": {
|
||||||
|
@ -1,17 +1,6 @@
|
|||||||
import {
|
import { app, ipcMain, IpcMainEvent, Tray, Menu, shell } from 'electron';
|
||||||
app,
|
import path from 'path';
|
||||||
ipcMain,
|
import fse from 'fs-extra';
|
||||||
IpcMainEvent,
|
|
||||||
remote,
|
|
||||||
Tray,
|
|
||||||
Menu,
|
|
||||||
dialog,
|
|
||||||
shell
|
|
||||||
} 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 { AppWindow } from './app/AppWindow';
|
||||||
import { now } from './util/now';
|
import { now } from './util/now';
|
||||||
@ -32,12 +21,16 @@ import { DefaultFolder } from './lib/default-folder';
|
|||||||
import { FileUtil } from './lib/file-util';
|
import { FileUtil } from './lib/file-util';
|
||||||
|
|
||||||
import { IdleChecker } from './lib/idle-checker';
|
import { IdleChecker } from './lib/idle-checker';
|
||||||
import { NotificationRequest } from '@ucap-webmessenger/native';
|
import {
|
||||||
|
NotificationRequest,
|
||||||
|
UpdateCheckConfig
|
||||||
|
} from '@ucap-webmessenger/native';
|
||||||
import { ElectronAppChannel } from '@ucap-webmessenger/electron-core';
|
import { ElectronAppChannel } from '@ucap-webmessenger/electron-core';
|
||||||
|
import { RendererUpdater } from './lib/renderer-updater';
|
||||||
|
|
||||||
const appIconPath = __LINUX__
|
const appIconPath = __LINUX__
|
||||||
? path.join(__dirname, 'static', 'icon-logo.png')
|
? path.join(__dirname, 'static', 'icon-logo.png')
|
||||||
: path.join(__dirname, 'resources/image', 'ico_64_64.png');
|
: path.join(__dirname, 'resources/image', '64_64.png');
|
||||||
|
|
||||||
let appWindow: AppWindow | null = null;
|
let appWindow: AppWindow | null = null;
|
||||||
let appTray: Tray | null = null;
|
let appTray: Tray | null = null;
|
||||||
@ -85,6 +78,7 @@ let isDuplicateInstance = false;
|
|||||||
const gotSingleInstanceLock = app.requestSingleInstanceLock();
|
const gotSingleInstanceLock = app.requestSingleInstanceLock();
|
||||||
isDuplicateInstance = !gotSingleInstanceLock;
|
isDuplicateInstance = !gotSingleInstanceLock;
|
||||||
let idle: IdleChecker | null;
|
let idle: IdleChecker | null;
|
||||||
|
let rendererUpdater: RendererUpdater | undefined;
|
||||||
|
|
||||||
app.on(ElectronAppChannel.SecondInstance, (event, args, workingDirectory) => {
|
app.on(ElectronAppChannel.SecondInstance, (event, args, workingDirectory) => {
|
||||||
// Someone tried to run a second instance, we should focus our window.
|
// Someone tried to run a second instance, we should focus our window.
|
||||||
@ -280,6 +274,38 @@ ipcMain.on(UpdaterChannel.Check, (event: IpcMainEvent, ...args: any[]) => {
|
|||||||
event.returnValue = false;
|
event.returnValue = false;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
ipcMain.on(
|
||||||
|
UpdaterChannel.StartCheckInstant,
|
||||||
|
(event: IpcMainEvent, ...args: any[]) => {
|
||||||
|
const config = args[0] as UpdateCheckConfig;
|
||||||
|
if (!!rendererUpdater) {
|
||||||
|
rendererUpdater.stopCheck();
|
||||||
|
rendererUpdater = null;
|
||||||
|
}
|
||||||
|
rendererUpdater = new RendererUpdater(appWindow.browserWindow, config); // default 10min
|
||||||
|
rendererUpdater.startCheck();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
ipcMain.on(
|
||||||
|
UpdaterChannel.StopCheckInstant,
|
||||||
|
(event: IpcMainEvent, ...args: any[]) => {
|
||||||
|
if (!!rendererUpdater) {
|
||||||
|
rendererUpdater.stopCheck();
|
||||||
|
rendererUpdater = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
ipcMain.on(
|
||||||
|
UpdaterChannel.ApplyInstant,
|
||||||
|
(event: IpcMainEvent, ...args: any[]) => {
|
||||||
|
if (!!rendererUpdater) {
|
||||||
|
rendererUpdater.apply();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
ipcMain.on(FileChannel.ReadFile, (event: IpcMainEvent, ...args: any[]) => {
|
ipcMain.on(FileChannel.ReadFile, (event: IpcMainEvent, ...args: any[]) => {
|
||||||
try {
|
try {
|
||||||
fse.readFile(root(args[0]), (err, data) => {
|
fse.readFile(root(args[0]), (err, data) => {
|
||||||
|
@ -0,0 +1,122 @@
|
|||||||
|
import { interval, Subscription } from 'rxjs';
|
||||||
|
import {
|
||||||
|
UpdateCheckConfig,
|
||||||
|
UpdateInfo,
|
||||||
|
UpdateType
|
||||||
|
} from '@ucap-webmessenger/native';
|
||||||
|
import axios from 'axios';
|
||||||
|
import semver from 'semver';
|
||||||
|
import path from 'path';
|
||||||
|
import fse from 'fs-extra';
|
||||||
|
import zlib from 'zlib';
|
||||||
|
import { BrowserWindow, app } from 'electron';
|
||||||
|
import { UpdaterChannel } from '@ucap-webmessenger/native-electron';
|
||||||
|
import { startWith } from 'rxjs/operators';
|
||||||
|
|
||||||
|
export class RendererUpdater {
|
||||||
|
private checkSubscription: Subscription | undefined;
|
||||||
|
private readonly appPath: string;
|
||||||
|
private readonly downloadPath: string;
|
||||||
|
private readonly unzipPath: string;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private window: BrowserWindow,
|
||||||
|
private config: UpdateCheckConfig
|
||||||
|
) {
|
||||||
|
this.appPath = app.getAppPath() + '/';
|
||||||
|
const appPathFolder = this.appPath.slice(
|
||||||
|
0,
|
||||||
|
this.appPath.indexOf('app.asar')
|
||||||
|
);
|
||||||
|
|
||||||
|
this.downloadPath = path.resolve(appPathFolder, 'update.zip');
|
||||||
|
this.unzipPath = path.resolve(appPathFolder, '_app.asar');
|
||||||
|
}
|
||||||
|
|
||||||
|
startCheck() {
|
||||||
|
if (!semver.valid(this.config.currentVersion)) {
|
||||||
|
console.log(
|
||||||
|
`RendererUpdater::error currentVersion[${this.config.currentVersion}] is not valid`
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.checkSubscription = interval(this.config.intervalHour * 60 * 60 * 1000)
|
||||||
|
.pipe(startWith(0))
|
||||||
|
.subscribe(i => {
|
||||||
|
axios
|
||||||
|
.post(this.config.feed)
|
||||||
|
.then(res => {
|
||||||
|
const appVersion = res.data.appVersion;
|
||||||
|
if (!semver.valid(appVersion)) {
|
||||||
|
console.log(
|
||||||
|
`RendererUpdater::error appVersion[${appVersion}] is not valid`
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (semver.lt(this.config.currentVersion, appVersion)) {
|
||||||
|
this.download(appVersion, res.data.installUrl);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(reason => {
|
||||||
|
console.log('RendererUpdater', reason);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
stopCheck() {
|
||||||
|
if (!!this.checkSubscription) {
|
||||||
|
this.checkSubscription.unsubscribe();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
apply() {
|
||||||
|
const downloadStream = fse.createReadStream(this.downloadPath);
|
||||||
|
const unzipStream = fse.createWriteStream(this.unzipPath);
|
||||||
|
const unzip = zlib.createGunzip();
|
||||||
|
|
||||||
|
downloadStream
|
||||||
|
.pipe(unzip)
|
||||||
|
.pipe(unzipStream)
|
||||||
|
.end(chunk => {
|
||||||
|
try {
|
||||||
|
fse.unlinkSync(this.appPath.slice(0, -1));
|
||||||
|
} catch (error) {
|
||||||
|
console.log('RendererUpdater::apply', error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
fse.renameSync(this.unzipPath, this.appPath.slice(0, -1));
|
||||||
|
} catch (error) {
|
||||||
|
console.log('RendererUpdater::apply', error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
app.relaunch();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private download(appVersion: string, installUrl: string) {
|
||||||
|
axios
|
||||||
|
.get(installUrl, { responseType: 'blob' })
|
||||||
|
.then(res => {
|
||||||
|
fse.writeFile(this.downloadPath, res.data, err => {
|
||||||
|
if (!!err) {
|
||||||
|
console.log('RendererUpdater::download failed', err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const updateInfo: UpdateInfo = {
|
||||||
|
type: UpdateType.Differencial,
|
||||||
|
version: appVersion,
|
||||||
|
description: ''
|
||||||
|
};
|
||||||
|
this.window.webContents.send(UpdaterChannel.ExistInstant, updateInfo);
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch(reason => {
|
||||||
|
console.log('RendererUpdater::download failed', reason);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
51
package-lock.json
generated
51
package-lock.json
generated
@ -2270,6 +2270,15 @@
|
|||||||
"integrity": "sha512-/+CRPXpBDpo2RK9C68N3b2cOvO0Cf5B9aPijHsoDQTHivnGSObdOF2BRQOYjojWTDy6nQvMjmqRXIxH55VjxxA==",
|
"integrity": "sha512-/+CRPXpBDpo2RK9C68N3b2cOvO0Cf5B9aPijHsoDQTHivnGSObdOF2BRQOYjojWTDy6nQvMjmqRXIxH55VjxxA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"@types/axios": {
|
||||||
|
"version": "0.14.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/axios/-/axios-0.14.0.tgz",
|
||||||
|
"integrity": "sha1-7CMA++fX3d1+udOr+HmZlkyvzkY=",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"axios": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"@types/copy-webpack-plugin": {
|
"@types/copy-webpack-plugin": {
|
||||||
"version": "5.0.0",
|
"version": "5.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/@types/copy-webpack-plugin/-/copy-webpack-plugin-5.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/@types/copy-webpack-plugin/-/copy-webpack-plugin-5.0.0.tgz",
|
||||||
@ -3224,6 +3233,48 @@
|
|||||||
"integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==",
|
"integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"axios": {
|
||||||
|
"version": "0.19.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/axios/-/axios-0.19.0.tgz",
|
||||||
|
"integrity": "sha512-1uvKqKQta3KBxIz14F2v06AEHZ/dIoeKfbTRkK1E5oqjDnuEerLmYTgJB5AiQZHJcljpg1TuRzdjDR06qNk0DQ==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"follow-redirects": "1.5.10",
|
||||||
|
"is-buffer": "^2.0.2"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"debug": {
|
||||||
|
"version": "3.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
|
||||||
|
"integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"ms": "2.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"follow-redirects": {
|
||||||
|
"version": "1.5.10",
|
||||||
|
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.10.tgz",
|
||||||
|
"integrity": "sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"debug": "=3.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"is-buffer": {
|
||||||
|
"version": "2.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.4.tgz",
|
||||||
|
"integrity": "sha512-Kq1rokWXOPXWuaMAqZiJW4XxsmD9zGx9q4aePabbn3qCRGedtH7Cm+zV8WETitMfu1wdh+Rvd6w5egwSngUX2A==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"ms": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
|
||||||
|
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
|
||||||
|
"dev": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"axobject-query": {
|
"axobject-query": {
|
||||||
"version": "2.0.2",
|
"version": "2.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-2.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-2.0.2.tgz",
|
||||||
|
@ -53,6 +53,7 @@
|
|||||||
"@ngrx/store": "^8.4.0",
|
"@ngrx/store": "^8.4.0",
|
||||||
"@ngrx/store-devtools": "^8.4.0",
|
"@ngrx/store-devtools": "^8.4.0",
|
||||||
"@ngx-translate/core": "^11.0.1",
|
"@ngx-translate/core": "^11.0.1",
|
||||||
|
"@types/axios": "^0.14.0",
|
||||||
"@types/copy-webpack-plugin": "^5.0.0",
|
"@types/copy-webpack-plugin": "^5.0.0",
|
||||||
"@types/crypto-js": "^3.1.43",
|
"@types/crypto-js": "^3.1.43",
|
||||||
"@types/detect-browser": "^4.0.0",
|
"@types/detect-browser": "^4.0.0",
|
||||||
@ -71,6 +72,7 @@
|
|||||||
"@types/webpack-node-externals": "^1.6.3",
|
"@types/webpack-node-externals": "^1.6.3",
|
||||||
"angular-split": "^3.0.2",
|
"angular-split": "^3.0.2",
|
||||||
"autolinker": "^3.11.1",
|
"autolinker": "^3.11.1",
|
||||||
|
"axios": "^0.19.0",
|
||||||
"awesome-node-loader": "^1.1.1",
|
"awesome-node-loader": "^1.1.1",
|
||||||
"awesome-typescript-loader": "^5.2.1",
|
"awesome-typescript-loader": "^5.2.1",
|
||||||
"classlist.js": "^1.1.20150312",
|
"classlist.js": "^1.1.20150312",
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { Injectable, Inject } from '@angular/core';
|
import { Injectable, Inject } from '@angular/core';
|
||||||
import { HttpClient } from '@angular/common/http';
|
import { HttpClient, HttpRequest } from '@angular/common/http';
|
||||||
|
|
||||||
import { Observable } from 'rxjs';
|
import { Observable } from 'rxjs';
|
||||||
import { map } from 'rxjs/operators';
|
import { map } from 'rxjs/operators';
|
||||||
@ -8,13 +8,13 @@ import {
|
|||||||
VersionInfo2Request,
|
VersionInfo2Request,
|
||||||
VersionInfo2Response,
|
VersionInfo2Response,
|
||||||
encodeVersionInfo2,
|
encodeVersionInfo2,
|
||||||
decodeVersionInfo2,
|
decodeVersionInfo2
|
||||||
} from '../apis/version-info2';
|
} from '../apis/version-info2';
|
||||||
import {
|
import {
|
||||||
UpdateInfoRequest,
|
UpdateInfoRequest,
|
||||||
UpdateInfoResponse,
|
UpdateInfoResponse,
|
||||||
encodeUpdateInfo,
|
encodeUpdateInfo,
|
||||||
decodeUpdateInfo,
|
decodeUpdateInfo
|
||||||
} from '../apis/update-info';
|
} from '../apis/update-info';
|
||||||
|
|
||||||
import { _MODULE_CONFIG } from '../config/token';
|
import { _MODULE_CONFIG } from '../config/token';
|
||||||
@ -23,7 +23,7 @@ import { UrlConfig } from '@ucap-webmessenger/core';
|
|||||||
import { Urls } from '../config/urls';
|
import { Urls } from '../config/urls';
|
||||||
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: 'root',
|
providedIn: 'root'
|
||||||
})
|
})
|
||||||
export class PublicApiService {
|
export class PublicApiService {
|
||||||
readonly urls: Urls;
|
readonly urls: Urls;
|
||||||
@ -46,19 +46,32 @@ export class PublicApiService {
|
|||||||
this.urls.versionInfo2,
|
this.urls.versionInfo2,
|
||||||
{},
|
{},
|
||||||
{
|
{
|
||||||
params: encodeVersionInfo2(req),
|
params: encodeVersionInfo2(req)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
.pipe(map((res: any) => decodeVersionInfo2(res)));
|
.pipe(map((res: any) => decodeVersionInfo2(res)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public urlForVersionInfo2(req: VersionInfo2Request): string {
|
||||||
|
const httpReq = new HttpRequest(
|
||||||
|
'GET',
|
||||||
|
this.urls.versionInfo2,
|
||||||
|
{},
|
||||||
|
{
|
||||||
|
params: encodeVersionInfo2(req)
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
return httpReq.urlWithParams;
|
||||||
|
}
|
||||||
|
|
||||||
public updateInfo(req: UpdateInfoRequest): Observable<UpdateInfoResponse> {
|
public updateInfo(req: UpdateInfoRequest): Observable<UpdateInfoResponse> {
|
||||||
return this.httpClient
|
return this.httpClient
|
||||||
.post<any>(
|
.post<any>(
|
||||||
this.urls.updateInfo,
|
this.urls.updateInfo,
|
||||||
{},
|
{},
|
||||||
{
|
{
|
||||||
params: encodeUpdateInfo(req),
|
params: encodeUpdateInfo(req)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
.pipe(map(res => decodeUpdateInfo(res)));
|
.pipe(map(res => decodeUpdateInfo(res)));
|
||||||
|
@ -21,18 +21,6 @@ export function initializeApp(
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// export function nativeServiceFactory(httpClient: HttpClient) {
|
|
||||||
// if ('browser' === environment.runtime) {
|
|
||||||
// return import('@ucap-webmessenger/native-browser').then(
|
|
||||||
// m => new m.BrowserNativeService(httpClient)
|
|
||||||
// );
|
|
||||||
// } else {
|
|
||||||
// return import('@ucap-webmessenger/native-electron').then(
|
|
||||||
// m => new m.ElectronNativeService()
|
|
||||||
// );
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
imports: [],
|
imports: [],
|
||||||
exports: [],
|
exports: [],
|
||||||
@ -44,7 +32,7 @@ export function initializeApp(
|
|||||||
'browser' === environment.runtime
|
'browser' === environment.runtime
|
||||||
? BrowserNativeService
|
? BrowserNativeService
|
||||||
: ElectronNativeService,
|
: ElectronNativeService,
|
||||||
deps: [HttpClient],
|
deps: [HttpClient]
|
||||||
},
|
},
|
||||||
...SERVICES,
|
...SERVICES,
|
||||||
...RESOLVERS,
|
...RESOLVERS,
|
||||||
@ -52,8 +40,8 @@ export function initializeApp(
|
|||||||
provide: APP_INITIALIZER,
|
provide: APP_INITIALIZER,
|
||||||
useFactory: initializeApp,
|
useFactory: initializeApp,
|
||||||
deps: [AppService, UCAP_NATIVE_SERVICE],
|
deps: [AppService, UCAP_NATIVE_SERVICE],
|
||||||
multi: true,
|
multi: true
|
||||||
},
|
}
|
||||||
],
|
]
|
||||||
})
|
})
|
||||||
export class AppProviderModule {}
|
export class AppProviderModule {}
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
<div class="app-layout-native-title-bar-logo">
|
<div class="app-layout-native-title-bar-logo">
|
||||||
<img src="assets/images/logo/64_64.png" />
|
<img src="assets/images/logo/64_64.png" />
|
||||||
</div>
|
</div>
|
||||||
<div class="app-layout-native-title-bar-title">UCAP M Messenger</div>
|
<div class="app-layout-native-title-bar-title">UCAP M Messenger!!</div>
|
||||||
<div class="app-layout-native-title-bar-spacer"></div>
|
<div class="app-layout-native-title-bar-spacer"></div>
|
||||||
<div *ngIf="!!loginRes" class="app-layout-native-title-bar-link">
|
<div *ngIf="!!loginRes" class="app-layout-native-title-bar-link">
|
||||||
<button
|
<button
|
||||||
@ -32,6 +32,32 @@
|
|||||||
|
|
||||||
<span class="stroke-bar"></span>
|
<span class="stroke-bar"></span>
|
||||||
|
|
||||||
|
<button
|
||||||
|
*ngIf="updateInfo$ | async as updateInfo"
|
||||||
|
mat-icon-button
|
||||||
|
class="button app-layout-native-title-bar-setting"
|
||||||
|
matTooltip="업데이트"
|
||||||
|
(click)="onClickUpdate()"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="18"
|
||||||
|
height="18"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
stroke-width="1.5"
|
||||||
|
stroke-linecap="butt"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
alt="업데이트"
|
||||||
|
>
|
||||||
|
<circle cx="12" cy="12" r="3"></circle>
|
||||||
|
<path
|
||||||
|
d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z"
|
||||||
|
></path>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
|
||||||
<button
|
<button
|
||||||
mat-icon-button
|
mat-icon-button
|
||||||
class="button app-layout-native-title-bar-setting"
|
class="button app-layout-native-title-bar-setting"
|
||||||
|
@ -2,7 +2,8 @@ import { Component, OnInit, Inject, OnDestroy, ViewChild } from '@angular/core';
|
|||||||
import {
|
import {
|
||||||
UCAP_NATIVE_SERVICE,
|
UCAP_NATIVE_SERVICE,
|
||||||
NativeService,
|
NativeService,
|
||||||
WindowState
|
WindowState,
|
||||||
|
UpdateInfo
|
||||||
} from '@ucap-webmessenger/native';
|
} from '@ucap-webmessenger/native';
|
||||||
import { Observable, Subscription } from 'rxjs';
|
import { Observable, Subscription } from 'rxjs';
|
||||||
import { Store, select } from '@ngrx/store';
|
import { Store, select } from '@ngrx/store';
|
||||||
@ -11,6 +12,7 @@ import * as AppStore from '@app/store';
|
|||||||
import * as ChatStore from '@app/store/messenger/chat';
|
import * as ChatStore from '@app/store/messenger/chat';
|
||||||
import * as AuthenticationStore from '@app/store/account/authentication';
|
import * as AuthenticationStore from '@app/store/account/authentication';
|
||||||
import * as SettingsStore from '@app/store/messenger/settings';
|
import * as SettingsStore from '@app/store/messenger/settings';
|
||||||
|
import * as UpdateStore from '@app/store/setting/update';
|
||||||
|
|
||||||
import { LoginResponse } from '@ucap-webmessenger/protocol-authentication';
|
import { LoginResponse } from '@ucap-webmessenger/protocol-authentication';
|
||||||
import { tap } from 'rxjs/operators';
|
import { tap } from 'rxjs/operators';
|
||||||
@ -23,11 +25,13 @@ import { RightDrawer } from '@app/types';
|
|||||||
})
|
})
|
||||||
export class TopBarComponent implements OnInit, OnDestroy {
|
export class TopBarComponent implements OnInit, OnDestroy {
|
||||||
windowStateChanged$: Observable<WindowState>;
|
windowStateChanged$: Observable<WindowState>;
|
||||||
|
|
||||||
WindowState = WindowState;
|
WindowState = WindowState;
|
||||||
|
|
||||||
loginRes: LoginResponse;
|
loginRes: LoginResponse;
|
||||||
loginResSubscription: Subscription;
|
loginResSubscription: Subscription;
|
||||||
|
|
||||||
|
updateInfo$: Observable<UpdateInfo>;
|
||||||
|
|
||||||
showWeblink = false;
|
showWeblink = false;
|
||||||
weblink: {
|
weblink: {
|
||||||
title: string;
|
title: string;
|
||||||
@ -159,6 +163,10 @@ export class TopBarComponent implements OnInit, OnDestroy {
|
|||||||
})
|
})
|
||||||
)
|
)
|
||||||
.subscribe();
|
.subscribe();
|
||||||
|
|
||||||
|
this.updateInfo$ = this.store.pipe(
|
||||||
|
select(AppStore.SettingSelector.UpdateSelector.updateInfo)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnDestroy(): void {}
|
ngOnDestroy(): void {}
|
||||||
@ -194,4 +202,8 @@ export class TopBarComponent implements OnInit, OnDestroy {
|
|||||||
onToggleWebLinkSelector(): void {
|
onToggleWebLinkSelector(): void {
|
||||||
this.showWeblink = !this.showWeblink;
|
this.showWeblink = !this.showWeblink;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onClickUpdate() {
|
||||||
|
this.store.dispatch(UpdateStore.applyInstantUpdate());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -52,6 +52,7 @@ import { KEY_LOGIN_RES_INFO } from '@app/types/login-res-info.type';
|
|||||||
|
|
||||||
import { environment } from '../../environments/environment';
|
import { environment } from '../../environments/environment';
|
||||||
import { SnackBarService } from '@ucap-webmessenger/ui';
|
import { SnackBarService } from '@ucap-webmessenger/ui';
|
||||||
|
import { AppNativeService } from '@app/services/native.service';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class AppMessengerResolver implements Resolve<void> {
|
export class AppMessengerResolver implements Resolve<void> {
|
||||||
@ -64,6 +65,7 @@ export class AppMessengerResolver implements Resolve<void> {
|
|||||||
private optionProtocolService: OptionProtocolService,
|
private optionProtocolService: OptionProtocolService,
|
||||||
private authenticationProtocolService: AuthenticationProtocolService,
|
private authenticationProtocolService: AuthenticationProtocolService,
|
||||||
private innerProtocolService: InnerProtocolService,
|
private innerProtocolService: InnerProtocolService,
|
||||||
|
private appNativeService: AppNativeService,
|
||||||
private snackBarService: SnackBarService,
|
private snackBarService: SnackBarService,
|
||||||
private logger: NGXLogger
|
private logger: NGXLogger
|
||||||
) {}
|
) {}
|
||||||
@ -205,6 +207,7 @@ export class AppMessengerResolver implements Resolve<void> {
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
this.store.dispatch(AuthenticationStore.postLogin({ loginRes }));
|
this.store.dispatch(AuthenticationStore.postLogin({ loginRes }));
|
||||||
|
this.appNativeService.subscribeAfterLogin();
|
||||||
resolve();
|
resolve();
|
||||||
},
|
},
|
||||||
err => {
|
err => {
|
||||||
|
@ -1,10 +1,25 @@
|
|||||||
import { Injectable, Inject } from '@angular/core';
|
import { Injectable, Inject } from '@angular/core';
|
||||||
import { UCAP_NATIVE_SERVICE, NativeService } from '@ucap-webmessenger/native';
|
import { DOCUMENT } from '@angular/common';
|
||||||
|
import {
|
||||||
|
UCAP_NATIVE_SERVICE,
|
||||||
|
NativeService,
|
||||||
|
UpdateCheckConfig
|
||||||
|
} from '@ucap-webmessenger/native';
|
||||||
import { Store } from '@ngrx/store';
|
import { Store } from '@ngrx/store';
|
||||||
import { NGXLogger } from 'ngx-logger';
|
import { NGXLogger } from 'ngx-logger';
|
||||||
|
|
||||||
import * as AuthenticationStore from '@app/store/account/authentication';
|
import * as AuthenticationStore from '@app/store/account/authentication';
|
||||||
import * as SettingsStore from '@app/store/messenger/settings';
|
import * as SettingsStore from '@app/store/messenger/settings';
|
||||||
|
import * as UpdateStore from '@app/store/setting/update';
|
||||||
|
import { PublicApiService } from '@ucap-webmessenger/api-public';
|
||||||
|
import { SessionStorageService } from '@ucap-webmessenger/web-storage';
|
||||||
|
import {
|
||||||
|
LoginInfo,
|
||||||
|
KEY_LOGIN_INFO,
|
||||||
|
EnvironmentsInfo,
|
||||||
|
KEY_ENVIRONMENTS_INFO
|
||||||
|
} from '@app/types';
|
||||||
|
import { environment } from '../../environments/environment';
|
||||||
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: 'root'
|
providedIn: 'root'
|
||||||
@ -12,6 +27,9 @@ import * as SettingsStore from '@app/store/messenger/settings';
|
|||||||
export class AppNativeService {
|
export class AppNativeService {
|
||||||
constructor(
|
constructor(
|
||||||
@Inject(UCAP_NATIVE_SERVICE) private nativeService: NativeService,
|
@Inject(UCAP_NATIVE_SERVICE) private nativeService: NativeService,
|
||||||
|
private publicApiService: PublicApiService,
|
||||||
|
private sessionStorageService: SessionStorageService,
|
||||||
|
@Inject(DOCUMENT) private document: Document,
|
||||||
private store: Store<any>,
|
private store: Store<any>,
|
||||||
private logger: NGXLogger
|
private logger: NGXLogger
|
||||||
) {}
|
) {}
|
||||||
@ -25,4 +43,32 @@ export class AppNativeService {
|
|||||||
this.store.dispatch(SettingsStore.showDialog());
|
this.store.dispatch(SettingsStore.showDialog());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
subscribeAfterLogin(): void {
|
||||||
|
const loginInfo = this.sessionStorageService.get<LoginInfo>(KEY_LOGIN_INFO);
|
||||||
|
const environmentsInfo = this.sessionStorageService.get<EnvironmentsInfo>(
|
||||||
|
KEY_ENVIRONMENTS_INFO
|
||||||
|
);
|
||||||
|
|
||||||
|
const els = this.document.getElementsByTagName('app-root');
|
||||||
|
|
||||||
|
const currentVersion = els.item(0).getAttribute('app-version');
|
||||||
|
|
||||||
|
const updateCheckConfig: UpdateCheckConfig = {
|
||||||
|
feed: this.publicApiService.urlForVersionInfo2({
|
||||||
|
deviceType: environment.productConfig.updateCheckConfig.deviceType,
|
||||||
|
companyGroupType: loginInfo.companyGroupType,
|
||||||
|
companyCode: loginInfo.companyCode,
|
||||||
|
loginId: loginInfo.loginId
|
||||||
|
}),
|
||||||
|
currentVersion,
|
||||||
|
intervalHour: environment.productConfig.updateCheckConfig.intervalHour
|
||||||
|
};
|
||||||
|
|
||||||
|
this.nativeService
|
||||||
|
.checkForInstantUpdates(updateCheckConfig)
|
||||||
|
.subscribe(updateInfo => {
|
||||||
|
this.store.dispatch(UpdateStore.existInstantUpdate({ updateInfo }));
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,46 +4,44 @@ import { Action, combineReducers, Selector, createSelector } from '@ngrx/store';
|
|||||||
import * as CompanyStore from './company';
|
import * as CompanyStore from './company';
|
||||||
import * as InitStore from './init';
|
import * as InitStore from './init';
|
||||||
import * as VersionInfoStore from './version-info';
|
import * as VersionInfoStore from './version-info';
|
||||||
|
import * as UpdateStore from './update';
|
||||||
|
|
||||||
export interface State {
|
export interface State {
|
||||||
company: CompanyStore.State;
|
company: CompanyStore.State;
|
||||||
init: InitStore.State;
|
init: InitStore.State;
|
||||||
versionInfo: VersionInfoStore.State;
|
versionInfo: VersionInfoStore.State;
|
||||||
|
update: UpdateStore.State;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const effects: Type<any>[] = [
|
export const effects: Type<any>[] = [
|
||||||
CompanyStore.Effects,
|
CompanyStore.Effects,
|
||||||
InitStore.Effects,
|
InitStore.Effects,
|
||||||
VersionInfoStore.Effects
|
VersionInfoStore.Effects,
|
||||||
|
UpdateStore.Effects
|
||||||
];
|
];
|
||||||
|
|
||||||
export function reducers(state: State | undefined, action: Action) {
|
export function reducers(state: State | undefined, action: Action) {
|
||||||
return combineReducers({
|
return combineReducers({
|
||||||
company: CompanyStore.reducer,
|
company: CompanyStore.reducer,
|
||||||
init: InitStore.reducer,
|
init: InitStore.reducer,
|
||||||
versionInfo: VersionInfoStore.reducer
|
versionInfo: VersionInfoStore.reducer,
|
||||||
|
update: UpdateStore.reducer
|
||||||
})(state, action);
|
})(state, action);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function selectors<S>(selector: Selector<any, State>) {
|
export function selectors<S>(selector: Selector<any, State>) {
|
||||||
return {
|
return {
|
||||||
CompanySelector: CompanyStore.selectors(
|
CompanySelector: CompanyStore.selectors(
|
||||||
createSelector(
|
createSelector(selector, (state: State) => state.company)
|
||||||
selector,
|
|
||||||
(state: State) => state.company
|
|
||||||
)
|
|
||||||
),
|
),
|
||||||
InitSelector: InitStore.selectors(
|
InitSelector: InitStore.selectors(
|
||||||
createSelector(
|
createSelector(selector, (state: State) => state.init)
|
||||||
selector,
|
|
||||||
(state: State) => state.init
|
|
||||||
)
|
|
||||||
),
|
),
|
||||||
VersionInfoSelector: VersionInfoStore.selectors(
|
VersionInfoSelector: VersionInfoStore.selectors(
|
||||||
createSelector(
|
createSelector(selector, (state: State) => state.versionInfo)
|
||||||
selector,
|
),
|
||||||
(state: State) => state.versionInfo
|
UpdateSelector: UpdateStore.selectors(
|
||||||
)
|
createSelector(selector, (state: State) => state.update)
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,11 @@
|
|||||||
|
import { createAction, props } from '@ngrx/store';
|
||||||
|
import { UpdateInfo } from '@ucap-webmessenger/native';
|
||||||
|
|
||||||
|
export const existInstantUpdate = createAction(
|
||||||
|
'[Setting::Update] existInstantUpdate',
|
||||||
|
props<{ updateInfo: UpdateInfo }>()
|
||||||
|
);
|
||||||
|
|
||||||
|
export const applyInstantUpdate = createAction(
|
||||||
|
'[Setting::Update] applyInstantUpdate'
|
||||||
|
);
|
@ -0,0 +1,25 @@
|
|||||||
|
import { Injectable, Inject } from '@angular/core';
|
||||||
|
import { createEffect, Actions, ofType } from '@ngrx/effects';
|
||||||
|
import { applyInstantUpdate } from './actions';
|
||||||
|
import { UCAP_NATIVE_SERVICE, NativeService } from '@ucap-webmessenger/native';
|
||||||
|
import { tap } from 'rxjs/operators';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class Effects {
|
||||||
|
applyInstantUpdate$ = createEffect(
|
||||||
|
() => {
|
||||||
|
return this.actions$.pipe(
|
||||||
|
ofType(applyInstantUpdate),
|
||||||
|
tap(() => {
|
||||||
|
this.nativeService.applyInstantUpdates();
|
||||||
|
})
|
||||||
|
);
|
||||||
|
},
|
||||||
|
{ dispatch: false }
|
||||||
|
);
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private actions$: Actions,
|
||||||
|
@Inject(UCAP_NATIVE_SERVICE) private nativeService: NativeService
|
||||||
|
) {}
|
||||||
|
}
|
@ -0,0 +1,4 @@
|
|||||||
|
export * from './actions';
|
||||||
|
export * from './effects';
|
||||||
|
export * from './reducers';
|
||||||
|
export * from './state';
|
@ -0,0 +1,13 @@
|
|||||||
|
import { createReducer, on } from '@ngrx/store';
|
||||||
|
import { initialState } from './state';
|
||||||
|
import { existInstantUpdate } from './actions';
|
||||||
|
|
||||||
|
export const reducer = createReducer(
|
||||||
|
initialState,
|
||||||
|
on(existInstantUpdate, (state, action) => {
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
updateInfo: action.updateInfo
|
||||||
|
};
|
||||||
|
})
|
||||||
|
);
|
@ -0,0 +1,16 @@
|
|||||||
|
import { Selector, createSelector } from '@ngrx/store';
|
||||||
|
import { UpdateInfo } from '@ucap-webmessenger/native';
|
||||||
|
|
||||||
|
export interface State {
|
||||||
|
updateInfo: UpdateInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const initialState: State = {
|
||||||
|
updateInfo: null
|
||||||
|
};
|
||||||
|
|
||||||
|
export function selectors<S>(selector: Selector<any, State>) {
|
||||||
|
return {
|
||||||
|
updateInfo: createSelector(selector, (state: State) => state.updateInfo)
|
||||||
|
};
|
||||||
|
}
|
@ -8,6 +8,7 @@ import {
|
|||||||
protocolUrls,
|
protocolUrls,
|
||||||
messageApiUrls
|
messageApiUrls
|
||||||
} from './environment.type';
|
} from './environment.type';
|
||||||
|
import { DeviceType } from '@ucap-webmessenger/core';
|
||||||
|
|
||||||
export const environment: Environment = {
|
export const environment: Environment = {
|
||||||
production: false,
|
production: false,
|
||||||
@ -22,6 +23,10 @@ export const environment: Environment = {
|
|||||||
productName: 'EZMessenger',
|
productName: 'EZMessenger',
|
||||||
authentication: {
|
authentication: {
|
||||||
usePrivateInformationAgree: false
|
usePrivateInformationAgree: false
|
||||||
|
},
|
||||||
|
updateCheckConfig: {
|
||||||
|
deviceType: DeviceType.Renderer,
|
||||||
|
intervalHour: 1
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -8,6 +8,7 @@ import {
|
|||||||
protocolUrls,
|
protocolUrls,
|
||||||
messageApiUrls
|
messageApiUrls
|
||||||
} from './environment.type';
|
} from './environment.type';
|
||||||
|
import { DeviceType } from '@ucap-webmessenger/core';
|
||||||
|
|
||||||
export const environment: Environment = {
|
export const environment: Environment = {
|
||||||
production: true,
|
production: true,
|
||||||
@ -22,6 +23,10 @@ export const environment: Environment = {
|
|||||||
productName: 'EZMessenger',
|
productName: 'EZMessenger',
|
||||||
authentication: {
|
authentication: {
|
||||||
usePrivateInformationAgree: false
|
usePrivateInformationAgree: false
|
||||||
|
},
|
||||||
|
updateCheckConfig: {
|
||||||
|
deviceType: DeviceType.Renderer,
|
||||||
|
intervalHour: 1
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -22,7 +22,11 @@ import {
|
|||||||
ModuleConfig as ProtocolModuleConfig,
|
ModuleConfig as ProtocolModuleConfig,
|
||||||
Urls as ProtocolUrls
|
Urls as ProtocolUrls
|
||||||
} from '@ucap-webmessenger/protocol';
|
} from '@ucap-webmessenger/protocol';
|
||||||
import { ModuleConfig as NativeModuleConfig } from '@ucap-webmessenger/native';
|
import {
|
||||||
|
ModuleConfig as NativeModuleConfig,
|
||||||
|
UpdateCheckConfig
|
||||||
|
} from '@ucap-webmessenger/native';
|
||||||
|
import { DeviceType } from '@ucap-webmessenger/core';
|
||||||
|
|
||||||
export type UCapRuntime = 'browser' | 'electron';
|
export type UCapRuntime = 'browser' | 'electron';
|
||||||
|
|
||||||
@ -41,6 +45,10 @@ export interface Environment {
|
|||||||
authentication: {
|
authentication: {
|
||||||
usePrivateInformationAgree: boolean;
|
usePrivateInformationAgree: boolean;
|
||||||
};
|
};
|
||||||
|
updateCheckConfig: {
|
||||||
|
deviceType: DeviceType;
|
||||||
|
intervalHour: number;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
commonApiModuleConfig: CommonApiModuleConfig;
|
commonApiModuleConfig: CommonApiModuleConfig;
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
<link href="assets/scss/partials/splash.css" rel="stylesheet" />
|
<link href="assets/scss/partials/splash.css" rel="stylesheet" />
|
||||||
</head>
|
</head>
|
||||||
<body class="theme-default">
|
<body class="theme-default">
|
||||||
<app-root></app-root>
|
<app-root app-version="0.0.1"></app-root>
|
||||||
|
|
||||||
<div class="wrapper-splash" id="splash-screen">
|
<div class="wrapper-splash" id="splash-screen">
|
||||||
<svg
|
<svg
|
||||||
|
@ -5,5 +5,6 @@ export enum DeviceType {
|
|||||||
iOS = 'I',
|
iOS = 'I',
|
||||||
iOSCall = 'O',
|
iOSCall = 'O',
|
||||||
PC = 'P',
|
PC = 'P',
|
||||||
iMessenger = 'H'
|
iMessenger = 'H',
|
||||||
|
Renderer = 'R'
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,9 @@ import {
|
|||||||
NativeService,
|
NativeService,
|
||||||
WindowState,
|
WindowState,
|
||||||
NotificationRequest,
|
NotificationRequest,
|
||||||
WindowIdle
|
WindowIdle,
|
||||||
|
UpdateInfo,
|
||||||
|
UpdateCheckConfig
|
||||||
} from '@ucap-webmessenger/native';
|
} from '@ucap-webmessenger/native';
|
||||||
import { HttpClient } from '@angular/common/http';
|
import { HttpClient } from '@angular/common/http';
|
||||||
import { map, share } from 'rxjs/operators';
|
import { map, share } from 'rxjs/operators';
|
||||||
@ -74,6 +76,19 @@ export class BrowserNativeService extends NativeService {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
checkForInstantUpdates(config: UpdateCheckConfig): Observable<UpdateInfo> {
|
||||||
|
return new Observable<UpdateInfo>(subscriber => {
|
||||||
|
try {
|
||||||
|
} catch (error) {
|
||||||
|
subscriber.error(error);
|
||||||
|
} finally {
|
||||||
|
subscriber.complete();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
applyInstantUpdates(): void {}
|
||||||
|
|
||||||
showImageViewer(): void {}
|
showImageViewer(): void {}
|
||||||
|
|
||||||
readFile(path: string): Promise<Buffer> {
|
readFile(path: string): Promise<Buffer> {
|
||||||
|
@ -6,7 +6,9 @@ import {
|
|||||||
NativeService,
|
NativeService,
|
||||||
WindowState,
|
WindowState,
|
||||||
NotificationRequest,
|
NotificationRequest,
|
||||||
WindowIdle
|
WindowIdle,
|
||||||
|
UpdateInfo,
|
||||||
|
UpdateCheckConfig
|
||||||
} from '@ucap-webmessenger/native';
|
} from '@ucap-webmessenger/native';
|
||||||
import { share } from 'rxjs/operators';
|
import { share } from 'rxjs/operators';
|
||||||
import {
|
import {
|
||||||
@ -49,6 +51,9 @@ export class ElectronNativeService implements NativeService {
|
|||||||
private chatOpenRoomSubject: Subject<string> | null = null;
|
private chatOpenRoomSubject: Subject<string> | null = null;
|
||||||
private chatOpenRoom$: Observable<string> | null = null;
|
private chatOpenRoom$: Observable<string> | null = null;
|
||||||
|
|
||||||
|
private backgroundCheckForUpdatesSubject: Subject<UpdateInfo> | null = null;
|
||||||
|
private backgroundCheckForUpdates$: Observable<UpdateInfo> | null = null;
|
||||||
|
|
||||||
postAppInit(): void {}
|
postAppInit(): void {}
|
||||||
|
|
||||||
logout(): Observable<void> {
|
logout(): Observable<void> {
|
||||||
@ -110,6 +115,29 @@ export class ElectronNativeService implements NativeService {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
checkForInstantUpdates(config: UpdateCheckConfig): Observable<UpdateInfo> {
|
||||||
|
if (!this.backgroundCheckForUpdatesSubject) {
|
||||||
|
this.backgroundCheckForUpdatesSubject = new Subject<UpdateInfo>();
|
||||||
|
this.backgroundCheckForUpdates$ = this.backgroundCheckForUpdatesSubject
|
||||||
|
.asObservable()
|
||||||
|
.pipe(share());
|
||||||
|
}
|
||||||
|
|
||||||
|
this.ipcRenderer.send(UpdaterChannel.StartCheckInstant, config);
|
||||||
|
|
||||||
|
this.ipcRenderer.on(
|
||||||
|
UpdaterChannel.ExistInstant,
|
||||||
|
(event: any, updateInfo: UpdateInfo) => {
|
||||||
|
this.backgroundCheckForUpdatesSubject.next(updateInfo);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
return this.backgroundCheckForUpdates$;
|
||||||
|
}
|
||||||
|
|
||||||
|
applyInstantUpdates(): void {
|
||||||
|
this.ipcRenderer.send(UpdaterChannel.ApplyInstant);
|
||||||
|
}
|
||||||
|
|
||||||
showImageViewer(): void {
|
showImageViewer(): void {
|
||||||
this.ipcRenderer.send(FileChannel.ShowImageViewer);
|
this.ipcRenderer.send(FileChannel.ShowImageViewer);
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,11 @@ export enum NotificationChannel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export enum UpdaterChannel {
|
export enum UpdaterChannel {
|
||||||
Check = 'UCAP::updater::check'
|
Check = 'UCAP::updater::check',
|
||||||
|
StartCheckInstant = 'UCAP::updater::startCheckInstant',
|
||||||
|
ExistInstant = 'UCAP::updater::existInstant',
|
||||||
|
ApplyInstant = 'UCAP::updater::applyInstant',
|
||||||
|
StopCheckInstant = 'UCAP::updater::stopCheckInstant'
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum FileChannel {
|
export enum FileChannel {
|
||||||
|
@ -0,0 +1,16 @@
|
|||||||
|
export enum UpdateType {
|
||||||
|
Full = 'Full',
|
||||||
|
Differencial = 'Differencial'
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface UpdateInfo {
|
||||||
|
type: UpdateType;
|
||||||
|
version: string;
|
||||||
|
description: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface UpdateCheckConfig {
|
||||||
|
feed: string;
|
||||||
|
currentVersion: string;
|
||||||
|
intervalHour: number;
|
||||||
|
}
|
@ -5,6 +5,7 @@ import { WindowIdle } from '../types/window-idle.type';
|
|||||||
import { NotificationRequest } from '../models/notification';
|
import { NotificationRequest } from '../models/notification';
|
||||||
import { TranslateLoader } from '@ngx-translate/core';
|
import { TranslateLoader } from '@ngx-translate/core';
|
||||||
import { StatusCode } from '@ucap-webmessenger/core';
|
import { StatusCode } from '@ucap-webmessenger/core';
|
||||||
|
import { UpdateInfo, UpdateCheckConfig } from '../models/update-info';
|
||||||
|
|
||||||
export abstract class NativeService {
|
export abstract class NativeService {
|
||||||
abstract postAppInit(): void;
|
abstract postAppInit(): void;
|
||||||
@ -17,6 +18,10 @@ export abstract class NativeService {
|
|||||||
abstract closeAllNotify(): void;
|
abstract closeAllNotify(): void;
|
||||||
|
|
||||||
abstract checkForUpdates(): Promise<boolean>;
|
abstract checkForUpdates(): Promise<boolean>;
|
||||||
|
abstract checkForInstantUpdates(
|
||||||
|
config: UpdateCheckConfig
|
||||||
|
): Observable<UpdateInfo>;
|
||||||
|
abstract applyInstantUpdates(): void;
|
||||||
|
|
||||||
abstract showImageViewer(): void;
|
abstract showImageViewer(): void;
|
||||||
|
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
export * from './lib/types/token';
|
export * from './lib/types/token';
|
||||||
|
|
||||||
export * from './lib/models/notification';
|
export * from './lib/models/notification';
|
||||||
|
export * from './lib/models/update-info';
|
||||||
|
|
||||||
export * from './lib/services/native.service';
|
export * from './lib/services/native.service';
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user