Skip to content

Commit

Permalink
Base functionality of the app is done.
Browse files Browse the repository at this point in the history
  • Loading branch information
roncli committed Jan 12, 2017
1 parent 6a2dc35 commit aae8789
Show file tree
Hide file tree
Showing 4 changed files with 266 additions and 15 deletions.
4 changes: 1 addition & 3 deletions app/index.js
Expand Up @@ -2,7 +2,7 @@ const {app, BrowserWindow} = require("electron");

var win,
createWindow = () => {
win = new BrowserWindow({show: false, width: 800, height: 600, minWidth: 640, minHeight: 480});
win = new BrowserWindow({show: false, width: 800, height: 600, minWidth: 800, minHeight: 600});
win.loadURL("file://" + __dirname + "/site/index.htm");
win.toggleDevTools();
win.setMenu(null);
Expand All @@ -17,8 +17,6 @@ var win,
});
};

app.disableHardwareAcceleration();

app.on("ready", createWindow);

app.on("window-all-closed", () => {
Expand Down
4 changes: 3 additions & 1 deletion app/package.json
Expand Up @@ -9,7 +9,9 @@
"dependencies": {
"angular": "1.5.8",
"bootstrap": "3.3.7",
"jquery": "3.1.1"
"jquery": "3.1.1",
"jszip": "3.1.3",
"mmmagic": "0.4.5"
},
"version": "0.1.0",
"description": "An application to easily create and share custom soundboards.",
Expand Down
15 changes: 13 additions & 2 deletions app/site/index.htm
Expand Up @@ -2,6 +2,9 @@
<head>
<link rel="stylesheet" href="../node_modules/bootstrap/dist/css/bootstrap.min.css" />
<link rel="stylesheet" href="index.css" />
<script src="../node_modules/jquery/dist/jquery.min.js"></script>
<script>window.$ = window.jQuery = require("jquery");</script>
<script src="../node_modules/bootstrap/dist/js/bootstrap.min.js"></script>
<script src="index.js"></script>
</head>
<body>
Expand All @@ -11,9 +14,14 @@
<div ng-repeat="sound in sounds" class="sound col-xs-3">
<div class="panel panel-defualt">
<div class="panel-body">
<div class="pull-left">{{sound.name}}</div>
<div class="pull-left">
<button class="btn btn-danger" ng-click="delete(sound)" title="Delete sound from ChatterGrid"><span class="glyphicon glyphicon-remove"></span></button>
{{sound.name}}
</div>
<div class="pull-right">
<button class="btn btn-primary" ng-click="play(sound)"><span class="glyphicon glyphicon-play"></span></button>
<button class="btn btn-primary" ng-if="sound.audio.paused" ng-click="play(sound)" title="Play sound"><span class="glyphicon glyphicon-play"></span></button>
<button class="btn btn-primary" ng-if="!sound.audio.paused" ng-click="pause(sound)" title="Pause sound"><span class="glyphicon glyphicon-pause"></span></button>
<button class="btn btn-primary" ng-if="!sound.audio.paused" ng-click="stop(sound)" title="Stop sound"><span class="glyphicon glyphicon-stop"></span></button>
</div>
</div>
</div>
Expand All @@ -25,6 +33,9 @@
Drop audio files here to add to the grid!
</div>
<div id="bar">
<button class="btn btn-default" ng-click="loadGrid()">Load Grid</button>
<button class="btn btn-default" ng-click="saveGrid()">Save Grid</button>
<button class="btn btn-default" ng-click="shareGrid()">Share Grid</button>
</div>
</body>
</html>
258 changes: 249 additions & 9 deletions app/site/index.js
@@ -1,19 +1,242 @@
var files = {},
var electron = require("electron"),
fs = require("fs"),
path = require("path"),
JSZip = require("jszip"),
files = {},
filenameRegex = /[/\\]([^/\\]+)\.([^/\\]+)$/,
dirty = false,
filterAllCg = {name: "All ChatterGrid files", extensions: ["chgd", "chgs"]},
filterChgd = {name: "ChatterGrid grid definition", extensions: ["chgd"]},
filterChgs = {name: "ChatterGrid sounds", extensions: ["chgs"]},
angular, app, scope;

window.$ = window.jQuery = require("../node_modules/jquery/dist/jquery.min.js");

angular = require("angular"),
app = angular.module("chattergrid", []),
require("../node_modules/bootstrap/dist/js/bootstrap.min.js");

app.controller("chattergrid", ["$scope", function($scope) {
$scope.sounds = [];

$scope.play = (sound) => {
sound.audio.play();
};

$scope.pause = (sound) => {
sound.audio.pause();
};

$scope.stop = (sound) => {
sound.audio.pause();
sound.audio.currentTime = 0;
};

$scope.delete = (sound) => {
// TODO: Check for memory leak if we don't dispose of the Audio properly.
delete files[sound.file];
$scope.sounds.splice($scope.sounds.indexOf(sound), 1);
dirty = true;
};

$scope.loadGrid = () => {
new Promise((resolve, reject) => {
if (dirty) {
electron.remote.dialog.showMessageBox({
type: "question",
buttons: ["Yes, discard", "No, cancel"],
title: "Load Grid",
message: "You have unsaved changes to the current grid. Discard the changes?",
cancelId: 1
}, (response) => {
if (response === 0) {
resolve();
} else {
reject();
}
});
} else {
resolve();
}
}).then(() => {
electron.remote.dialog.showOpenDialog({
title: "Load Grid",
filters: [filterAllCg, filterChgd, filterChgs],
properties: ["openFile"]
}, (filenames) => {
var filename;

if (!filenames || filenames.length === 0) {
return;
}

filename = filenames[0];

fs.readFile(filename, (err, data) => {
if (err) {
alert("There was a problem loading the file.");
return;
}

new Promise((resolve, reject) => {
JSZip.loadAsync(data).then((zip) => {
// Load the ZIP file.
zip.file("json").async("string").then((data) => {
try {
var sounds = JSON.parse(data),
promises;

files = {};
// TODO: Check for memory leak if we don't dispose of the Audio properly.
$scope.sounds = [];

promises = sounds.map((sound) => new Promise((resolve, reject) => {
zip.file(sound.index.toString()).async("nodebuffer").then((data) => {
checkFile({file: sound.file, data: data.toString("base64"), type: sound.type}, true);
resolve();
}).catch(reject);
}));

Promise.all(promises).then(() => {
dirty = false;
resolve();
}).catch(reject);
} catch(err) {
reject();
}
}).catch(reject);
}).catch(reject);
}).catch(() => {
// Load the JSON file.
try {
var sounds = JSON.parse(data.toString());

files = {};
// TODO: Check for memory leak if we don't dispose of the Audio properly.
$scope.sounds = [];

sounds.forEach((sound) => {
checkFile({file: sound.file, type: sound.type}, true);
});
dirty = false;
} catch (err) {
alert("There was a problem loading the file.");
return;
}
});
});
});
}).catch(() => {});
};

$scope.saveGrid = () => {
electron.remote.dialog.showSaveDialog({
title: "Save Current Grid",
filters: [filterChgd]
}, (filename) => {
var promises;

if (!filename) {
return;
}

promises = $scope.sounds.map((sound) => new Promise((resolve, reject) => {
if (sound.data) {
sound.file = path.join(path.dirname(filename), sound.name + "." + sound.extension);
fs.writeFile(sound.file, new Buffer(sound.data, "base64"), (err) => {
if (err) {
reject();
}

resolve();
});
} else {
resolve();
}
}));

Promise.all(promises).then(() => {
fs.writeFile(filename, JSON.stringify($scope.sounds.map((sound) => {
var audioFilename;

return {
file: sound.file,
type: sound.type
};
})), (err) => {
if (err) {
alert("There was a problem saving the file.");
return;
}

dirty = false;
alert("Grid saved!");
});
}).catch(() => {
alert("There was a problem saving the file.");
});
});
};

$scope.shareGrid = () => {
electron.remote.dialog.showSaveDialog({
title: "Share Current Grid",
filters: [filterChgs]
}, (filename) => {
var zip, promises;

if (!filename) {
return;
}

zip = new JSZip();

zip.file("json", JSON.stringify($scope.sounds.map((sound, index) => {
return {
file: "/" + sound.name + "." + sound.extension,
type: sound.type,
index: index
};
})));

promises = $scope.sounds.map((sound, index) => new Promise((resolve, reject) => {
if (sound.data) {
zip.file(index.toString(), new Buffer(sound.data, "base64"), {binary: true});

resolve();
} else {
fs.readFile(sound.file, (err, data) => {
if (err) {
reject(err);
return;
}

zip.file(index.toString(), data, {binary: true});

resolve();
});
}
}));

Promise.all(promises).then(() => {
zip.generateAsync({
compression: "DEFLATE",
type: "nodebuffer"
}).then((content) => {
fs.writeFile(filename, content, (err) => {
if (err) {
alert("There was a problem saving the file.");
return;
}

dirty = false;
alert("Grid saved!");
});
}).catch((err) => {
alert("There was a problem saving the file.");
});
}).catch((err) => {
alert("There was a problem saving the file.");
});
});
};
}]);

$(document).ready(() => {
Expand All @@ -27,7 +250,7 @@ $(document).ready(() => {

if (ev.target.id === "drop") {
[].concat.apply([], ev.originalEvent.dataTransfer.files).forEach((file) => {
checkFile(file.path);
checkFile({file: file.path, type: file.type});
});
}

Expand All @@ -38,13 +261,19 @@ $(document).ready(() => {
scope = angular.element("html").scope();
});

checkFile = (file) => {
checkFile = (opts, fromLoad) => {
var file, type, data, audio;

file = opts.file;
type = opts.type;
data = opts.data;

if (files[file]) {
alert("You've already added " + file + ".");
return;
}

var audio = new Audio(file);
audio = new Audio(data ? "data:" + type + ";base64," + data : file);

audio.onerror = (err) => {
alert(file + " is not of a supported format.");
Expand All @@ -55,13 +284,24 @@ checkFile = (file) => {
audio.onloadeddata = () => {
var parsed = filenameRegex.exec(file);

files[file] = true;
files[file] = type;
scope.sounds.push({
file: file,
data: data,
name: parsed[1],
type: parsed[2],
extension: parsed[2],
type: type,
audio: audio
});

audio.addEventListener("pause", () => {
scope.$apply();
});

if (!fromLoad) {
dirty = true;
}

scope.$apply();
};
};

0 comments on commit aae8789

Please sign in to comment.