IDLE 체크로 부재중 <> 온라인 상태 변경 로직 추가.(only electron)
This commit is contained in:
parent
d8581a70fe
commit
731a9f74a0
|
@ -6,7 +6,6 @@ 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';
|
import { registerWindowStateChangedEvents } from '../lib/window-state';
|
||||||
|
|
||||||
export class AppWindow {
|
export class AppWindow {
|
||||||
|
@ -214,4 +213,8 @@ export class AppWindow {
|
||||||
public destroy() {
|
public destroy() {
|
||||||
this.window.destroy();
|
this.window.destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public get browserWindow(): BrowserWindow | null {
|
||||||
|
return this.window;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,8 @@ import { root } from './util/root';
|
||||||
import { DefaultFolder } from './lib/default-folder';
|
import { DefaultFolder } from './lib/default-folder';
|
||||||
import { FileUtil } from './lib/file-util';
|
import { FileUtil } from './lib/file-util';
|
||||||
|
|
||||||
|
import { IdleChecker } from './lib/idle-checker';
|
||||||
|
|
||||||
let appWindow: AppWindow | null = null;
|
let appWindow: AppWindow | null = null;
|
||||||
|
|
||||||
const launchTime = now();
|
const launchTime = now();
|
||||||
|
@ -53,6 +55,7 @@ process.on('uncaughtException', (error: Error) => {
|
||||||
let isDuplicateInstance = false;
|
let isDuplicateInstance = false;
|
||||||
const gotSingleInstanceLock = app.requestSingleInstanceLock();
|
const gotSingleInstanceLock = app.requestSingleInstanceLock();
|
||||||
isDuplicateInstance = !gotSingleInstanceLock;
|
isDuplicateInstance = !gotSingleInstanceLock;
|
||||||
|
let idle: IdleChecker | null;
|
||||||
|
|
||||||
app.on('second-instance', (event, args, workingDirectory) => {
|
app.on('second-instance', (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.
|
||||||
|
@ -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[]) => {
|
ipcMain.on(Channel.showNotify, (event: IpcMainEvent, ...args: any[]) => {
|
||||||
console.log('Channel.showNotify', args);
|
console.log('Channel.showNotify', args);
|
||||||
});
|
});
|
||||||
|
|
72
main/src/lib/idle-checker.ts
Normal file
72
main/src/lib/idle-checker.ts
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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 { Store, select } from '@ngrx/store';
|
||||||
|
|
||||||
import * as AppSotre from '@app/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({
|
@Component({
|
||||||
selector: 'app-page-messenger-main',
|
selector: 'app-page-messenger-main',
|
||||||
|
@ -12,12 +20,44 @@ import { Observable } from 'rxjs';
|
||||||
})
|
})
|
||||||
export class MainPageComponent implements OnInit {
|
export class MainPageComponent implements OnInit {
|
||||||
selectedChat$: Observable<string | null>;
|
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 {
|
ngOnInit(): void {
|
||||||
this.selectedChat$ = this.store.pipe(
|
this.selectedChat$ = this.store.pipe(
|
||||||
select(AppSotre.MessengerSelector.ChatSelector.selectedRoom)
|
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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,8 @@ import { Observable } from 'rxjs';
|
||||||
import {
|
import {
|
||||||
NativeService,
|
NativeService,
|
||||||
WindowState,
|
WindowState,
|
||||||
NotiRequest
|
NotiRequest,
|
||||||
|
WindowIdle
|
||||||
} from '@ucap-webmessenger/native';
|
} 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';
|
||||||
|
@ -59,5 +60,17 @@ export class BrowserNativeService implements NativeService {
|
||||||
|
|
||||||
windowMaximize(): void {}
|
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) {}
|
constructor(private httpClient: HttpClient) {}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,8 @@ import { Observable, Subject } from 'rxjs';
|
||||||
import {
|
import {
|
||||||
NativeService,
|
NativeService,
|
||||||
WindowState,
|
WindowState,
|
||||||
NotiRequest
|
NotiRequest,
|
||||||
|
WindowIdle
|
||||||
} from '@ucap-webmessenger/native';
|
} from '@ucap-webmessenger/native';
|
||||||
import { Channel } from '../types/channel.type';
|
import { Channel } from '../types/channel.type';
|
||||||
import { share } from 'rxjs/operators';
|
import { share } from 'rxjs/operators';
|
||||||
|
@ -14,6 +15,9 @@ export class ElectronNativeService implements NativeService {
|
||||||
private windowStateChangedSubject: Subject<WindowState> | null = null;
|
private windowStateChangedSubject: Subject<WindowState> | null = null;
|
||||||
private windowStateChanged$: Observable<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 {
|
showNotify(noti: NotiRequest): void {
|
||||||
ipcRenderer.send(
|
ipcRenderer.send(
|
||||||
Channel.showNotify,
|
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() {}
|
constructor() {}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
export enum Channel {
|
export enum Channel {
|
||||||
windowStateChanged = 'window-state-changed',
|
windowStateChanged = 'window-state-changed',
|
||||||
|
idleStateChanged = 'window-idle-state-changed',
|
||||||
|
idleStateStart = 'window-idle-state-check-start',
|
||||||
|
|
||||||
showNotify = 'UCAP::showNotify',
|
showNotify = 'UCAP::showNotify',
|
||||||
checkForUpdates = 'UCAP::checkForUpdates',
|
checkForUpdates = 'UCAP::checkForUpdates',
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import { Observable } from 'rxjs';
|
import { Observable } from 'rxjs';
|
||||||
|
|
||||||
import { WindowState } from '../types/window-state.type';
|
import { WindowState } from '../types/window-state.type';
|
||||||
|
import { WindowIdle } from '../types/window-idle.type';
|
||||||
|
|
||||||
export interface NativeService {
|
export interface NativeService {
|
||||||
showNotify(noti: NotiRequest): void;
|
showNotify(noti: NotiRequest): void;
|
||||||
|
@ -16,6 +17,8 @@ export interface NativeService {
|
||||||
windowClose(): void;
|
windowClose(): void;
|
||||||
windowMinimize(): void;
|
windowMinimize(): void;
|
||||||
windowMaximize(): void;
|
windowMaximize(): void;
|
||||||
|
|
||||||
|
idleStateChanged(): Observable<WindowIdle>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface NotiRequest {
|
export interface NotiRequest {
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
export enum WindowIdle {
|
||||||
|
Active = 'ACT',
|
||||||
|
Idle = 'IDLE'
|
||||||
|
}
|
|
@ -6,5 +6,6 @@ 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/types/window-state.type';
|
||||||
|
export * from './lib/types/window-idle.type';
|
||||||
|
|
||||||
export * from './lib/ucap-native.module';
|
export * from './lib/ucap-native.module';
|
||||||
|
|
Loading…
Reference in New Issue
Block a user