Skip to content

Commit ed69ae1

Browse files
committed
Removed direct file access from view.
1 parent ae60cb5 commit ed69ae1

21 files changed

+158
-102
lines changed

.stylelintrc.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
"selector-pseudo-class-no-unknown": [
1010
true,
1111
{
12-
"ignorePseudoClasses": ["horizontal", "vertical"]
12+
"ignorePseudoClasses": ["global", "horizontal", "vertical"]
1313
}
1414
]
1515
},

package.json

+1
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@
8787
"classnames": "^2.2.6",
8888
"debug": "^4.1.1",
8989
"del": "^5.1.0",
90+
"glob": "^7.1.6",
9091
"id3js": "2.1.1",
9192
"immer": "^6.0.6",
9293
"immutable": "^4.0.0-rc.12",

src/actions/app.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ export function initApp() {
7777
};
7878
}
7979

80-
export function saveImage(file) {
80+
export function saveImage() {
8181
return async dispatch => {
8282
const { filePath, canceled } = await api.showSaveDialog({
8383
defaultPath: `image-${Date.now()}.png`,
@@ -91,7 +91,7 @@ export function saveImage(file) {
9191

9292
const buffer = stage.getImage();
9393

94-
await api.writeFile(file, buffer);
94+
await api.saveImageFile(filePath, buffer);
9595

9696
logger.log('Image saved:', filePath);
9797
} catch (error) {

src/actions/audio.js

+2-6
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
import { createSlice } from '@reduxjs/toolkit';
2-
import path from 'path';
32
import { api, analyzer, logger, player } from 'view/global';
43
import { setStatusText } from 'actions/app';
54
import { raiseError } from 'actions/errors';
6-
import { blobToArrayBuffer, dataToBlob } from 'utils/data';
75
import { loadAudioData } from 'utils/audio';
86
import { trimChars } from 'utils/string';
97

@@ -34,10 +32,8 @@ export function loadAudioFile(file, play) {
3432
logger.time('audio-file-load');
3533

3634
try {
37-
const fileData = await api.readFile(file);
38-
const blob = await dataToBlob(fileData, path.extname(file));
39-
const arrayBuffer = await blobToArrayBuffer(blob);
40-
const audio = await loadAudioData(arrayBuffer);
35+
const data = await api.readAudioFile(file);
36+
const audio = await loadAudioData(data);
4137
const duration = audio.getDuration();
4238

4339
player.load(audio);

src/actions/project.js

+7-23
Original file line numberDiff line numberDiff line change
@@ -149,30 +149,14 @@ export function checkUnsavedChanges(menuAction, action) {
149149

150150
export function loadProjectFile(file) {
151151
return async dispatch => {
152-
function loadData(data) {
153-
dispatch(loadProject(JSON.parse(data)));
154-
155-
dispatch(loadScenes());
156-
157-
dispatch(updateProject({ file, opened: Date.now(), lastModified: 0 }));
158-
}
159-
160-
function handleError(error) {
161-
dispatch(raiseError('Invalid project file.', error));
162-
}
163-
164152
try {
165-
const data = await api.readFileCompressed(file);
153+
const data = await api.loadProjectFile(file);
166154

167-
loadData(data);
168-
} catch (error) {
169-
if (error.message.indexOf('incorrect header check') > -1) {
170-
const data = await api.readFile(file);
171-
172-
loadData(data).catch(handleError);
173-
} else {
174-
handleError(error);
175-
}
155+
await dispatch(loadProject(data));
156+
await dispatch(loadScenes());
157+
await dispatch(updateProject({ file, opened: Date.now(), lastModified: 0 }));
158+
} catch (e) {
159+
return dispatch(raiseError('Invalid project file.', e));
176160
}
177161
};
178162
}
@@ -188,7 +172,7 @@ export function saveProjectFile(file) {
188172
};
189173

190174
try {
191-
await api.writeFileCompressed(file, JSON.stringify(data));
175+
await api.saveProjectFile(file, data);
192176

193177
logger.log('Project saved:', file, data);
194178

src/core/Process.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,10 @@ export default class Process extends EventEmitter {
1313

1414
const handlers = {
1515
onStdOut: data => {
16-
this.emit('data', data);
16+
this.emit('stdout', data);
1717
},
1818
onStdErr: data => {
19-
this.emit('data', data);
19+
this.emit('stderr', data);
2020
},
2121
onClose: (code, signal) => {
2222
logger.log('Process ended with code', code, 'and signal', signal);

src/main/api/files.js

+51
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import path from 'path';
2+
import { readFile, readFileCompressed, writeFile, writeFileCompressed } from 'utils/io';
3+
import { blobToArrayBuffer, blobToDataUrl, dataToBlob } from 'utils/data';
4+
5+
export async function loadProjectFile(file) {
6+
try {
7+
const data = await readFileCompressed(file);
8+
9+
return JSON.parse(data);
10+
} catch (error) {
11+
if (error.message.indexOf('incorrect header check') > -1) {
12+
const data = readFile(file);
13+
14+
return JSON.parse(data);
15+
}
16+
}
17+
}
18+
19+
export async function saveProjectFile(file, data) {
20+
if (path.extname(file) === '.afx') {
21+
return writeFileCompressed(file, JSON.stringify(data));
22+
}
23+
}
24+
25+
export async function saveImageFile(file, data) {
26+
if (['.jpg', '.png', '.gif'].includes(path.extname(file))) {
27+
return writeFile(file, data);
28+
}
29+
}
30+
31+
export async function readImageFile(file) {
32+
const fileData = await readFile(file);
33+
const blob = await dataToBlob(fileData, path.extname(file));
34+
35+
if (!/^image/.test(blob.type)) {
36+
throw new Error('Invalid image file.');
37+
}
38+
39+
return blobToDataUrl(blob);
40+
}
41+
42+
export async function readAudioFile(file) {
43+
const fileData = await readFile(file);
44+
const blob = await dataToBlob(fileData, path.extname(file));
45+
46+
if (!/^audio/.test(blob.type)) {
47+
throw new Error('Invalid audio file.');
48+
}
49+
50+
return blobToArrayBuffer(blob);
51+
}

src/main/api/index.js

+7-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
export { loadAudioTags } from 'main/api/audio';
22
export { loadConfig, saveConfig } from 'main/api/config';
3+
export {
4+
loadProjectFile,
5+
saveProjectFile,
6+
readImageFile,
7+
saveImageFile,
8+
readAudioFile,
9+
} from 'main/api/files';
310
export { send, on, once, off, invoke } from 'main/api/ipc';
411
export { spawnProcess } from 'main/api/process';
512
export { getEnvironment } from 'main/api/remote';
@@ -12,4 +19,3 @@ export {
1219
showOpenDialog,
1320
showSaveDialog,
1421
} from 'main/api/window';
15-
export { readFile, readFileCompressed, writeFile, writeFileCompressed, removeFile } from 'utils/io';

src/main/index.js

+4-37
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
1-
import { app, systemPreferences, session, BrowserWindow } from 'electron';
2-
import fs from 'fs';
1+
import { app, BrowserWindow } from 'electron';
32
import debug from 'debug';
43
import * as env from './environment';
5-
import initMenu from './menu';
6-
import initAutoUpdate from './autoupdate';
4+
import init from './init';
75
import { createWindow, disposeWindow } from './window';
86

97
const log = debug('main');
@@ -14,18 +12,6 @@ log('NODE_ENV', process.env.NODE_ENV);
1412
// Set global variables
1513
global.env = env;
1614

17-
// Create temp folder for application
18-
function createTempFolder() {
19-
try {
20-
fs.mkdirSync(env.TEMP_PATH);
21-
log('Temp folder created:', env.TEMP_PATH);
22-
} catch (err) {
23-
if (err.code !== 'EEXIST') {
24-
log('ERROR:', err.message);
25-
}
26-
}
27-
}
28-
2915
// Chrome flags
3016
// Hardware acceleration
3117
app.commandLine.appendSwitch('ignore-gpu-blacklist');
@@ -36,29 +22,10 @@ if (process.env.NODE_ENV !== 'production') {
3622
}
3723

3824
// Application events
39-
app.on('ready', () => {
25+
app.on('ready', async () => {
4026
log('ready');
4127

42-
initMenu();
43-
initAutoUpdate();
44-
45-
// Modify the user agent for all requests to the following urls
46-
const filter = {
47-
urls: ['https://*.astrofox.io/*'],
48-
};
49-
50-
session.defaultSession.webRequest.onBeforeSendHeaders(filter, (details, callback) => {
51-
details.requestHeaders['User-Agent'] = env.USER_AGENT;
52-
callback({ cancel: false, requestHeaders: details.requestHeaders });
53-
});
54-
55-
// Disable menu items on macOS
56-
if (process.platform === 'darwin') {
57-
systemPreferences.setUserDefault('NSDisabledDictationMenuItem', 'boolean', true);
58-
systemPreferences.setUserDefault('NSDisabledCharacterPaletteMenuItem', 'boolean', true);
59-
}
60-
61-
createTempFolder();
28+
await init();
6229

6330
createWindow();
6431
});

src/main/init.js

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import { session, systemPreferences } from 'electron';
2+
import path from 'path';
3+
import glob from 'glob';
4+
import debug from 'debug';
5+
import { removeFile, createFolder } from 'utils/io';
6+
import * as env from './environment';
7+
import initMenu from './menu';
8+
import initAutoUpdate from './autoupdate';
9+
10+
const log = debug('init');
11+
12+
async function removeTempFiles() {
13+
const files = glob.sync('*.*', { cwd: env.TEMP_PATH });
14+
15+
files.forEach(file => removeFile(path.join(env.TEMP_PATH, file)));
16+
}
17+
18+
export default async function init() {
19+
log('Initialize application');
20+
21+
await createFolder(env.TEMP_PATH);
22+
await removeTempFiles();
23+
24+
initMenu();
25+
initAutoUpdate();
26+
27+
// Modify the user agent for all requests to the following urls
28+
const filter = {
29+
urls: ['https://*.astrofox.io/*'],
30+
};
31+
32+
session.defaultSession.webRequest.onBeforeSendHeaders(filter, (details, callback) => {
33+
details.requestHeaders['User-Agent'] = env.USER_AGENT;
34+
callback({ cancel: false, requestHeaders: details.requestHeaders });
35+
});
36+
37+
// Disable menu items on macOS
38+
if (process.platform === 'darwin') {
39+
systemPreferences.setUserDefault('NSDisabledDictationMenuItem', 'boolean', true);
40+
systemPreferences.setUserDefault('NSDisabledCharacterPaletteMenuItem', 'boolean', true);
41+
}
42+
}

src/video/AudioProcess.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ export default class AudioProcess extends Process {
4444
});
4545

4646
this.on('stderr', data => {
47-
this.emit('data', data);
47+
this.emit('output', data);
4848
});
4949

5050
const args = ['-y', '-i', audioFile, '-ss', timeStart, '-t', duration, '-c:a', codec];

src/video/MergeProcess.js

+4-4
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,19 @@ import Process from 'core/Process';
33
export default class MergeProcess extends Process {
44
start(videoFile, audioFile, outputFile) {
55
return new Promise((resolve, reject) => {
6-
this.on('close', (code) => {
6+
this.on('close', code => {
77
if (code !== 0) {
88
reject(new Error('Process was terminated.'));
99
}
1010
resolve();
1111
});
1212

13-
this.on('error', (err) => {
13+
this.on('error', err => {
1414
reject(err);
1515
});
1616

17-
this.on('stderr', (data) => {
18-
this.emit('data', data);
17+
this.on('stderr', data => {
18+
this.emit('output', data);
1919
});
2020

2121
super.start([

src/video/RenderProcess.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ export default class RenderProcess extends Process {
2424
});
2525

2626
this.on('stderr', data => {
27-
this.emit('data', data);
27+
this.emit('output', data);
2828
});
2929

3030
const args = [

src/video/VideoRenderer.js

+6-12
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@ export default class VideoRenderer extends EventEmitter {
1717
this.audioProcess = new AudioProcess(FFMPEG_PATH);
1818
this.mergeProcess = new MergeProcess(FFMPEG_PATH);
1919

20-
this.renderProcess.on('data', data => {
21-
logger.log(data.toString());
20+
this.renderProcess.on('output', data => {
21+
logger.log(data);
2222

2323
// Start requesting frames
2424
if (!this.started) {
@@ -27,12 +27,12 @@ export default class VideoRenderer extends EventEmitter {
2727
}
2828
});
2929

30-
this.audioProcess.on('data', data => {
31-
logger.log(data.toString());
30+
this.audioProcess.on('output', data => {
31+
logger.log(data);
3232
});
3333

34-
this.mergeProcess.on('data', data => {
35-
logger.log(data.toString());
34+
this.mergeProcess.on('output', data => {
35+
logger.log(data);
3636
});
3737
}
3838

@@ -95,12 +95,6 @@ export default class VideoRenderer extends EventEmitter {
9595
// Merge audio and video
9696
this.currentProcess = mergeProcess;
9797
await mergeProcess.start(outputVideoFile, outputAudioFile, videoFile);
98-
99-
// Remove temp files
100-
if (process.env.NODE_ENV === 'production') {
101-
await api.removeFile(outputVideoFile);
102-
await api.removeFile(outputAudioFile);
103-
}
10498
} catch (error) {
10599
logger.error(error);
106100

0 commit comments

Comments
 (0)