richard-loafle ef007d0ab5 clipboard
2020-02-04 17:13:09 +09:00

509 lines
13 KiB
TypeScript

import { ipcRenderer, remote, shell, webFrame } from 'electron';
import { Observable, Subject } from 'rxjs';
import {
NativeService,
WindowState,
NotificationRequest,
WindowIdle,
UpdateInfo,
UpdateCheckConfig,
NativePathName,
NativeType
} from '@ucap-webmessenger/native';
import { share } from 'rxjs/operators';
import {
NotificationChannel,
UpdaterChannel,
FileChannel,
WindowStateChannel,
IdleStateChannel,
ChatChannel,
MessengerChannel,
MessageChannel,
ProcessChannel,
AppChannel,
ClipboardChannel
} from '../types/channel.type';
import { Injectable } from '@angular/core';
import { TranslateLoaderService } from '../translate/electron-loader';
import { TranslateLoader } from '@ngx-translate/core';
import { StatusCode } from '@ucap-webmessenger/core';
@Injectable({
providedIn: 'root'
})
export class ElectronNativeService implements NativeService {
private ipcRenderer: typeof ipcRenderer;
private webFrame: typeof webFrame;
private remote: typeof remote;
private shell: typeof shell;
private logoutSubject: Subject<void> | null = null;
private logout$: Observable<void> | null = null;
private changeStatusSubject: Subject<StatusCode> | null = null;
private changeStatus$: Observable<StatusCode> | null = null;
private showSettingSubject: Subject<void> | null = null;
private showSetting$: Observable<void> | null = null;
private windowStateChangedSubject: Subject<WindowState> | null = null;
private windowStateChanged$: Observable<WindowState> | null = null;
private idleStateChangedSubject: Subject<WindowIdle> | null = null;
private idleStateChanged$: Observable<WindowIdle> | null = null;
private chatOpenRoomSubject: Subject<string> | null = null;
private chatOpenRoom$: Observable<string> | null = null;
private msgOpenMessageSubject: Subject<string> | null = null;
private msgOpenMessage$: Observable<string> | null = null;
private backgroundCheckForUpdatesSubject: Subject<UpdateInfo> | null = null;
private backgroundCheckForUpdates$: Observable<UpdateInfo> | null = null;
type(): NativeType {
return NativeType.Electron;
}
postAppInit(): void {}
logout(): Observable<void> {
if (!this.logoutSubject) {
this.logoutSubject = new Subject<void>();
this.logout$ = this.logoutSubject.asObservable().pipe(share());
}
this.ipcRenderer.on(MessengerChannel.Logout, (event: any) => {
this.logoutSubject.next();
});
return this.logout$;
}
getNetworkInfo(): Promise<any> {
return new Promise<string>((resolve, reject) => {
try {
resolve(this.ipcRenderer.sendSync(MessengerChannel.GetNetworkInfo));
} catch (error) {
reject(error);
}
});
}
getVersionInfo(): Promise<string> {
return new Promise<string>((resolve, reject) => {
try {
resolve(this.ipcRenderer.sendSync(MessengerChannel.GetVersionInfo));
} catch (error) {
reject(error);
}
});
}
changeStatus(): Observable<StatusCode> {
if (!this.changeStatusSubject) {
this.changeStatusSubject = new Subject<StatusCode>();
this.changeStatus$ = this.changeStatusSubject
.asObservable()
.pipe(share());
}
this.ipcRenderer.on(
MessengerChannel.ChangeStatus,
(event: any, statusCode: StatusCode) => {
this.changeStatusSubject.next(statusCode);
}
);
return this.changeStatus$;
}
showSetting(): Observable<void> {
if (!this.showSettingSubject) {
this.showSettingSubject = new Subject<void>();
this.showSetting$ = this.showSettingSubject.asObservable().pipe(share());
}
this.ipcRenderer.on(MessengerChannel.ShowSetting, (event: any) => {
this.showSettingSubject.next();
});
return this.showSetting$;
}
changeAutoLaunch(autoLaunch: boolean): Promise<boolean> {
return new Promise<boolean>((resolve, reject) => {
try {
resolve(
this.ipcRenderer.sendSync(
MessengerChannel.ChangeAutoLaunch,
autoLaunch
)
);
} catch (error) {
reject(error);
}
});
}
changeStartupHideWindow(startupHideWindow: boolean): Promise<boolean> {
return new Promise<boolean>((resolve, reject) => {
try {
resolve(
this.ipcRenderer.sendSync(
MessengerChannel.ChangeStartupHideWindow,
startupHideWindow
)
);
} catch (error) {
reject(error);
}
});
}
changeDownloadPath(downloadPath: string): Promise<string> {
return new Promise<string>((resolve, reject) => {
try {
resolve(
this.ipcRenderer.sendSync(
MessengerChannel.ChangeDownloadPath,
downloadPath
)
);
} catch (error) {
reject(error);
}
});
}
notify(noti: NotificationRequest): void {
this.ipcRenderer.send(NotificationChannel.Notify, noti);
}
closeAllNotify(): void {
this.ipcRenderer.send(NotificationChannel.CloseAllNotify);
}
checkForUpdates(currentVersion: string): void {
this.ipcRenderer.send(UpdaterChannel.Apply, currentVersion);
}
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 {
this.ipcRenderer.send(FileChannel.ShowImageViewer);
}
readFile(path: string): Promise<Buffer> {
return new Promise<Buffer>((resolve, reject) => {
try {
const buffer = this.ipcRenderer.sendSync(FileChannel.ReadFile, path);
if (!!buffer) {
resolve(buffer);
} else {
reject(buffer as Error);
}
} catch (error) {
reject(error);
}
});
}
saveFile(
buffer: Buffer,
fileName: string,
mimeType: string,
path?: string
): Promise<string> {
return new Promise<string>((resolve, reject) => {
try {
resolve(
this.ipcRenderer.sendSync(
FileChannel.SaveFile,
buffer,
fileName,
mimeType,
path
)
);
} catch (error) {
reject(error);
}
});
}
openDefaultDownloadFolder(): Promise<boolean> {
return new Promise<boolean>((resolve, reject) => {
try {
resolve(
this.ipcRenderer.sendSync(FileChannel.OpenFolderItem, undefined, true)
);
} catch (error) {
reject(error);
}
});
}
openTargetFolder(folderPath?: string, make?: boolean): Promise<boolean> {
return new Promise<boolean>((resolve, reject) => {
try {
resolve(
this.ipcRenderer.sendSync(
FileChannel.OpenFolderItem,
folderPath,
!make ? false : make
)
);
} catch (error) {
reject(error);
}
});
}
openTargetItem(filePath?: string): Promise<boolean> {
return new Promise<boolean>((resolve, reject) => {
try {
resolve(
this.ipcRenderer.sendSync(FileChannel.OpenFolderItem, filePath, false)
);
} catch (error) {
reject(error);
}
});
}
getPath(name: NativePathName): Promise<string> {
return new Promise<string>((resolve, reject) => {
try {
resolve(this.ipcRenderer.sendSync(FileChannel.GetPath, name));
} catch (error) {
reject(error);
}
});
}
selectDirectory(): Promise<string> {
return new Promise<string>((resolve, reject) => {
try {
resolve(this.ipcRenderer.sendSync(FileChannel.SelectDirectory));
} catch (error) {
reject(error);
}
});
}
selectSaveFilePath(
defaultPath?: string
): Promise<{
canceled: boolean;
filePath: string;
}> {
return new Promise<{
canceled: boolean;
filePath: string;
}>((resolve, reject) => {
try {
resolve(
this.ipcRenderer.sendSync(FileChannel.SelectSaveFilePath, defaultPath)
);
} catch (error) {
reject(error);
}
});
}
executeProcess(executableName: string): Promise<number> {
return new Promise<number>((resolve, reject) => {
try {
resolve(
this.ipcRenderer.sendSync(ProcessChannel.Execute, executableName)
);
} catch (error) {
reject(error);
}
});
}
windowStateChanged(): Observable<WindowState> {
if (!this.windowStateChangedSubject) {
this.windowStateChangedSubject = new Subject<WindowState>();
this.windowStateChanged$ = this.windowStateChangedSubject
.asObservable()
.pipe(share());
}
this.ipcRenderer.on(
WindowStateChannel.Changed,
(event: any, windowState: WindowState) => {
this.windowStateChangedSubject.next(windowState);
}
);
return this.windowStateChanged$;
}
windowClose(): void {
const currentWindow = this.remote.getCurrentWindow();
if (!currentWindow) {
return;
}
currentWindow.close();
}
windowMinimize(): void {
const currentWindow = this.remote.getCurrentWindow();
if (!currentWindow) {
return;
}
currentWindow.minimize();
}
windowMaximize(): void {
const currentWindow = this.remote.getCurrentWindow();
if (!currentWindow) {
return;
}
if (currentWindow.isMaximized()) {
currentWindow.unmaximize();
} else {
currentWindow.maximize();
}
}
appExit(): void {
this.ipcRenderer.send(AppChannel.Exit);
}
zoomTo(factor: number): Promise<number> {
return new Promise<number>((resolve, reject) => {
try {
this.webFrame.setZoomFactor(factor / 100);
resolve(this.webFrame.getZoomFactor());
} catch (error) {
reject(error);
}
});
}
idleStateChanged(): Observable<WindowIdle> {
if (!this.idleStateChangedSubject) {
this.idleStateChangedSubject = new Subject<WindowIdle>();
this.idleStateChanged$ = this.idleStateChangedSubject
.asObservable()
.pipe(share());
}
console.log('idleStateChanged');
this.ipcRenderer.send(IdleStateChannel.StartCheck);
this.ipcRenderer.on(
IdleStateChannel.Changed,
(event: any, idleState: WindowIdle) => {
this.idleStateChangedSubject.next(idleState);
}
);
return this.idleStateChanged$;
}
idleStateStop(): void {
this.ipcRenderer.send(IdleStateChannel.StopCheck);
}
changeLimitOfIdleState(limitTime: number): void {
this.ipcRenderer.send(IdleStateChannel.ChangeLimitTime, limitTime);
}
chatOpenRoom(): Observable<string> {
if (!this.chatOpenRoomSubject) {
this.chatOpenRoomSubject = new Subject<WindowIdle>();
this.chatOpenRoom$ = this.chatOpenRoomSubject
.asObservable()
.pipe(share());
}
this.ipcRenderer.on(ChatChannel.OpenRoom, (event: any, roomSeq: string) => {
this.chatOpenRoomSubject.next(roomSeq);
});
return this.chatOpenRoom$;
}
msgOpenMessage(): Observable<string> {
if (!this.msgOpenMessageSubject) {
this.msgOpenMessageSubject = new Subject<WindowIdle>();
this.msgOpenMessage$ = this.msgOpenMessageSubject
.asObservable()
.pipe(share());
}
this.ipcRenderer.on(
MessageChannel.OpenMessage,
(event: any, messageSeq: string) => {
this.msgOpenMessageSubject.next(messageSeq);
}
);
return this.msgOpenMessage$;
}
getTranslateLoader(prefix?: string, suffix?: string): TranslateLoader {
return new TranslateLoaderService(this, prefix, suffix);
}
openDefaultBrowser(url: string): void {
this.shell.openExternal(url);
}
readFromClipboard(): Promise<{
text?: string;
rtf?: string;
html?: string;
image?: Buffer;
imageDataUrl?: string;
}> {
return new Promise<{
text?: string;
rtf?: string;
html?: string;
image?: Buffer;
imageDataUrl?: string;
}>((resolve, reject) => {
try {
resolve(this.ipcRenderer.sendSync(ClipboardChannel.Read));
} catch (error) {
reject(error);
}
});
}
get isElectron() {
return window && (window as any).process && (window as any).process.type;
}
constructor() {
if (this.isElectron) {
this.ipcRenderer = (window as any).require('electron').ipcRenderer;
this.remote = (window as any).require('electron').remote;
this.shell = (window as any).require('electron').shell;
this.webFrame = (window as any).require('electron').webFrame;
}
}
}