main folder is removed

This commit is contained in:
병준 박 2019-11-11 16:00:26 +09:00
parent fe1ebca2b5
commit bed06e0f71
41 changed files with 0 additions and 1411 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 504 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 897 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 117 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 105 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 842 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 643 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 226 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

View File

@ -1,143 +0,0 @@
'use strict';
const electron = require('electron');
const ipc = electron.ipcRenderer;
const winId = electron.remote.getCurrentWindow().id;
function setStyle(config) {
// Style it
let notiDoc = global.window.document;
let container = notiDoc.getElementById('container');
let appIcon = notiDoc.getElementById('appIcon');
let image = notiDoc.getElementById('image');
let close = notiDoc.getElementById('close');
let message = notiDoc.getElementById('message');
// Default style
setStyleOnDomElement(config.defaultStyleContainer, container);
// Size and radius
let style = {
height:
config.height -
2 * config.borderRadius -
2 * config.defaultStyleContainer.padding,
width:
config.width -
2 * config.borderRadius -
2 * config.defaultStyleContainer.padding,
borderRadius: config.borderRadius + 'px'
};
setStyleOnDomElement(style, container);
// Style appIcon or hide
if (config.appIcon) {
setStyleOnDomElement(config.defaultStyleAppIcon, appIcon);
appIcon.src = config.appIcon;
} else {
setStyleOnDomElement(
{
display: 'none'
},
appIcon
);
}
// Style image
setStyleOnDomElement(config.defaultStyleImage, image);
// Style close button
setStyleOnDomElement(config.defaultStyleClose, close);
// Remove margin from text p
setStyleOnDomElement(config.defaultStyleText, message);
}
function setContents(event, notificationObj) {
// sound
if (notificationObj.sound) {
// Check if file is accessible
try {
// If it's a local file, check it's existence
// Won't check remote files e.g. http://
if (
notificationObj.sound.match(/^file\:/) !== null ||
notificationObj.sound.match(/^\//) !== null
) {
let audio = new global.window.Audio(notificationObj.sound);
audio.play();
}
} catch (e) {
log(
'electron-notify: ERROR could not find sound file: ' +
notificationObj.sound.replace('file://', ''),
e,
e.stack
);
}
}
let notiDoc = global.window.document;
// Title
let titleDoc = notiDoc.getElementById('title');
titleDoc.innerHTML = notificationObj.title || '';
// message
let messageDoc = notiDoc.getElementById('message');
messageDoc.innerHTML = notificationObj.text || '';
// Image
let imageDoc = notiDoc.getElementById('image');
if (notificationObj.image) {
imageDoc.src = notificationObj.image;
} else {
setStyleOnDomElement({ display: 'none' }, imageDoc);
}
// Close button
let closeButton = notiDoc.getElementById('close');
closeButton.addEventListener('click', function(event) {
event.stopPropagation();
ipc.send('UCAP::ElectronNotification::close', winId, notificationObj);
});
// URL
let container = notiDoc.getElementById('container');
container.addEventListener('click', function() {
ipc.send('UCAP::ElectronNotification::click', winId, notificationObj);
});
}
function setStyleOnDomElement(styleObj, domElement) {
try {
for (let styleAttr in styleObj) {
domElement.style[styleAttr] = styleObj[styleAttr];
}
} catch (e) {
throw new Error(
'electron-notify: Could not set style on domElement',
styleObj,
domElement
);
}
}
function loadConfig(event, conf) {
setStyle(conf || {});
}
function reset() {
let notiDoc = global.window.document;
let container = notiDoc.getElementById('container');
let closeButton = notiDoc.getElementById('close');
// Remove event listener
let newContainer = container.cloneNode(true);
container.parentNode.replaceChild(newContainer, container);
let newCloseButton = closeButton.cloneNode(true);
closeButton.parentNode.replaceChild(newCloseButton, closeButton);
}
ipc.on('UCAP::ElectronNotification::BrowserWindowSetContents', setContents);
ipc.on('UCAP::ElectronNotification::loadConfig', loadConfig);
ipc.on('UCAP::ElectronNotification::reset', reset);
function log() {
console.log.apply(console, arguments);
}
delete global.require;
delete global.exports;
delete global.module;

View File

@ -1,130 +0,0 @@
html {
height: 100%;
overflow-y: scroll;
}
body {
position: relative;
width: 100%;
height: 100%;
padding: 0;
margin: 0;
color: #333;
font-family: '나눔고딕', Malgun Gothic, '맑은고딕', Arial, Dotum, '돋움',
Gulim, '굴림';
font-size: 12px;
line-height: 18px !important;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
body * {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
ul,
ol {
list-style: none;
margin: 0;
padding: 0;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
img {
border: none;
}
a:link,
a:visited,
a:hover,
a:active {
text-decoration: none;
}
.noti_messege {
width: 340px;
height: 100px;
border: 1px solid #666;
background-color: #fff;
box-shadow: 0px 0px 3px 0px #e7e7e7;
}
.info {
position: relative;
width: 100%;
height: 100%;
box-sizing: border-box;
padding: 16px 14px;
color: #fff;
}
.btn_close {
position: absolute;
z-index: 1;
right: 6px;
top: 6px;
width: 20px;
height: 20px;
background: url(../image/btn_close_gray.png) no-repeat 50% 50%;
}
.btn_close:hover {
opacity: 0.7;
}
.photo {
position: relative;
top: 0px;
right: 0;
bottom: 0;
left: 0;
margin: 4px 0;
width: 54px;
height: 54px;
border-radius: 50%;
background: #5bc1ff url(../image/img_nophoto_50.png) no-repeat 50% 50%;
border: 2px solid #ddd;
}
.info .profile {
position: absolute;
width: 60px;
text-align: center;
}
.photo img {
overflow: hidden;
width: 50px;
height: 50px;
border-radius: 50px;
}
.noti_messege .info .profile + div {
padding-left: 70px;
position: relative;
line-height: 180%;
height: 100%;
}
.sender {
font-size: 14px;
font-weight: bold;
margin-bottom: 4px;
color: #333;
width: 94%;
}
.sender .name {
color: #2e7fb5;
}
.message {
color: #666;
}
.ellipsis {
display: block;
text-overflow: ellipsis;
white-space: nowrap;
word-wrap: normal;
overflow: hidden;
}
.ellipsis_row2 {
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
word-wrap: break-word;
line-height: 1.6em;
height: 3.2em;
}

View File

@ -1,50 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD>
<title>[개발]M Messenger - 메시지 알림</title>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta charset="UTF-8" />
<link
type="text/css"
rel="stylesheet"
href="styles/noti_messege.css"
/>
</HEAD>
<style>
html,
body {
overflow-y: hidden;
overflow-x: hidden;
}
</style>
<BODY>
<div class="noti_messege" id="container">
<div class="info">
<a class="btn_close" id="close"></a>
<div class="profile">
<div class="photo">
<img src="" id="appIcon" />
<img
src=""
id="image"
onerror="this.src='image/img_nophoto_50.png';"
/>
</div>
</div>
<div>
<ul id="text">
<li class="sender ellipsis" id="title">
<span class="name">김 수안무 거북이와 두루미</span>님이 메시지를
보냈습니다.
</li>
<li class="message ellipsis_row2" id="message">
홍길동 대리(솔루션사업팀)홍길동 대리(솔루션사업팀)홍길동
대리(솔루션사업팀)홍길동 대리(솔루션사업팀)
</li>
</ul>
</div>
</div>
</div>
</BODY>
</HTML>

View File

@ -1,229 +0,0 @@
import * as path from 'path';
import * as url from 'url';
import { app, BrowserWindow, screen, ipcMain, IpcMainEvent } from 'electron';
import windowStateKeeper from 'electron-window-state';
import { EventEmitter } from 'events';
import { now } from '../util/now';
import { registerWindowStateChangedEvents } from '../lib/window-state';
import {
ElectronAppChannel,
ElectronBrowserWindowChannel,
ElectronWebContentsChannel
} from '@ucap-webmessenger/electron-core';
export class AppWindow {
private window: BrowserWindow | null = null;
private eventEmitter = new EventEmitter();
// tslint:disable-next-line: variable-name
private _loadTime: number | null = null;
// tslint:disable-next-line: variable-name
private _rendererReadyTime: number | null = null;
private minWidth = 960;
private minHeight = 660;
public constructor() {
const savedWindowState = windowStateKeeper({
defaultWidth: this.minWidth,
defaultHeight: this.minHeight
});
const windowOptions: Electron.BrowserWindowConstructorOptions = {
x: savedWindowState.x,
y: savedWindowState.y,
width: savedWindowState.width,
height: savedWindowState.height,
minWidth: this.minWidth,
minHeight: this.minHeight,
center: true,
// This fixes subpixel aliasing on Windows
// See https://github.com/atom/atom/commit/683bef5b9d133cb194b476938c77cc07fd05b972
backgroundColor: '#fff',
webPreferences: {
// Disable auxclick event
// See https://developers.google.com/web/updates/2016/10/auxclick
disableBlinkFeatures: 'Auxclick',
// Enable, among other things, the ResizeObserver
experimentalFeatures: true,
nodeIntegration: true
},
acceptFirstMouse: true,
icon: path.join(__dirname, 'resources/image', 'ico_64_64.png')
};
if (__DARWIN__) {
windowOptions.titleBarStyle = 'hidden';
} else if (__WIN32__) {
windowOptions.frame = false;
} else if (__LINUX__) {
windowOptions.icon = path.join(__dirname, 'static', 'icon-logo.png');
}
this.window = new BrowserWindow(windowOptions);
savedWindowState.manage(this.window);
let quitting = false;
app.on(ElectronAppChannel.BeforeQuit, () => {
quitting = true;
});
ipcMain.on(ElectronAppChannel.WillQuit, (event: IpcMainEvent) => {
quitting = true;
event.returnValue = true;
});
// on macOS, when the user closes the window we really just hide it. This
// lets us activate quickly and keep all our interesting logic in the
// renderer.
if (__DARWIN__) {
this.window.on(ElectronBrowserWindowChannel.Close, e => {
if (!quitting) {
e.preventDefault();
}
});
}
if (__WIN32__) {
// workaround for known issue with fullscreen-ing the app and restoring
// is that some Chromium API reports the incorrect bounds, so that it
// will leave a small space at the top of the screen on every other
// maximize
//
// adapted from https://github.com/electron/electron/issues/12971#issuecomment-403956396
//
// can be tidied up once https://github.com/electron/electron/issues/12971
// has been confirmed as resolved
this.window.once(ElectronBrowserWindowChannel.ReadyToShow, () => {
this.window.on(ElectronBrowserWindowChannel.Unmaximize, () => {
setTimeout(() => {
const bounds = this.window.getBounds();
bounds.width += 1;
this.window.setBounds(bounds);
bounds.width -= 1;
this.window.setBounds(bounds);
}, 5);
});
});
}
}
public load(): void {
let startLoad = 0;
this.window.webContents.once(
ElectronWebContentsChannel.DidStartLoading,
() => {
this._rendererReadyTime = null;
this._loadTime = null;
startLoad = now();
}
);
this.window.webContents.once(
ElectronWebContentsChannel.DidFinishLoad,
() => {
this.window.webContents.setVisualZoomLevelLimits(1, 1);
if (process.env.NODE_ENV === 'development') {
this.window.webContents.openDevTools();
}
this._loadTime = now() - startLoad;
}
);
this.window.webContents.on(ElectronWebContentsChannel.DidFailLoad, () => {
this.window.webContents.openDevTools();
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? */
private get rendererLoaded(): boolean {
return !!this.loadTime && !!this.rendererReadyTime;
}
public onClose(fn: () => void) {
this.window.on(ElectronBrowserWindowChannel.Closed, fn);
}
/**
* Register a function to call when the window is done loading. At that point
* the page has loaded and the renderer has signalled that it is ready.
*/
public onDidLoad(fn: () => void): EventEmitter {
return this.eventEmitter.on('did-load', fn);
}
public isMinimized() {
return this.window.isMinimized();
}
/** Is the window currently visible? */
public isVisible() {
return this.window.isVisible();
}
public restore() {
this.window.restore();
}
public focus() {
this.window.focus();
}
/** Show the window. */
public show() {
this.window.show();
}
/**
* Get the time (in milliseconds) spent loading the page.
*
* This will be `null` until `onDidLoad` is called.
*/
public get loadTime(): number | null {
return this._loadTime;
}
/**
* Get the time (in milliseconds) elapsed from the renderer being loaded to it
* signaling it was ready.
*
* This will be `null` until `onDidLoad` is called.
*/
public get rendererReadyTime(): number | null {
return this._rendererReadyTime;
}
public destroy() {
this.window.destroy();
}
public get browserWindow(): BrowserWindow | null {
return this.window;
}
}

View File

@ -1 +0,0 @@
export function showUncaughtException(isLaunchError: boolean, error: Error) {}

18
main/src/global.d.ts vendored
View File

@ -1,18 +0,0 @@
/* eslint-disable @typescript-eslint/interface-name-prefix */
/** Is the app running in dev mode? */
declare const __DEV__: boolean;
/** Is the app being built to run on Darwin? */
declare const __DARWIN__: boolean;
/** Is the app being built to run on Win32? */
declare const __WIN32__: boolean;
/** Is the app being built to run on Linux? */
declare const __LINUX__: boolean;
/**
* The currently executing process kind, this is specific to desktop
* and identifies the processes that we have.
*/
declare const __PROCESS_KIND__: 'main' | 'ui';

View File

@ -1,306 +0,0 @@
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
} 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'
};
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: {}
});
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: () => {
console.log('onClick');
}
});
console.log('Channel.notify', noti);
}
);
ipcMain.on(
NotificationChannel.CloseAllNotify,
(event: IpcMainEvent, ...args: any[]) => {
console.log('Channel.closeAllNotify', args);
}
);

View File

@ -1,37 +0,0 @@
import * as os from 'os';
import { execSync } from 'child_process';
import * as fse from 'fs-extra';
export class DefaultFolder {
static downloads(): string {
switch (os.platform()) {
case 'win32':
return `${process.env.USERPROFILE}/Downloads`;
case 'darwin':
return `${process.env.HOME}/Downloads`;
case 'linux': {
let dir: Buffer;
try {
dir = execSync('xdg-user-dir DOWNLOAD', { stdio: [0, 3, 3] });
} catch (_) {}
if (dir) {
return dir.toString('utf-8');
}
let stat: fse.Stats;
const homeDownloads = `${process.env.HOME}/Downloads`;
try {
stat = fse.statSync(homeDownloads);
} catch (_) {}
if (stat) {
return homeDownloads;
}
return '/tmp/';
}
default:
break;
}
}
}

View File

@ -1,222 +0,0 @@
import * as path from 'path';
import * as fse from 'fs-extra';
/**
*
* separator
* If the specified filename exists, the separator will be added before the incremental value such as: file{separator}2.jpg
* The default value is '-'.
*
* mode
* The mode allows you to specify which characters to use to generate the incremental value (the string after the separator)
* The default value is 'numeric'.
* 'numeric' Using the following characters: 1234567890
* 'alpha' Using the following characters: abcdefghijklmnopqrstuvwxyz
* 'ALPHA' Using the following characters: ABCDEFGHIJKLMNOPQRSTUVWXYZ
* 'alphanumeric' Using the following characters: 0123456789abcdefghijklmnopqrstuvwxyz
* 'ALPHANUMERIC' Using the following characters: 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ
* 'charset' You must specify the characters you wish to use in the charset option
*
* paddingCharacter && paddingSize
* If you wish to left-pad the incremental values with a character, use this option. Here's an example :
* var uniquefilename = require('uniquefilename');
* options = {mode: 'alpha', paddingCharacter: '0', paddingSize: 3};
* uniquefilename.get('/path/to/dir/file.jpg', options, function(filename) {
* // filename might be "/path/to/dir/file.jpg",
* // "/path/to/dir/file-002.jpg", "/path/to/dir/file-045.jpg", etc...
* // depending on the files that exist on your filesystem
* });
*
* alwaysAppend
* If alwaysAppend is true filenames will include the separator and attachment from the first request.
* So instead of file.jpg, file-2.jpg you'd get file-1.jpg, file-2.jpg.
*/
export interface UniqueFileNameOption {
separator?: string;
mode?:
| 'numeric'
| 'alpha'
| 'ALPHA'
| 'alphanumeric'
| 'ALPHANUMERIC'
| 'charset';
paddingCharacter?: string;
paddingSize?: number;
alwaysAppend?: boolean;
charset?: string;
}
const charsets = {
alpha: 'abcdefghijklmnopqrstuvwxyz',
alphanumeric: '0123456789abcdefghijklmnopqrstuvwxyz',
ALPHA: 'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
ALPHANUMERIC: '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'
};
interface UniqueFile {
dir?: string;
ext?: string;
base?: string;
increment?: number;
}
export class FileUtil {
static blobToBuffer(blob: Blob): Promise<Buffer> {
if (typeof Blob === 'undefined' || !(blob instanceof Blob)) {
throw new Error('first argument must be a Blob');
}
return new Promise<Buffer>((resolve, reject) => {
const reader = new FileReader();
reader.onloadend = () => {
resolve(Buffer.from(reader.result as ArrayBuffer));
};
reader.onerror = () => {
reader.abort();
reject(reader.error);
};
reader.readAsArrayBuffer(blob);
});
}
static uniqueFileName(
filePath: string,
options?: UniqueFileNameOption
): Promise<string> {
return new Promise<string>((resolve, reject) => {
const dir = path.dirname(filePath);
const ext = path.extname(filePath);
const base = path.basename(filePath, ext);
const uniqueFile: UniqueFile = {
dir,
ext,
base
};
options = options || {};
options.separator = options.separator || '-';
options.mode = options.mode || 'numeric';
if ('numeric' !== options.mode) {
if (charsets[options.mode]) {
options.charset = charsets[options.mode];
options.mode = 'charset';
} else if (
'charset' !== options.mode ||
('charset' === options.mode && !options.charset)
) {
options.mode = 'numeric';
}
}
if (options.paddingSize && !options.paddingCharacter) {
options.paddingCharacter = '0';
}
FileUtil.uniqueFileNameProcess(
uniqueFile,
options,
(fileName: string) => {
resolve(fileName);
}
);
});
}
private static uniqueFileNameProcess(
uniqueFile: UniqueFile,
options: UniqueFileNameOption,
callback: (fileName: string) => void
) {
let fileName: string;
let append = '';
if (options.alwaysAppend && !uniqueFile.increment) {
uniqueFile.increment = 1;
}
if (uniqueFile.increment) {
if ('numeric' === options.mode) {
append = '' + uniqueFile.increment;
} else {
append = FileUtil.numberToString(uniqueFile.increment, options.charset);
}
if (options.paddingSize) {
while (append.length < options.paddingSize) {
append = options.paddingCharacter + append;
}
}
append = options.separator + append;
}
fileName = path.join(
uniqueFile.dir,
uniqueFile.base + append + uniqueFile.ext
);
if (fse.existsSync(fileName)) {
if (uniqueFile.increment) {
uniqueFile.increment += 1;
} else {
uniqueFile.increment = 'numeric' === options.mode ? 2 : 1;
}
return FileUtil.uniqueFileNameProcess(uniqueFile, options, callback);
} else {
return callback(fileName);
}
}
private static numberToString(nbr: number, charset: string) {
const charsetLen = charset.length;
let strLen = 0;
let strThisLen = 0;
let tmp: number;
for (let maxpower = 20; maxpower >= 0; maxpower--) {
const maxvalue = FileUtil.sumOfPowerFromOne(charsetLen, maxpower);
if (maxvalue < nbr) {
strLen = maxpower + 1;
strThisLen = maxvalue + Math.pow(charsetLen, maxpower + 1) - maxvalue;
break;
}
}
if (0 === strLen) {
return null;
}
let str = '';
while (--strLen >= 0) {
if (strLen === 0) {
str += charset.charAt(nbr - 1);
break;
}
strThisLen = Math.pow(charsetLen, strLen);
const initial = FileUtil.sumOfPowerFromOne(charsetLen, strLen - 1);
for (tmp = charsetLen; tmp >= 1; tmp--) {
if (initial + tmp * strThisLen < nbr) {
break;
}
}
nbr -= tmp * strThisLen;
str += charset.charAt(tmp - 1);
}
return str;
}
private static sumOfPowerFromOne(base: number, maxpower: number) {
let value = 0;
for (let tmp = maxpower; tmp >= 1; tmp--) {
value += Math.pow(base, tmp);
}
return value;
}
}

View File

@ -1,72 +0,0 @@
import { powerMonitor, BrowserWindow } from 'electron';
import { IdleStateChannel } 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(IdleStateChannel.Changed, this.status);
}
} else {
if (this.status === IdleType.IDLE) {
this.status = IdleType.ACTIVE;
// TODO :: USER_STATUS chage online
this.window.webContents.send(IdleStateChannel.Changed, 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,99 +0,0 @@
import Store from 'electron-store';
const STORE_KEY_AUTORUN = 'options.autoRun';
const STORE_KEY_AUTOLOGIN = 'options.autoLogin';
const STORE_KEY_STARTUPHIDEWINDOW = 'options.startupHideWindow';
const STORE_KEY_LOGINCOMPANY = 'login.loginCompany';
const STORE_KEY_LOGINID = 'login.loginId';
const STORE_KEY_LOGINPW = 'login.loginPw';
export class Storage extends Store<any> {
constructor() {
super({
schema: {
options: {
type: 'object',
properties: {
autoRun: {
type: 'boolean'
},
autoLogin: {
type: 'boolean'
},
startupHideWindow: {
type: 'boolean'
}
},
default: {
autoRun: false,
autoLogin: false,
startupHideWindow: false
}
},
login: {
type: 'object',
properties: {
loginCompany: {
type: 'string'
},
loginId: {
type: 'string'
},
loginPw: {
type: 'string'
}
},
default: {
loginCompany: '',
loginId: '',
loginPw: ''
}
}
},
encryptionKey: 'ucap',
fileExtension: 'dat'
});
}
get autoRun(): boolean {
return this.get(STORE_KEY_AUTORUN, false);
}
set autoRun(autoRun: boolean) {
this.set(STORE_KEY_AUTORUN, autoRun);
}
get autoLogin(): boolean {
return this.get(STORE_KEY_AUTOLOGIN, false);
}
set autoLogin(autoLogin: boolean) {
this.set(STORE_KEY_AUTOLOGIN, autoLogin);
}
get startupHideWindow(): boolean {
return this.get(STORE_KEY_STARTUPHIDEWINDOW, false);
}
set startupHideWindow(startupHideWindow: boolean) {
this.set(STORE_KEY_STARTUPHIDEWINDOW, startupHideWindow);
}
get loginCompany(): string {
return this.get(STORE_KEY_LOGINCOMPANY, false);
}
set loginCompany(loginCompany: string) {
this.set(STORE_KEY_LOGINCOMPANY, loginCompany);
}
get loginId(): string {
return this.get(STORE_KEY_LOGINID, false);
}
set loginId(loginId: string) {
this.set(STORE_KEY_LOGINID, loginId);
}
get loginPw(): string {
return this.get(STORE_KEY_LOGINPW, false);
}
set loginPw(loginPw: string) {
this.set(STORE_KEY_LOGINPW, loginPw);
}
}

View File

@ -1,54 +0,0 @@
import { BrowserWindow } from 'electron';
import { WindowState } from '@ucap-webmessenger/native';
import { WindowStateChannel } from '@ucap-webmessenger/native-electron';
import { ElectronBrowserWindowChannel } from '@ucap-webmessenger/electron-core';
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(ElectronBrowserWindowChannel.EnterFullScreen, () =>
sendWindowStateEvent(window, WindowState.FullScreen)
);
window.on(ElectronBrowserWindowChannel.LeaveFullScreen, () =>
sendWindowStateEvent(window, WindowState.Normal)
);
window.on(ElectronBrowserWindowChannel.Maximize, () =>
sendWindowStateEvent(window, WindowState.Maximized)
);
window.on(ElectronBrowserWindowChannel.Minimize, () =>
sendWindowStateEvent(window, WindowState.Minimized)
);
window.on(ElectronBrowserWindowChannel.Unmaximize, () =>
sendWindowStateEvent(window, WindowState.Normal)
);
window.on(ElectronBrowserWindowChannel.Restore, () =>
sendWindowStateEvent(window, WindowState.Normal)
);
window.on(ElectronBrowserWindowChannel.Hide, () =>
sendWindowStateEvent(window, WindowState.Hidden)
);
window.on(ElectronBrowserWindowChannel.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(WindowStateChannel.Changed, windowState);
}

View File

@ -1,4 +0,0 @@
export function now(): number {
const time = process.hrtime();
return time[0] * 1000 + time[1] / 1000000;
}

View File

@ -1,11 +0,0 @@
import * as path from 'path';
// tslint:disable-next-line: variable-name
const _root = __DEV__
? path.resolve(__dirname, '..', '..')
: path.resolve(__dirname);
export function root(...paths: string[]) {
const args = Array.prototype.slice.call(paths, 0);
return path.join.apply(path, [_root].concat(args));
}

View File

@ -1,35 +0,0 @@
{
"compilerOptions": {
"baseUrl": "./",
"outDir": "../dist/main",
"sourceMap": true,
"declaration": false,
"module": "commonjs",
"moduleResolution": "node",
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"esModuleInterop": true,
"target": "es5",
"types": ["node"],
"lib": ["es2017", "es2016", "es2015", "dom"],
"paths": {
"@ucap-webmessenger/electron-core": [
"../projects/ucap-webmessenger-electron-core/src/public-api"
],
"@ucap-webmessenger/electron-notification": [
"../projects/ucap-webmessenger-electron-notification/src/public-api"
],
"@ucap-webmessenger/native": [
"../projects/ucap-webmessenger-native/src/public-api"
],
"@ucap-webmessenger/native-electron": [
"../projects/ucap-webmessenger-native-electron/src/public-api"
],
"@ucap-webmessenger/electron": [
"../projects/ucap-webmessenger-electron/src/public-api"
]
}
},
"exclude": ["../node_modules", "**/*.spec.ts"]
}