next-ucap-messenger/electron-projects/ucap-webmessenger-electron/src/index.ts

311 lines
7.3 KiB
TypeScript
Raw Normal View History

2019-11-11 06:53:39 +00:00
import { app, ipcMain, IpcMainEvent, remote } 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 { now } from './util/now';
import { showUncaughtException } from './crash/show-uncaught-exception';
import {
UpdaterChannel,
FileChannel,
IdleStateChannel,
NotificationChannel,
ChatChannel,
2019-11-11 06:53:39 +00:00
} from '@ucap-webmessenger/native-electron';
import { ElectronNotificationService } from '@ucap-webmessenger/electron-notification';
import { root } from './util/root';
import { DefaultFolder } from './lib/default-folder';
import { FileUtil } from './lib/file-util';
import { IdleChecker } from './lib/idle-checker';
import { NotificationRequest } from '@ucap-webmessenger/native';
import { ElectronAppChannel } from '@ucap-webmessenger/electron-core';
let appWindow: AppWindow | null = null;
const launchTime = now();
let readyTime: number | null = null;
type OnDidLoadFn = (window: AppWindow) => void;
let onDidLoadFns: Array<OnDidLoadFn> | null = [];
let preventQuit = false;
let notificationService: ElectronNotificationService | null;
function handleUncaughtException(error: Error) {
preventQuit = true;
// If we haven't got a window we'll assume it's because
// we've just launched and haven't created it yet.
// It could also be because we're encountering an unhandled
// exception on shutdown but that's less likely and since
// this only affects the presentation of the crash dialog
// it's a safe assumption to make.
const isLaunchError = appWindow === null;
if (appWindow) {
appWindow.destroy();
appWindow = null;
}
showUncaughtException(isLaunchError, error);
}
function getUptimeInSeconds() {
return (now() - launchTime) / 1000;
}
process.on('uncaughtException', (error: Error) => {
// error = withSourceMappedStack(error);
// reportError(error, getExtraErrorContext());
handleUncaughtException(error);
});
let isDuplicateInstance = false;
const gotSingleInstanceLock = app.requestSingleInstanceLock();
isDuplicateInstance = !gotSingleInstanceLock;
let idle: IdleChecker | null;
app.on(ElectronAppChannel.SecondInstance, (event, args, workingDirectory) => {
// Someone tried to run a second instance, we should focus our window.
if (appWindow) {
if (appWindow.isMinimized()) {
appWindow.restore();
}
if (!appWindow.isVisible()) {
appWindow.show();
}
appWindow.focus();
}
});
if (isDuplicateInstance) {
app.quit();
}
function createWindow() {
const window = new AppWindow();
if (__DEV__) {
// const {
// default: installExtension,
// REDUX_DEVTOOLS
// } = require('electron-devtools-installer');
import('electron-debug').then(ed => {
ed.default({ showDevTools: true });
});
import('electron-devtools-installer').then(edi => {
const ChromeLens = {
id: 'idikgljglpfilbhaboonnpnnincjhjkd',
electron: '>=1.2.1',
2019-11-11 06:53:39 +00:00
};
const extensions = [edi.REDUX_DEVTOOLS, ChromeLens];
for (const extension of extensions) {
try {
edi.default(extension);
} catch (e) {
console.log(e);
}
}
});
}
window.onClose(() => {
appWindow = null;
if (!__DARWIN__ && !preventQuit) {
app.quit();
}
});
window.onDidLoad(() => {
window.show();
const fns = onDidLoadFns;
onDidLoadFns = null;
for (const fn of fns) {
fn(window);
}
});
window.load();
appWindow = window;
}
// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.on(ElectronAppChannel.Ready, () => {
if (isDuplicateInstance) {
return;
}
readyTime = now() - launchTime;
createWindow();
notificationService = new ElectronNotificationService({
width: 340,
height: 100,
padding: 0,
borderRadius: 0,
// appIcon: iconPath,
displayTime: 5000,
defaultStyleContainer: {},
defaultStyleAppIcon: { display: 'none' },
defaultStyleImage: {},
defaultStyleClose: {},
defaultStyleText: {},
2019-11-11 06:53:39 +00:00
});
notificationService.options.defaultWindow.webPreferences.preload = path.join(
__dirname,
'resources/notification/preload.js'
);
notificationService.templatePath = path.join(
__dirname,
'resources/notification/template.html'
);
ipcMain.on('uncaught-exception', (event: IpcMainEvent, error: Error) => {
handleUncaughtException(error);
});
ipcMain.on(
'send-error-report',
(
event: IpcMainEvent,
{ error, extra }: { error: Error; extra: { [key: string]: string } }
) => {}
);
});
// Quit when all windows are closed.
app.on(ElectronAppChannel.WindowAllClosed, () => {
// On OS X it is common for applications and their menu bar
// to stay active until the user quits explicitly with Cmd + Q
if (process.platform !== 'darwin') {
app.quit();
}
});
app.on(ElectronAppChannel.Activate, () => {
onDidLoad(window => {
window.show();
});
});
function onDidLoad(fn: OnDidLoadFn) {
if (onDidLoadFns) {
onDidLoadFns.push(fn);
} else {
if (appWindow) {
fn(appWindow);
}
}
}
ipcMain.on(UpdaterChannel.Check, (event: IpcMainEvent, ...args: any[]) => {
event.returnValue = false;
});
ipcMain.on(FileChannel.ReadFile, (event: IpcMainEvent, ...args: any[]) => {
try {
fse.readFile(root(args[0]), (err, data) => {
if (!!err) {
event.returnValue = null;
} else {
event.returnValue = new Blob([data]);
}
});
} catch (error) {
event.returnValue = null;
}
});
ipcMain.on(
FileChannel.SaveFile,
async (event: IpcMainEvent, ...args: any[]) => {
try {
const buffer: Buffer = args[0];
const fileName: string = args[1];
let savePath: string = path.join(
!!args[2] ? args[2] : DefaultFolder.downloads(),
fileName
);
savePath = await FileUtil.uniqueFileName(savePath);
fse.writeFile(savePath, buffer, err => {
if (!err) {
event.returnValue = savePath;
} else {
event.returnValue = undefined;
}
});
} catch (error) {
event.returnValue = undefined;
}
}
);
ipcMain.on(
IdleStateChannel.StartCheck,
(event: IpcMainEvent, ...args: any[]) => {
if (!!idle) {
idle.destoryChecker();
idle = null;
}
idle = new IdleChecker(appWindow.browserWindow); // default 10min
idle.startChecker();
}
);
ipcMain.on(
NotificationChannel.Notify,
(event: IpcMainEvent, ...args: any[]) => {
const noti: NotificationRequest = args[0];
notificationService.notify({
title: noti.title,
text: noti.contents,
image:
noti.image ||
path.join(__dirname, 'resources/notification/image/img_nophoto_50.png'),
sound: noti.useSound
? path.join(
'file://',
__dirname,
'resources/notification/sound/messageAlarm.mp3'
)
: '',
onClick: e => {
appWindow.browserWindow.webContents.send(
ChatChannel.OpenRoom,
noti.roomSeq
);
appWindow.show();
e.close();
},
2019-11-11 06:53:39 +00:00
});
}
);
ipcMain.on(
NotificationChannel.CloseAllNotify,
(event: IpcMainEvent, ...args: any[]) => {
console.log('Channel.closeAllNotify', args);
}
);