This commit is contained in:
병준 박 2019-11-07 17:33:17 +09:00
commit 77ceeb84f7
12 changed files with 208 additions and 18 deletions

View File

@ -6,7 +6,6 @@ import windowStateKeeper from 'electron-window-state';
import { EventEmitter } from 'events';
import { now } from '../util/now';
import { Channel } from '@ucap-webmessenger/native-electron';
import { registerWindowStateChangedEvents } from '../lib/window-state';
export class AppWindow {
@ -214,4 +213,8 @@ export class AppWindow {
public destroy() {
this.window.destroy();
}
public get browserWindow(): BrowserWindow | null {
return this.window;
}
}

View File

@ -12,6 +12,8 @@ import { root } from './util/root';
import { DefaultFolder } from './lib/default-folder';
import { FileUtil } from './lib/file-util';
import { IdleChecker } from './lib/idle-checker';
let appWindow: AppWindow | null = null;
const launchTime = now();
@ -53,6 +55,7 @@ process.on('uncaughtException', (error: Error) => {
let isDuplicateInstance = false;
const gotSingleInstanceLock = app.requestSingleInstanceLock();
isDuplicateInstance = !gotSingleInstanceLock;
let idle: IdleChecker | null;
app.on('second-instance', (event, args, workingDirectory) => {
// Someone tried to run a second instance, we should focus our window.
@ -216,6 +219,15 @@ ipcMain.on(Channel.saveFile, async (event: IpcMainEvent, ...args: any[]) => {
}
});
ipcMain.on(Channel.idleStateStart, (event: IpcMainEvent, ...args: any[]) => {
if (!!idle) {
idle.destoryChecker();
idle = null;
}
idle = new IdleChecker(appWindow.browserWindow); // default 10min
idle.startChecker();
});
ipcMain.on(Channel.showNotify, (event: IpcMainEvent, ...args: any[]) => {
console.log('Channel.showNotify', args);
});

View File

@ -0,0 +1,72 @@
import { powerMonitor, BrowserWindow } from 'electron';
import { Channel } 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(Channel.idleStateChanged, this.status);
}
} else {
if (this.status === IdleType.IDLE) {
this.status = IdleType.ACTIVE;
// TODO :: USER_STATUS chage online
this.window.webContents.send(Channel.idleStateChanged, 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);
}
}
}

View File

@ -1,9 +1,17 @@
import { Component, OnInit } from '@angular/core';
import { map, tap } from 'rxjs/operators';
import { Component, OnInit, Inject, OnDestroy } from '@angular/core';
import { Store, select } from '@ngrx/store';
import * as AppSotre from '@app/store';
import { Observable } from 'rxjs';
import { Observable, Subscription } from 'rxjs';
import {
WindowIdle,
UCAP_NATIVE_SERVICE,
NativeService
} from '@ucap-webmessenger/native';
import { StatusProtocolService } from '@ucap-webmessenger/protocol-status';
import { StatusType, StatusCode } from '@ucap-webmessenger/core';
@Component({
selector: 'app-page-messenger-main',
@ -12,12 +20,44 @@ import { Observable } from 'rxjs';
})
export class MainPageComponent implements OnInit {
selectedChat$: Observable<string | null>;
idleStateChangedSubscription: Subscription;
constructor(private store: Store<any>) {}
constructor(
@Inject(UCAP_NATIVE_SERVICE) private nativeService: NativeService,
private store: Store<any>,
private statusProtocolService: StatusProtocolService
) {}
ngOnInit(): void {
this.selectedChat$ = this.store.pipe(
select(AppSotre.MessengerSelector.ChatSelector.selectedRoom)
);
this.idleStateChangedSubscription = this.nativeService
.idleStateChanged()
.subscribe(action => {
console.log(action);
let statusType: StatusCode;
if (action === 'IDLE') {
// away
statusType = StatusCode.Away;
} else {
// online
statusType = StatusCode.OnLine;
}
this.statusProtocolService.status({
statusDivisionType: StatusType.Messenger,
statusType,
statusMessage: ''
});
});
}
OnDestroy(): void {
if (!!this.idleStateChangedSubscription) {
this.idleStateChangedSubscription.unsubscribe();
}
}
}

View File

@ -3,7 +3,8 @@ import { Observable } from 'rxjs';
import {
NativeService,
WindowState,
NotiRequest
NotiRequest,
WindowIdle
} from '@ucap-webmessenger/native';
import { HttpClient } from '@angular/common/http';
import { map } from 'rxjs/operators';
@ -59,5 +60,17 @@ export class BrowserNativeService implements NativeService {
windowMaximize(): void {}
idleStateChanged(): Observable<WindowIdle> {
return new Observable<WindowIdle>(subscriber => {
try {
subscriber.next(WindowIdle.Active);
} catch (error) {
subscriber.error(error);
} finally {
subscriber.complete();
}
});
}
constructor(private httpClient: HttpClient) {}
}

View File

@ -5,7 +5,8 @@ import { Observable, Subject } from 'rxjs';
import {
NativeService,
WindowState,
NotiRequest
NotiRequest,
WindowIdle
} from '@ucap-webmessenger/native';
import { Channel } from '../types/channel.type';
import { share } from 'rxjs/operators';
@ -14,6 +15,9 @@ export class ElectronNativeService implements NativeService {
private windowStateChangedSubject: Subject<WindowState> | null = null;
private windowStateChanged$: Observable<WindowState> | null = null;
private idleStateChangedSubject: Subject<WindowIdle> | null = null;
private idleStateChanged$: Observable<WindowIdle> | null = null;
showNotify(noti: NotiRequest): void {
ipcRenderer.send(
Channel.showNotify,
@ -121,5 +125,24 @@ export class ElectronNativeService implements NativeService {
}
}
idleStateChanged(): Observable<WindowIdle> {
if (!this.idleStateChangedSubject) {
this.idleStateChangedSubject = new Subject<WindowIdle>();
this.idleStateChanged$ = this.idleStateChangedSubject
.asObservable()
.pipe(share());
}
ipcRenderer.send(Channel.idleStateStart, 'start');
ipcRenderer.on(
Channel.idleStateChanged,
(event: IpcRendererEvent, idleState: WindowIdle) => {
this.idleStateChangedSubject.next(idleState);
}
);
return this.idleStateChanged$;
}
constructor() {}
}

View File

@ -1,5 +1,7 @@
export enum Channel {
windowStateChanged = 'window-state-changed',
idleStateChanged = 'window-idle-state-changed',
idleStateStart = 'window-idle-state-check-start',
showNotify = 'UCAP::showNotify',
checkForUpdates = 'UCAP::checkForUpdates',

View File

@ -1,6 +1,7 @@
import { Observable } from 'rxjs';
import { WindowState } from '../types/window-state.type';
import { WindowIdle } from '../types/window-idle.type';
export interface NativeService {
showNotify(noti: NotiRequest): void;
@ -16,6 +17,8 @@ export interface NativeService {
windowClose(): void;
windowMinimize(): void;
windowMaximize(): void;
idleStateChanged(): Observable<WindowIdle>;
}
export interface NotiRequest {

View File

@ -0,0 +1,4 @@
export enum WindowIdle {
Active = 'ACT',
Idle = 'IDLE'
}

View File

@ -6,5 +6,6 @@ export * from './lib/services/native.service';
export * from './lib/types/token';
export * from './lib/types/window-state.type';
export * from './lib/types/window-idle.type';
export * from './lib/ucap-native.module';

View File

@ -1,24 +1,31 @@
<div class="bubble-main">
<div class="file-img video"></div>
<!--파일명에 따라 doc exe hwp ppt xls zip 으로 추가되고 나머지 파일 명은 file로 기간이 만료된 파일은 그뒤에 disable도 추가-->
<!-- <div class="file-img" [ngClass]="fileInfo.FileExt"></div> -->
<div [ngClass]="['mime-icon', 'light', 'ico-' + fileInfo.fileExt]">
<div class="ico"></div>
</div>
<ul class="file-info">
<li class="file-name">
{{ fileInfo.FileName }}
{{ fileInfo.fileName }}
</li>
<li class="file-size">
{{ fileInfo.AttSize }}
{{ fileInfo.attachmentSize | ucapBytes }}
</li>
<li class="file-ext">
{{ fileInfo.FileExt }}
{{ fileInfo.fileExt }}
</li>
</ul>
</div>
<span class="btn-box">
<ul>
<div class="btn-box">
<ul *ngIf="expired" class="expired">
<li>기간이 만료된 파일입니다.</li>
</ul>
<ul *ngIf="!expired && fileInfo && fileInfo.attachmentSeq">
<li>
<button mat-button >Save</button>
<button mat-button (click)="onClickSave()">Save</button>
</li>
<li>
<button mat-button >Save As</button>
<button mat-button (click)="onClickSaveAs()">Save As</button>
</li>
</ul>
</span>
</div>

View File

@ -1,6 +1,6 @@
import { Component, OnInit, Input } from '@angular/core';
import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
import { NGXLogger } from 'ngx-logger';
import { FileInfo } from '../../models/file-info.json';
import { FileEventJson } from '@ucap-webmessenger/protocol-event';
@Component({
selector: 'ucap-chat-message-box-video',
@ -9,11 +9,21 @@ import { FileInfo } from '../../models/file-info.json';
})
export class VideoComponent implements OnInit {
@Input()
fileInfo: FileInfo;
fileInfo: FileEventJson;
@Input()
expired = false;
@Output()
save = new EventEmitter<string>();
constructor(private logger: NGXLogger) {}
ngOnInit() {}
onClickSave() {
this.save.emit('save');
}
onClickSaveAs() {
this.save.emit('saveAs');
}
}