-
Notifications
You must be signed in to change notification settings - Fork 14
/
main.js
184 lines (164 loc) · 4.58 KB
/
main.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
const menubar = require('menubar');
const fs = require('fs');
const path = require('path');
const notifier = require('node-notifier');
const { ipcMain, clipboard, Menu } = require('electron');
const configService = require('./ConfigurationService');
const S3Service = require('./S3Service');
/**
* Electron window high-level wrapped constructor.
*/
const mb = menubar({
width: 400,
height: 300,
});
let s3 = null;
/**
* Sends data from main Electron process to renderer process.
* Works only if window has been instantiated first.
* @param thread
* @param data
*/
const sendWebContentsMessage = (thread, data) => {
if (mb.window !== undefined) {
mb.window.webContents.send(thread, {
data,
});
} else {
console.warn('mb.window is not defined, sending message ignored...');
}
};
/**
* Sends OS-level native notification invoker
* @param title
* @param message
*/
const sendNotification = (title, message) => {
notifier.notify({
title,
message,
});
};
/**
* S3.ManagedUpload high-level wrapper.
*
* Forwards EventEmitter events to IPC Bus to renderer process.
* Sends notification if process fails or succeeds.
* Automatically replaces clipboard contents with URL to file in AWS S3.
*
* @param uploadEventEmitter
* @param file
*/
const handleUpload = (uploadEventEmitter, file) => {
sendWebContentsMessage('UPLOAD_START', file);
uploadEventEmitter.on('error', (error) => {
sendNotification('Upload Error!', 'Click icon for more details...');
sendWebContentsMessage('UPLOAD_ERROR', error);
});
uploadEventEmitter.on('progress', (data) => {
sendWebContentsMessage('UPLOAD_PROGRESS', data);
});
uploadEventEmitter.on('success', (data) => {
clipboard.writeText(data.Location);
sendNotification('File Uploaded!', 'Link has been copied to clipboard');
sendWebContentsMessage('UPLOAD_SUCCESS', data);
});
};
/**
* Function returns Promise resolved if supplied path is directory (contains files inside this
* directory) or rejected if it's file.
* @param file
*/
const checkForDirectory = (file) => new Promise((resolve, reject) => {
fs.stat(file, (err, stats) => {
if (err) {
throw new Error(err);
} else if (stats.isDirectory()) {
fs.readdir(file, (error, files) => {
if (err) {
throw new Error(error);
}
return resolve(files.map((node) => path.join(file, node)));
});
} else {
return reject();
}
});
});
/**
* Reads file and passes it's binary data for upload.
* @param file
*/
const readFileAndUpload = (file) => {
fs.readFile(file, (err, data) => {
if (err) throw new Error(err);
handleUpload(s3.uploadFile(file.split('/').pop(), data), file);
});
};
/**
* Callback function for handling drop-files events.
*
* Takes array of files (directories) as argument and processes sequentially for upload.
*
* Fails if S3Service has been not initialized yet.
* @param files
*/
const handleFiles = (files) => {
if (s3 !== null) {
files.forEach((file) => {
checkForDirectory(file)
.then((dirFiles) => handleFiles(dirFiles))
.catch(() => readFileAndUpload(file));
});
} else {
throw new Error('Client has been not initialized yet!');
}
};
/**
* MenuBar EventEmitter listener.
*
* Listens for window readiness and loads config from file.
* If config is present, instantiates S3Service basing on that information.
*/
mb.on('ready', () => {
const template = [{label: 'Actions', submenu: [{role: "paste"}, {role: "quit"}]}];
const menu = Menu.buildFromTemplate(template);
//Menu.setApplicationMenu(menu);
configService.loadConfig()
.then((config) => {
if (config.bucket !== null) {
s3 = new S3Service(config.accessKey, config.secretKey);
} else {
throw new Error('Not ready for uploading, please configure tool first.');
}
})
.catch(() => {
throw new Error('Error while loading configuration');
});
mb.tray.on('drop-files', (event, files) => handleFiles(files));
});
/**
* IPC EventEmitter listener.
* Receiver of events from renderer process.
*/
ipcMain.on('GET_BUCKETS', (event, arg) => {
s3 = new S3Service(arg.accessKey, arg.secretKey);
s3.getBuckets().then((data) => {
event.sender.send('GET_BUCKETS_REPLY', {
success: true,
data,
});
configService.updateConfig(arg);
}).catch((error) => {
event.sender.send('GET_BUCKETS_REPLY', {
success: false,
error,
});
});
});
ipcMain.on('UPDATE_CONFIG', (event, arg) => {
configService.updateConfig(arg);
});
ipcMain.on('DROP_FILES', (event, arg) => {
handleFiles(arg.files);
});