Skip to content

Commit

Permalink
feat: add export and delete
Browse files Browse the repository at this point in the history
also fixes loading unsupported archives

close #5
  • Loading branch information
hassan committed Dec 14, 2018
1 parent 6cfde66 commit a8d64e4
Show file tree
Hide file tree
Showing 14 changed files with 618 additions and 128 deletions.
5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,17 +22,19 @@
"dependencies": {
"@material-ui/core": "3.5.1",
"@material-ui/icons": "3.0.1",
"archiver": "3.0.0",
"classnames": "2.2.6",
"connected-react-router": "5.0.1",
"electron": "3.0.10",
"electron-devtools-installer": "2.2.4",
"electron-dl": "1.12.0",
"electron-is-dev": "1.0.1",
"electron-publisher-s3": "20.17.2",
"extract-zip": "1.6.7",
"fs-extra": "7.0.1",
"history": "4.7.2",
"immutable": "4.0.0-rc.12",
"is-online": "8.0.0",
"ncp": "2.0.0",
"prop-types": "15.6.2",
"react": "16.6.3",
"react-dev-utils": "6.1.1",
Expand All @@ -52,6 +54,7 @@
"concurrently": "4.1.0",
"cross-env": "5.2.0",
"electron-builder": "20.36.2",
"electron": "3.0.10",
"eslint-config-airbnb": "17.1.0",
"react-scripts": "2.1.1",
"version-bump-prompt": "4.2.1"
Expand Down
250 changes: 199 additions & 51 deletions public/electron.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,22 @@ const isDev = require('electron-is-dev');
const fs = require('fs');
const isOnline = require('is-online');
const fsPromises = fs.promises;
const fse = require('fs-extra');
const electronDl = require('electron-dl');
const { download } = electronDl;
const extract = require('extract-zip');
const archiver = require('archiver');
const { ncp } = require('ncp');


let mainWindow;

const savedSpacesPath = app.getPath('userData') + '/.meta';
const spacesFileName = 'spaces.json';
const ERROR_ZIP_CORRUPTED = 'ERROR_ZIP_CORRUPTED';
const ERROR_JSON_CORRUPTED = 'ERROR_JSON_CORRUPTED';
const ERROR_SPACE_ALREADY_AVAILABLE = 'ERROR_SPACE_ALREADY_AVAILABLE';
const ERROR_GENERAL = 'ERROR_GENERAL';

createWindow = () => {
mainWindow = new BrowserWindow({
Expand Down Expand Up @@ -67,11 +75,19 @@ createWindow = () => {
});
};

handleLoad = () => {
console.log('que vidinha');
};

generateMenu = () => {
const template = [
{
label: 'File',
submenu: [{ label: 'Load Space', click() { app.quit() }}, { role: 'about' }, { role: 'quit' }],
submenu: [{
label: 'Load Space',
click() { this.handleLoad() }},
{ role: 'about' },
{ role: 'quit' }],
},
{type:'separator'},
{
Expand All @@ -96,6 +112,7 @@ generateMenu = () => {
{ role: 'toggledevtools' },
{ type: 'separator' },
{ role: 'resetzoom' },
{ role: 'resetzoom' },
{ role: 'zoomin' },
{ role: 'zoomout' },
{ type: 'separator' },
Expand Down Expand Up @@ -137,7 +154,7 @@ app.on('ready', () => {
generateMenu();
ipcMain.on('space:get', async (event, { id, spaces }) => {
try {
const space = spaces.find(el => el.id === Number(id));
const space = spaces.find(el => Number(el.id) === Number(id));
const { phases } = space;
for (const phase of phases) {
const { items = [] } = phase;
Expand All @@ -164,16 +181,17 @@ app.on('ready', () => {
.catch(console.log('error'));
} else {
mainWindow.webContents.send(
'space:gotten',
1
'space:get',
ERROR_GENERAL

);
}
}
}
}
}
mainWindow.webContents.send(
'space:gotten',
'space:get',
space
);
} catch (err) {
Expand All @@ -182,7 +200,7 @@ app.on('ready', () => {
});
ipcMain.on('spaces:get', () => {
let spaces = [];
const spacesPath = `${savedSpacesPath}/ss.json`;
const spacesPath = `${savedSpacesPath}/${spacesFileName}`;
fs.readFile(spacesPath, 'utf8', (err, data) => {
// we dont have saved spaces yet
if (err) {
Expand All @@ -199,84 +217,214 @@ app.on('ready', () => {
}
});
});
ipcMain.on('space:delete', async (event, { id }) => {
try {
let spaces = [];
const spacesPath = `${savedSpacesPath}/${spacesFileName}`;
fs.readFile(spacesPath, 'utf8', async (err, data) => {
if (err) {
mainWindow.webContents.send(
'space:deleted',
ERROR_GENERAL
);
} else {
spaces = JSON.parse(data);
const newSpaces = spaces.filter(el => Number(el.id) !== Number(id));
const spacesString = JSON.stringify(newSpaces);
await fsPromises.writeFile(`${savedSpacesPath}/${spacesFileName}`, spacesString);
mainWindow.webContents.send(
'space:deleted',
);
}
});
} catch {
mainWindow.webContents.send(
'space:deleted',
ERROR_GENERAL
);
}
});
ipcMain.on('space:load', async (event, { fileLocation }) => {
try {
extract(fileLocation, {dir: savedSpacesPath}, async err => {
const extractPath = `${savedSpacesPath}/temp/`;
extract(fileLocation, {dir: extractPath}, async err => {
if (err) {
console.log(err);
} else {
let space = {};
const spacePath = `${savedSpacesPath}/space.json`;
const spacePath = `${extractPath}/space.json`;
fs.readFile(spacePath, 'utf8', async (err, data) => {
if (err) {
mainWindow.webContents.send(
'space:loaded',
1
ERROR_ZIP_CORRUPTED
);
fse.remove(extractPath, (err) => {
if (err) {
console.log(err);
}
});
} else {
let spaces = [];
space = JSON.parse(data);
const spacesPath = `${savedSpacesPath}/ss.json`;
fs.readFile(spacesPath, 'utf8', async (err, data) => {
// we dont have saved spaces yet
ncp(extractPath, savedSpacesPath, async (err) => {
if (err) {
spaces.push(space);
const spacesString = JSON.stringify(spaces);
await fsPromises.writeFile(`${savedSpacesPath}/ss.json`, spacesString);
mainWindow.webContents.send(
'space:loaded',
spaces
);
} else {
try {
spaces = JSON.parse(data);
} catch (e) {
mainWindow.webContents.send(
'space:loaded',
2
);
}
const spaceId = Number(space.id);
const available = spaces.find(({ id }) => (Number(id) === spaceId));
if (!available) {
return console.error(err);
}
let spaces = [];
space = JSON.parse(data);
const spacesPath = `${savedSpacesPath}/${spacesFileName}`;
fs.readFile(spacesPath, 'utf8', async (err, data) => {
// we dont have saved spaces yet
if (err) {
spaces.push(space);
const spacesString = JSON.stringify(spaces);
await fsPromises.writeFile(`${savedSpacesPath}/ss.json`, spacesString);
await fsPromises.writeFile(`${savedSpacesPath}/${spacesFileName}`, spacesString);
mainWindow.webContents.send(
'space:loaded',
spaces
);
} else {
mainWindow.webContents.send(
'space:loaded',
3
);
try {
spaces = JSON.parse(data);
} catch (e) {
mainWindow.webContents.send(
'space:loaded',
ERROR_JSON_CORRUPTED
);
}
const spaceId = Number(space.id);
const available = spaces.find(({ id }) => (Number(id) === spaceId));
if (!available) {
spaces.push(space);
const spacesString = JSON.stringify(spaces);
await fsPromises.writeFile(`${savedSpacesPath}/${spacesFileName}`, spacesString);
mainWindow.webContents.send(
'space:loaded',
spaces
);
} else {
mainWindow.webContents.send(
'space:loaded',
ERROR_SPACE_ALREADY_AVAILABLE
);
}
}
}
fs.unlink(`${savedSpacesPath}/space.json`, (err) => {
if (err) {
console.log(err);
}
});
fse.remove(extractPath, (err) => {
if (err) {
console.log(err);
}
});
});
});
}
fs.unlink(spacePath, (err) => {
if (err) {
console.log(err);
}
});
});
}
});
} catch (err) {
console.log('error:', err);
}
});
ipcMain.on('show-open-dialog', ()=> {
const options = {
filters: [
{ name: 'zip', extensions: ['zip'] },
],
};
ipcMain.on('space:export', async (event, { archivePath, id, spaces } ) => {
try {
const space = spaces.find(el => Number(el.id) === Number(id));
const { phases } = space;
const spacesString = JSON.stringify(space);
const ssPath = `${savedSpacesPath}/space.json`;
await fsPromises.writeFile(ssPath, spacesString);
const filesPaths = [ssPath];
for (const phase of phases) {
const { items = [] } = phase;
for (let i=0; i < items.length; i++) {
const { resource } = items[i];
if (resource) {
const {
hash,
type,
} = resource;
const fileName = `${hash}.${type}`;
const filePath = `${savedSpacesPath}/${fileName}`;
const fileAvailable = await checkFileAvailable({ filePath });
if (fileAvailable){
filesPaths.push(filePath);
}
}
}
}
const output = fs.createWriteStream(archivePath);
const archive = archiver('zip', {
zlib: { level: 9 }
});
output.on('close', () => {
fs.unlink(ssPath, (err) => {
if (err) {
console.log(err);
}
});
mainWindow.webContents.send(
'space:exported',
);
});
output.on('end', () => {
mainWindow.webContents.send(
'space:exported',
ERROR_GENERAL
);
});
archive.on('warning', err => {
if (err.code === 'ENOENT') {
console.log(err);
}
});
archive.on('error', err => {
mainWindow.webContents.send(
'space:exported',
ERROR_GENERAL
);
});
archive.pipe(output);
filesPaths.forEach( path => {
const pathArr = path.split('/');
archive.file(path, { name: pathArr[pathArr.length -1 ] });
});
archive.finalize();
} catch (err) {
console.log(err);
mainWindow.webContents.send(
'space:exported',
ERROR_GENERAL
);
}
});
ipcMain.on('show-open-dialog', (event, options)=> {
dialog.showOpenDialog(null, options, (filePaths) => {
mainWindow.webContents.send('open-dialog-paths-selected', filePaths)
});
})
});
ipcMain.on('show-save-dialog', (event, spaceTitle) => {
const options = {
title: 'Save as',
defaultPath: `${spaceTitle}.zip`,
};
dialog.showSaveDialog(null, options, (filePath) => {
mainWindow.webContents.send('save-dialog-path-selected', filePath)
});
});
ipcMain.on('show-message-dialog', () => {
const options = {
type: 'warning',
buttons: ['Cancel', 'Delete'],
defaultId: 0,
cancelId: 0,
message: 'Are you sure you want to delete the space?'
};
dialog.showMessageBox(null, options, (respond) => {
mainWindow.webContents.send('message-dialog-respond', respond)
});
});
});

app.on('window-all-closed', () => {
Expand Down
2 changes: 1 addition & 1 deletion src/Home.js
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ Home.propTypes = {
classes: PropTypes.shape({ appBar: PropTypes.string.isRequired }).isRequired,
theme: PropTypes.shape({ direction: PropTypes.string }).isRequired,
dispatchGetSpaces: PropTypes.func.isRequired,
spaces: PropTypes.arrayOf({ id: PropTypes.string.isRequired }).isRequired,
spaces: PropTypes.arrayOf(PropTypes.shape({ id: PropTypes.string.isRequired })).isRequired,
activity: PropTypes.bool.isRequired,
history: PropTypes.shape({ length: PropTypes.number.isRequired }).isRequired,
};
Expand Down
Loading

0 comments on commit a8d64e4

Please sign in to comment.