Merge branch 'master' of http://10.81.13.221:6990/Web/next-ucap-messenger
This commit is contained in:
commit
c52cda0e46
|
@ -6,13 +6,17 @@ import windowStateKeeper from 'electron-window-state';
|
||||||
import { EventEmitter } from 'events';
|
import { EventEmitter } from 'events';
|
||||||
|
|
||||||
import { now } from '../util/now';
|
import { now } from '../util/now';
|
||||||
|
import { Channel } from '@ucap-webmessenger/native-electron';
|
||||||
|
import { registerWindowStateChangedEvents } from '../lib/window-state';
|
||||||
|
|
||||||
export class AppWindow {
|
export class AppWindow {
|
||||||
private window: BrowserWindow | null = null;
|
private window: BrowserWindow | null = null;
|
||||||
|
|
||||||
private eventEmitter = new EventEmitter();
|
private eventEmitter = new EventEmitter();
|
||||||
|
|
||||||
|
// tslint:disable-next-line: variable-name
|
||||||
private _loadTime: number | null = null;
|
private _loadTime: number | null = null;
|
||||||
|
// tslint:disable-next-line: variable-name
|
||||||
private _rendererReadyTime: number | null = null;
|
private _rendererReadyTime: number | null = null;
|
||||||
|
|
||||||
private minWidth = 960;
|
private minWidth = 960;
|
||||||
|
@ -32,8 +36,6 @@ export class AppWindow {
|
||||||
minWidth: this.minWidth,
|
minWidth: this.minWidth,
|
||||||
minHeight: this.minHeight,
|
minHeight: this.minHeight,
|
||||||
center: true,
|
center: true,
|
||||||
autoHideMenuBar: true,
|
|
||||||
title: 'UCAP M Messenger',
|
|
||||||
// This fixes subpixel aliasing on Windows
|
// This fixes subpixel aliasing on Windows
|
||||||
// See https://github.com/atom/atom/commit/683bef5b9d133cb194b476938c77cc07fd05b972
|
// See https://github.com/atom/atom/commit/683bef5b9d133cb194b476938c77cc07fd05b972
|
||||||
backgroundColor: '#fff',
|
backgroundColor: '#fff',
|
||||||
|
@ -52,7 +54,7 @@ export class AppWindow {
|
||||||
if (__DARWIN__) {
|
if (__DARWIN__) {
|
||||||
windowOptions.titleBarStyle = 'hidden';
|
windowOptions.titleBarStyle = 'hidden';
|
||||||
} else if (__WIN32__) {
|
} else if (__WIN32__) {
|
||||||
// windowOptions.frame = false;
|
windowOptions.frame = false;
|
||||||
} else if (__LINUX__) {
|
} else if (__LINUX__) {
|
||||||
windowOptions.icon = path.join(__dirname, 'static', 'icon-logo.png');
|
windowOptions.icon = path.join(__dirname, 'static', 'icon-logo.png');
|
||||||
}
|
}
|
||||||
|
@ -108,22 +110,6 @@ export class AppWindow {
|
||||||
public load(): void {
|
public load(): void {
|
||||||
let startLoad = 0;
|
let startLoad = 0;
|
||||||
|
|
||||||
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
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.window.webContents.once('did-start-loading', () => {
|
this.window.webContents.once('did-start-loading', () => {
|
||||||
this._rendererReadyTime = null;
|
this._rendererReadyTime = null;
|
||||||
this._loadTime = null;
|
this._loadTime = null;
|
||||||
|
@ -147,6 +133,24 @@ export class AppWindow {
|
||||||
this.window.webContents.openDevTools();
|
this.window.webContents.openDevTools();
|
||||||
this.window.show();
|
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? */
|
/** Is the page loaded and has the renderer signalled it's ready? */
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { app, ipcMain, IpcMainEvent } from 'electron';
|
import { app, ipcMain, IpcMainEvent, remote } from 'electron';
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
import * as url from 'url';
|
import * as url from 'url';
|
||||||
import * as fse from 'fs-extra';
|
import * as fse from 'fs-extra';
|
||||||
|
|
49
main/src/lib/window-state.ts
Normal file
49
main/src/lib/window-state.ts
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
import { BrowserWindow } from 'electron';
|
||||||
|
import { WindowState } from '@ucap-webmessenger/native';
|
||||||
|
import { Channel } from '@ucap-webmessenger/native-electron';
|
||||||
|
|
||||||
|
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('enter-full-screen', () =>
|
||||||
|
sendWindowStateEvent(window, WindowState.FullScreen)
|
||||||
|
);
|
||||||
|
|
||||||
|
window.on('leave-full-screen', () =>
|
||||||
|
sendWindowStateEvent(window, WindowState.Normal)
|
||||||
|
);
|
||||||
|
|
||||||
|
window.on('maximize', () =>
|
||||||
|
sendWindowStateEvent(window, WindowState.Maximized)
|
||||||
|
);
|
||||||
|
window.on('minimize', () =>
|
||||||
|
sendWindowStateEvent(window, WindowState.Minimized)
|
||||||
|
);
|
||||||
|
window.on('unmaximize', () =>
|
||||||
|
sendWindowStateEvent(window, WindowState.Normal)
|
||||||
|
);
|
||||||
|
window.on('restore', () => sendWindowStateEvent(window, WindowState.Normal));
|
||||||
|
window.on('hide', () => sendWindowStateEvent(window, WindowState.Hidden));
|
||||||
|
window.on('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(Channel.windowStateChanged, windowState);
|
||||||
|
}
|
1121
package-lock.json
generated
1121
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
35
package.json
35
package.json
|
@ -20,23 +20,23 @@
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@angular-builders/custom-webpack": "^8.2.0",
|
"@angular-builders/custom-webpack": "^8.2.0",
|
||||||
"@angular-devkit/build-angular": "~0.803.2",
|
"@angular-devkit/build-angular": "~0.803.14",
|
||||||
"@angular-devkit/build-ng-packagr": "~0.803.2",
|
"@angular-devkit/build-ng-packagr": "~0.803.14",
|
||||||
"@angular/animations": "^8.2.11",
|
"@angular/animations": "^8.2.12",
|
||||||
"@angular/cdk": "^8.2.3",
|
"@angular/cdk": "^8.2.3",
|
||||||
"@angular/cli": "~8.3.2",
|
"@angular/cli": "~8.3.14",
|
||||||
"@angular/common": "~8.2.4",
|
"@angular/common": "~8.2.12",
|
||||||
"@angular/compiler": "~8.2.4",
|
"@angular/compiler": "~8.2.12",
|
||||||
"@angular/compiler-cli": "~8.2.4",
|
"@angular/compiler-cli": "~8.2.12",
|
||||||
"@angular/core": "~8.2.4",
|
"@angular/core": "~8.2.12",
|
||||||
"@angular/flex-layout": "^8.0.0-beta.27",
|
"@angular/flex-layout": "^8.0.0-beta.27",
|
||||||
"@angular/forms": "~8.2.4",
|
"@angular/forms": "~8.2.12",
|
||||||
"@angular/language-service": "~8.2.4",
|
"@angular/language-service": "~8.2.12",
|
||||||
"@angular/material": "^8.2.3",
|
"@angular/material": "^8.2.3",
|
||||||
"@angular/material-moment-adapter": "^8.2.3",
|
"@angular/material-moment-adapter": "^8.2.3",
|
||||||
"@angular/platform-browser": "~8.2.4",
|
"@angular/platform-browser": "~8.2.12",
|
||||||
"@angular/platform-browser-dynamic": "~8.2.4",
|
"@angular/platform-browser-dynamic": "~8.2.12",
|
||||||
"@angular/router": "~8.2.4",
|
"@angular/router": "~8.2.12",
|
||||||
"@ngrx/effects": "^8.4.0",
|
"@ngrx/effects": "^8.4.0",
|
||||||
"@ngrx/entity": "^8.4.0",
|
"@ngrx/entity": "^8.4.0",
|
||||||
"@ngrx/router-store": "^8.4.0",
|
"@ngrx/router-store": "^8.4.0",
|
||||||
|
@ -51,9 +51,9 @@
|
||||||
"@types/filesize": "^4.1.0",
|
"@types/filesize": "^4.1.0",
|
||||||
"@types/jasmine": "~3.3.8",
|
"@types/jasmine": "~3.3.8",
|
||||||
"@types/jasminewd2": "~2.0.3",
|
"@types/jasminewd2": "~2.0.3",
|
||||||
"@types/node": "^12.7.3",
|
"@types/node": "^10.14.22",
|
||||||
"@types/semver": "^6.0.2",
|
"@types/semver": "^6.0.2",
|
||||||
"@types/webpack": "^4.39.1",
|
"@types/webpack": "^4.39.5",
|
||||||
"@types/webpack-merge": "^4.1.5",
|
"@types/webpack-merge": "^4.1.5",
|
||||||
"@types/webpack-node-externals": "^1.6.3",
|
"@types/webpack-node-externals": "^1.6.3",
|
||||||
"awesome-node-loader": "^1.1.1",
|
"awesome-node-loader": "^1.1.1",
|
||||||
|
@ -66,13 +66,14 @@
|
||||||
"cross-env": "^5.2.1",
|
"cross-env": "^5.2.1",
|
||||||
"detect-browser": "^4.6.0",
|
"detect-browser": "^4.6.0",
|
||||||
"devtron": "^1.4.0",
|
"devtron": "^1.4.0",
|
||||||
"electron": "^6.0.7",
|
"electron": "^7.0.0",
|
||||||
"electron-builder": "^21.2.0",
|
"electron-builder": "^21.2.0",
|
||||||
"electron-debug": "^3.0.1",
|
"electron-debug": "^3.0.1",
|
||||||
"electron-devtools-installer": "^2.2.4",
|
"electron-devtools-installer": "^2.2.4",
|
||||||
"electron-log": "^3.0.7",
|
"electron-log": "^3.0.8",
|
||||||
"electron-reload": "^1.5.0",
|
"electron-reload": "^1.5.0",
|
||||||
"electron-store": "^4.0.0",
|
"electron-store": "^4.0.0",
|
||||||
|
"electron-updater": "^4.1.2",
|
||||||
"electron-window-state": "^5.0.3",
|
"electron-window-state": "^5.0.3",
|
||||||
"fs-extra": "^8.1.0",
|
"fs-extra": "^8.1.0",
|
||||||
"filesize": "^4.1.2",
|
"filesize": "^4.1.2",
|
||||||
|
|
|
@ -1 +1,2 @@
|
||||||
|
<app-layout-native-top-bar></app-layout-native-top-bar>
|
||||||
<router-outlet></router-outlet>
|
<router-outlet></router-outlet>
|
||||||
|
|
|
@ -42,6 +42,7 @@ import { AppComponent } from './app.component';
|
||||||
|
|
||||||
import { GUARDS } from './guards';
|
import { GUARDS } from './guards';
|
||||||
import { AppMessengerLayoutModule } from './layouts/messenger/messenger.layout.module';
|
import { AppMessengerLayoutModule } from './layouts/messenger/messenger.layout.module';
|
||||||
|
import { AppNativeLayoutModule } from './layouts/native/native.layout.module';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
imports: [
|
imports: [
|
||||||
|
@ -93,6 +94,7 @@ import { AppMessengerLayoutModule } from './layouts/messenger/messenger.layout.m
|
||||||
AppTranslateModule,
|
AppTranslateModule,
|
||||||
|
|
||||||
AppMessengerLayoutModule,
|
AppMessengerLayoutModule,
|
||||||
|
AppNativeLayoutModule,
|
||||||
|
|
||||||
LoggerModule.forRoot({
|
LoggerModule.forRoot({
|
||||||
level: NgxLoggerLevel.DEBUG
|
level: NgxLoggerLevel.DEBUG
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
import { TopBarComponent } from './top-bar.component';
|
||||||
|
|
||||||
|
export const COMPONENTS = [TopBarComponent];
|
|
@ -0,0 +1,30 @@
|
||||||
|
<mat-toolbar class="app-layout-native-title-bar">
|
||||||
|
<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-actions">
|
||||||
|
<button
|
||||||
|
mat-icon-button
|
||||||
|
class="button app-layout-native-title-bar-minimize"
|
||||||
|
(click)="onClickMinimize()"
|
||||||
|
>
|
||||||
|
<mat-icon>minimize</mat-icon>
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
mat-icon-button
|
||||||
|
class="button app-layout-native-title-bar-maximize"
|
||||||
|
(click)="onClickMaxmize()"
|
||||||
|
>
|
||||||
|
<ng-container [ngSwitch]="windowStateChanged$ | async">
|
||||||
|
<mat-icon *ngSwitchCase="WindowState.Maximized">filter_none</mat-icon>
|
||||||
|
<mat-icon *ngSwitchDefault>maximize</mat-icon>
|
||||||
|
</ng-container>
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
mat-icon-button
|
||||||
|
class="button app-layout-native-title-bar-close"
|
||||||
|
(click)="onClickClose()"
|
||||||
|
>
|
||||||
|
<mat-icon>close</mat-icon>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</mat-toolbar>
|
|
@ -0,0 +1,81 @@
|
||||||
|
:host {
|
||||||
|
.app-layout-native-title-bar {
|
||||||
|
-webkit-user-select: none;
|
||||||
|
-webkit-app-region: drag;
|
||||||
|
|
||||||
|
position: fixed;
|
||||||
|
right: 0;
|
||||||
|
top: 0;
|
||||||
|
display: flex;
|
||||||
|
// align-items: center;
|
||||||
|
// justify-content: center;
|
||||||
|
// flex-direction: row-reverse;
|
||||||
|
cursor: pointer;
|
||||||
|
background: white;
|
||||||
|
height: 30px;
|
||||||
|
|
||||||
|
.app-layout-native-title-bar-spacer {
|
||||||
|
flex: 1 1 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.app-layout-native-title-bar-actions {
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
.button {
|
||||||
|
-webkit-app-region: no-drag;
|
||||||
|
outline: 0;
|
||||||
|
cursor: pointer;
|
||||||
|
border: none;
|
||||||
|
height: 100%;
|
||||||
|
min-width: 30px;
|
||||||
|
max-width: 30px;
|
||||||
|
padding: 5px;
|
||||||
|
line-height: 10px;
|
||||||
|
border-radius: 0;
|
||||||
|
background: transparent;
|
||||||
|
transition: background 0.2s linear, color 0.2s linear;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 10px;
|
||||||
|
|
||||||
|
.mat-icon {
|
||||||
|
transform: translateY(-2px);
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.app-layout-native-title-bar-close,
|
||||||
|
&.app-layout-native-title-bar-maximize,
|
||||||
|
&.app-layout-native-title-bar-minimize {
|
||||||
|
color: black;
|
||||||
|
font-weight: lighter;
|
||||||
|
}
|
||||||
|
|
||||||
|
// &.app-layout-native-title-bar-minimize .mat-icon {
|
||||||
|
// transform: translateY(-43%);
|
||||||
|
// }
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
&.app-layout-native-title-bar-close {
|
||||||
|
background: #e81123;
|
||||||
|
color: darken(white, 20%);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.app-layout-native-title-bar-minimize {
|
||||||
|
background: darken(#673ab7, 10%);
|
||||||
|
color: darken(white, 20%);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.app-layout-native-title-bar-maximize {
|
||||||
|
background: darken(#673ab7, 10%);
|
||||||
|
color: darken(white, 20%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.app-layout-native-title-bar-title {
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { TopBarComponent } from './top-bar.component';
|
||||||
|
|
||||||
|
describe('App::Layout::Messenger::TopBarComponent', () => {
|
||||||
|
let component: TopBarComponent;
|
||||||
|
let fixture: ComponentFixture<TopBarComponent>;
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [TopBarComponent]
|
||||||
|
}).compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(TopBarComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,40 @@
|
||||||
|
import { Component, OnInit, Inject, OnDestroy } from '@angular/core';
|
||||||
|
import {
|
||||||
|
UCAP_NATIVE_SERVICE,
|
||||||
|
NativeService,
|
||||||
|
WindowState
|
||||||
|
} from '@ucap-webmessenger/native';
|
||||||
|
import { Observable } from 'rxjs';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-layout-native-top-bar',
|
||||||
|
templateUrl: './top-bar.component.html',
|
||||||
|
styleUrls: ['./top-bar.component.scss']
|
||||||
|
})
|
||||||
|
export class TopBarComponent implements OnInit, OnDestroy {
|
||||||
|
windowStateChanged$: Observable<WindowState>;
|
||||||
|
|
||||||
|
WindowState = WindowState;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
@Inject(UCAP_NATIVE_SERVICE) private nativeService: NativeService
|
||||||
|
) {}
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
this.windowStateChanged$ = this.nativeService.windowStateChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnDestroy(): void {}
|
||||||
|
|
||||||
|
onClickClose() {
|
||||||
|
this.nativeService.windowClose();
|
||||||
|
}
|
||||||
|
|
||||||
|
onClickMinimize() {
|
||||||
|
this.nativeService.windowMinimize();
|
||||||
|
}
|
||||||
|
|
||||||
|
onClickMaxmize() {
|
||||||
|
this.nativeService.windowMaximize();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
import { NgModule } from '@angular/core';
|
||||||
|
import { CommonModule } from '@angular/common';
|
||||||
|
|
||||||
|
import { FlexLayoutModule } from '@angular/flex-layout';
|
||||||
|
|
||||||
|
import { MatIconModule } from '@angular/material/icon';
|
||||||
|
import { MatToolbarModule } from '@angular/material/toolbar';
|
||||||
|
|
||||||
|
import { UCapUiModule } from '@ucap-webmessenger/ui';
|
||||||
|
|
||||||
|
import { COMPONENTS } from './components';
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
imports: [
|
||||||
|
CommonModule,
|
||||||
|
FlexLayoutModule,
|
||||||
|
MatIconModule,
|
||||||
|
MatToolbarModule,
|
||||||
|
UCapUiModule
|
||||||
|
],
|
||||||
|
exports: [...COMPONENTS],
|
||||||
|
declarations: [...COMPONENTS],
|
||||||
|
entryComponents: []
|
||||||
|
})
|
||||||
|
export class AppNativeLayoutModule {}
|
|
@ -1,6 +1,6 @@
|
||||||
import { Observable } from 'rxjs';
|
import { Observable } from 'rxjs';
|
||||||
|
|
||||||
import { NativeService } from '@ucap-webmessenger/native';
|
import { NativeService, WindowState } from '@ucap-webmessenger/native';
|
||||||
import { HttpClient } from '@angular/common/http';
|
import { HttpClient } from '@angular/common/http';
|
||||||
import { map } from 'rxjs/operators';
|
import { map } from 'rxjs/operators';
|
||||||
|
|
||||||
|
@ -35,5 +35,23 @@ export class BrowserNativeService implements NativeService {
|
||||||
return this.httpClient.post<boolean>(path, buf, {});
|
return this.httpClient.post<boolean>(path, buf, {});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
windowStateChanged(): Observable<WindowState> {
|
||||||
|
return new Observable<WindowState>(subscriber => {
|
||||||
|
try {
|
||||||
|
subscriber.next(WindowState.Normal);
|
||||||
|
} catch (error) {
|
||||||
|
subscriber.error(error);
|
||||||
|
} finally {
|
||||||
|
subscriber.complete();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
windowClose(): void {}
|
||||||
|
|
||||||
|
windowMinimize(): void {}
|
||||||
|
|
||||||
|
windowMaximize(): void {}
|
||||||
|
|
||||||
constructor(private httpClient: HttpClient) {}
|
constructor(private httpClient: HttpClient) {}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,15 @@
|
||||||
import { ipcRenderer } from 'electron';
|
import { ipcRenderer, remote, IpcRendererEvent } from 'electron';
|
||||||
|
|
||||||
import { Observable } from 'rxjs';
|
import { Observable, Subject } from 'rxjs';
|
||||||
|
|
||||||
import { NativeService } from '@ucap-webmessenger/native';
|
import { NativeService, WindowState } from '@ucap-webmessenger/native';
|
||||||
import { Channel } from '../types/channel.type';
|
import { Channel } from '../types/channel.type';
|
||||||
|
import { share } from 'rxjs/operators';
|
||||||
|
|
||||||
export class ElectronNativeService implements NativeService {
|
export class ElectronNativeService implements NativeService {
|
||||||
|
private windowStateChangedSubject: Subject<WindowState> | null = null;
|
||||||
|
private windowStateChanged$: Observable<WindowState> | null = null;
|
||||||
|
|
||||||
showNotify(
|
showNotify(
|
||||||
roomSeq: number,
|
roomSeq: number,
|
||||||
title: string,
|
title: string,
|
||||||
|
@ -63,5 +67,54 @@ export class ElectronNativeService implements NativeService {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
windowStateChanged(): Observable<WindowState> {
|
||||||
|
if (!this.windowStateChangedSubject) {
|
||||||
|
this.windowStateChangedSubject = new Subject<WindowState>();
|
||||||
|
this.windowStateChanged$ = this.windowStateChangedSubject
|
||||||
|
.asObservable()
|
||||||
|
.pipe(share());
|
||||||
|
}
|
||||||
|
|
||||||
|
ipcRenderer.on(
|
||||||
|
Channel.windowStateChanged,
|
||||||
|
(event: IpcRendererEvent, windowState: WindowState) => {
|
||||||
|
console.log('windowStateChanged', windowState);
|
||||||
|
this.windowStateChangedSubject.next(windowState);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
return this.windowStateChanged$;
|
||||||
|
}
|
||||||
|
|
||||||
|
windowClose(): void {
|
||||||
|
const currentWindow = remote.getCurrentWindow();
|
||||||
|
if (!currentWindow) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
currentWindow.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
windowMinimize(): void {
|
||||||
|
const currentWindow = remote.getCurrentWindow();
|
||||||
|
if (!currentWindow) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
currentWindow.minimize();
|
||||||
|
}
|
||||||
|
|
||||||
|
windowMaximize(): void {
|
||||||
|
const currentWindow = remote.getCurrentWindow();
|
||||||
|
if (!currentWindow) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentWindow.isMaximized()) {
|
||||||
|
currentWindow.unmaximize();
|
||||||
|
} else {
|
||||||
|
currentWindow.maximize();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
constructor() {}
|
constructor() {}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
export enum Channel {
|
export enum Channel {
|
||||||
|
windowStateChanged = 'window-state-changed',
|
||||||
|
|
||||||
showNotify = 'UCAP::showNotify',
|
showNotify = 'UCAP::showNotify',
|
||||||
checkForUpdates = 'UCAP::checkForUpdates',
|
checkForUpdates = 'UCAP::checkForUpdates',
|
||||||
showImageViewer = 'UCAP::showImageViewer',
|
showImageViewer = 'UCAP::showImageViewer',
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
import { Observable } from 'rxjs';
|
import { Observable } from 'rxjs';
|
||||||
|
|
||||||
|
import { WindowState } from '../types/window-state.type';
|
||||||
|
|
||||||
export interface NativeService {
|
export interface NativeService {
|
||||||
showNotify(
|
showNotify(
|
||||||
roomSeq: number,
|
roomSeq: number,
|
||||||
|
@ -15,4 +17,9 @@ export interface NativeService {
|
||||||
|
|
||||||
saveFile(path: string, buf: ArrayBuffer): Observable<boolean>;
|
saveFile(path: string, buf: ArrayBuffer): Observable<boolean>;
|
||||||
readFile(path: string): Observable<ArrayBuffer>;
|
readFile(path: string): Observable<ArrayBuffer>;
|
||||||
|
|
||||||
|
windowStateChanged(): Observable<WindowState>;
|
||||||
|
windowClose(): void;
|
||||||
|
windowMinimize(): void;
|
||||||
|
windowMaximize(): void;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
export enum WindowState {
|
||||||
|
Minimized = 'minimized',
|
||||||
|
Normal = 'normal',
|
||||||
|
Maximized = 'maximized',
|
||||||
|
FullScreen = 'full-screen',
|
||||||
|
Hidden = 'hidden'
|
||||||
|
}
|
|
@ -5,5 +5,6 @@
|
||||||
export * from './lib/services/native.service';
|
export * from './lib/services/native.service';
|
||||||
|
|
||||||
export * from './lib/types/token';
|
export * from './lib/types/token';
|
||||||
|
export * from './lib/types/window-state.type';
|
||||||
|
|
||||||
export * from './lib/ucap-native.module';
|
export * from './lib/ucap-native.module';
|
||||||
|
|
|
@ -5,15 +5,17 @@
|
||||||
fxLayoutAlign="center center"
|
fxLayoutAlign="center center"
|
||||||
>
|
>
|
||||||
<div class="add-option">
|
<div class="add-option">
|
||||||
<i class="material-icons">
|
<button mat-icon-button class="material-icons">
|
||||||
attach_file
|
<mat-icon>attach_file</mat-icon>
|
||||||
</i>
|
</button>
|
||||||
<i class="material-icons">
|
|
||||||
sentiment_satisfied_alt
|
<button mat-icon-button class="material-icons">
|
||||||
</i>
|
<mat-icon>sentiment_satisfied_alt</mat-icon>
|
||||||
<i class="material-icons">
|
</button>
|
||||||
g_translate
|
|
||||||
</i>
|
<button mat-icon-button class="material-icons">
|
||||||
|
<mat-icon>g_translate</mat-icon>
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<form
|
<form
|
||||||
|
|
Loading…
Reference in New Issue
Block a user