diff --git a/api-client.js b/api-client.js
index 0246c48..6f32e80 100644
--- a/api-client.js
+++ b/api-client.js
@@ -7,31 +7,33 @@ class ApiClient {
this.config = new ElectronStore();
this.store = new JsonApiDataStore();
}
-
+
token() {
return this.config.get('token');
}
-
+
email() {
return this.config.get('email');
}
-
+
logIn(email, password, callback) {
- var me = this;
+ const me = this;
this.config.set('email', email);
- var req = https.request({
+ const req = https.request({
method: 'POST',
host: 'api.op1.fun',
path: '/v1/api_token',
headers: {
'Content-Type': 'application/json',
- 'Accept': 'application/json'
- }
+ 'Accept': 'application/json',
+ },
}, function(res) {
- var body = '';
- res.on('data', function(d) { body += d; });
+ let body = '';
+ res.on('data', function(d) {
+ body += d;
+ });
res.on('end', function() {
- var res = JSON.parse(body);
+ const res = JSON.parse(body);
if (res.api_token) {
me.config.set('token', res.api_token);
}
@@ -39,62 +41,63 @@ class ApiClient {
callback(res);
});
});
- req.write(JSON.stringify({ email: email, password: password }));
+ req.write(JSON.stringify({email: email, password: password}));
req.end();
}
-
+
enableAppFeatureFlag() {
- this._post('feature_flags', { flags: { app: true } }, function() {});
+ this._post('feature_flags', {flags: {app: true}}, function() {});
}
-
+
logOut(callback) {
this.config.set('email', null);
this.config.set('token', null);
callback();
}
-
+
isLoggedIn() {
return (this.email() && this.token());
}
-
+
getPack(path, id, callback) {
- var me = this;
+ const me = this;
this._get(path, function() {
- var pack = me.store.find("packs", id);
+ const pack = me.store.find('packs', id);
callback(pack);
- })
+ });
}
-
+
getPatch(path, id, callback) {
- var me = this;
+ const me = this;
this._get(path, function() {
- var patch = me.store.find("patches", id);
+ const patch = me.store.find('patches', id);
callback(patch);
- })
+ });
}
-
+
_get(path, callback) {
- var me = this;
+ const me = this;
return https.get({
host: 'api.op1.fun',
path: '/v1/' + path,
headers: {
'X-User-Email': this.email(),
- 'X-User-Token': this.token()
- }
+ 'X-User-Token': this.token(),
+ },
}, function(res) {
- var body = '';
- res.on('data', function(d) { body += d; });
+ let body = '';
+ res.on('data', function(d) {
+ body += d;
+ });
res.on('end', function() {
me.store.sync(JSON.parse(body));
callback();
});
});
}
-
+
_post(path, data, callback) {
- var me = this;
- var req = https.request({
+ const req = https.request({
method: 'POST',
host: 'api.op1.fun',
path: '/v1/' + path,
@@ -102,12 +105,16 @@ class ApiClient {
'X-User-Email': this.email(),
'X-User-Token': this.token(),
'Content-Type': 'application/json',
- 'Accept': 'application/json'
- }
+ 'Accept': 'application/json',
+ },
}, function(res) {
- var body = '';
- res.on('data', function(d) { body += d; });
- res.on('end', function() { callback(body); });
+ let body = '';
+ res.on('data', function(d) {
+ body += d;
+ });
+ res.on('end', function() {
+ callback(body);
+ });
});
console.log(data);
console.log(JSON.stringify(data));
diff --git a/front-end.js b/front-end.js
index 4485070..85f4375 100644
--- a/front-end.js
+++ b/front-end.js
@@ -1,45 +1,63 @@
-const { ipcRenderer, webFrame } = require('electron');
+const {ipcRenderer, webFrame} = require('electron');
const ApiClient = require('./api-client');
const groupBy = require('./lib/group-by');
const api = new ApiClient();
const version = require('./package.json').version;
-var app;
-
// disable zoom
webFrame.setVisualZoomLevelLimits(1, 1);
-var categoryFilter = function (patches, category) {
- var filtered = patches.filter((p) => { return p.category === category });
- return filtered.sort(function (a, b) {
+const categoryFilter = function(patches, category) {
+ const filtered = patches.filter((p) => {
+ return p.category === category;
+ });
+ return filtered.sort(function(a, b) {
// "/000" makes root level patches sort to the top
- var _a = (a.packDir || "/000") + a.name.toLowerCase();
- var _b = (b.packDir || "/000") + b.name.toLowerCase();
- if (_a < _b) { return -1 } else if (_a > _b) { return 1 }
+ const _a = (a.packDir || '/000') + a.name.toLowerCase();
+ const _b = (b.packDir || '/000') + b.name.toLowerCase();
+ if (_a < _b) {
+ return -1;
+ } else if (_a > _b) {
+ return 1;
+ }
return 0;
});
-}
+};
-app = new Vue({
+const app = new Vue({
el: '#app',
- data: {
- patches: [],
- downloading: false,
- currentView: api.isLoggedIn() ? 'browser' : 'login',
- currentListId: 'synth',
- loginError: '',
- isLoggedIn: api.isLoggedIn(),
- connected: false
+ data: function() {
+ return {
+ patches: [],
+ downloading: false,
+ currentView: api.isLoggedIn() ? 'browser' : 'login',
+ currentListId: 'synth',
+ loginError: '',
+ isLoggedIn: api.isLoggedIn(),
+ connected: false,
+ };
},
methods: {
- goToView: function (e) { this.currentView = e },
- showList: function (e) { this.currentListId = e },
- setLoginError: function (error) { this.loginError = error; },
- setLoggedInFalse: function () { this.isLoggedIn = false; },
- setLoggedInTrue: function () { this.isLoggedIn = true; },
- mountOP1: function () { ipcRenderer.send('mount-op1'); },
- showPopupMenu: function () {
- ipcRenderer.send('show-popup-menu', { view: this.currentView });
+ goToView: function(e) {
+ this.currentView = e;
+ },
+ showList: function(e) {
+ this.currentListId = e;
+ },
+ setLoginError: function(error) {
+ this.loginError = error;
+ },
+ setLoggedInFalse: function() {
+ this.isLoggedIn = false;
+ },
+ setLoggedInTrue: function() {
+ this.isLoggedIn = true;
+ },
+ mountOP1: function() {
+ ipcRenderer.send('mount-op1');
+ },
+ showPopupMenu: function() {
+ ipcRenderer.send('show-popup-menu', {view: this.currentView});
},
},
components: {
@@ -49,16 +67,16 @@ app = new Vue({
//
login: {
template: '#login',
- data: function () {
+ data: function() {
return {
email: api.email(),
version: version,
- password: ''
- }
+ password: '',
+ };
},
props: ['loginError', 'isLoggedIn'],
methods: {
- logIn: function (e) {
+ logIn: function(e) {
api.logIn(this.email, this.password, (res) => {
if (res.error) {
this.$emit('error', res.error);
@@ -69,12 +87,12 @@ app = new Vue({
}
});
},
- logOut: function () {
+ logOut: function() {
api.logOut(() => {
this.$emit('log-out');
});
- }
- }
+ },
+ },
},
//
@@ -84,7 +102,7 @@ app = new Vue({
template: '#browser',
props: ['patches', 'downloading', 'currentListId', 'connected'],
computed: {
- filteredPatches: function () {
+ filteredPatches: function() {
return categoryFilter(this.patches, this.currentListId);
},
},
@@ -92,32 +110,32 @@ app = new Vue({
sideNav: {
template: '#side-nav',
props: ['patches', 'currentListId'],
- data: function () {
+ data: function() {
return {
- limits: { drum: 42, synth: 100, sampler: 42 },
- }
+ limits: {drum: 42, synth: 100, sampler: 42},
+ };
},
computed: {
- navItems: function () {
- var sub = (cat) => {
- return categoryFilter(this.patches, cat).length + " of " + this.limits[cat];
- }
+ navItems: function() {
+ const sub = (cat) => {
+ return categoryFilter(this.patches, cat).length + ' of ' + this.limits[cat];
+ };
return [
- { id: 'synth', title: 'Synth', subtitle: sub('synth') },
- { id: 'drum', title: 'Drum', subtitle: sub('drum') },
- { id: 'sampler', title: 'Sampler', subtitle: sub('sampler') },
+ {id: 'synth', title: 'Synth', subtitle: sub('synth')},
+ {id: 'drum', title: 'Drum', subtitle: sub('drum')},
+ {id: 'sampler', title: 'Sampler', subtitle: sub('sampler')},
// { id: 'backups', title: 'Backups', subtitle: 'ok' },
- ]
- }
- }
+ ];
+ },
+ },
},
contentArea: {
- template: "",
+ template: '',
props: ['currentListId', 'patches', 'id'],
computed: {
- currentComponent: function () {
+ currentComponent: function() {
return (this.currentListId === 'backups') ? 'backups' : 'patch-list';
- }
+ },
},
components: {
@@ -125,29 +143,31 @@ app = new Vue({
template: '#patch-list',
props: ['patches', 'id'],
computed: {
- packs: function () { return groupBy(this.patches, 'packName') }
+ packs: function() {
+ return groupBy(this.patches, 'packName');
+ },
},
methods: {
- showInFinder: function (e) {
+ showInFinder: function(e) {
if (e) {
- ipcRenderer.send('show-in-finder', e.target.getAttribute("href"));
+ ipcRenderer.send('show-in-finder', e.target.getAttribute('href'));
}
},
},
},
backups: {
- template: '#backups'
- }
+ template: '#backups',
+ },
- }
+ },
},
disconnected: {
- template: '#disconnected'
- }
- }
- }
+ template: '#disconnected',
+ },
+ },
+ },
- }
+ },
});
@@ -172,9 +192,9 @@ ipcRenderer.on('show-login', (event, data) => {
ipcRenderer.on('start-download', (event, message) => {
if (message['pack']) {
- app.downloading = "Downloading Pack: " + message.pack.name;
+ app.downloading = 'Downloading Pack: ' + message.pack.name;
} else if (message['patch']) {
- app.downloading = "Downloading Patch: " + message.patch.name;
+ app.downloading = 'Downloading Patch: ' + message.patch.name;
}
});
diff --git a/index.js b/index.js
index fb9c920..3084644 100644
--- a/index.js
+++ b/index.js
@@ -1,6 +1,6 @@
-const { menubar } = require('menubar');
-const { autoUpdater, dialog, ipcMain, shell, Menu } = require('electron');
-const { download } = require('electron-dl');
+const {menubar} = require('menubar');
+const {autoUpdater, dialog, ipcMain, shell, Menu} = require('electron');
+const {download} = require('electron-dl');
const chokidar = require('chokidar');
const drivelist = require('drivelist');
const Url = require('url');
@@ -13,10 +13,12 @@ const isDev = require('electron-is-dev');
if (!isDev) {
const version = require('./package.json').version;
- const platform = os.platform() + "_" + os.arch();
+ const platform = os.platform() + '_' + os.arch();
autoUpdater.setFeedURL('https://nuts.op1.fun/update/' + platform + '/' + version);
autoUpdater.checkForUpdates();
- setInterval(() => { autoUpdater.checkForUpdates() }, 300000);
+ setInterval(() => {
+ autoUpdater.checkForUpdates();
+ }, 300000);
autoUpdater.on('update-downloaded', (event, releaseNotes, releaseName) => {
const dialogOpts = {
@@ -24,28 +26,25 @@ if (!isDev) {
buttons: ['Restart', 'Later'],
title: 'Application Update',
message: releaseName,
- detail: 'A new version of op1.fun.app has been downloaded. Restart the application to apply the update.'
- }
+ detail: 'A new version of op1.fun.app has been downloaded. Restart the application to apply the update.',
+ };
dialog.showMessageBox(dialogOpts, (response) => {
if (response === 0) autoUpdater.quitAndInstall();
});
});
- autoUpdater.on('error', message => {
+ autoUpdater.on('error', (message) => {
console.error('There was a problem updating the application');
console.error(message);
});
}
-var email,
- token,
- watcher,
- urlToOpen,
- mountpoint,
- patches = [],
- mounted = false,
- settingUpWatcher = false;
+let watcher;
+let mountpoint;
+let patches = [];
+let mounted = false;
+let settingUpWatcher = false;
// mountpoint = "/Users/jordan/Documents/OP-1/fakeop1";
@@ -53,27 +52,27 @@ const mb = menubar({
browserWindow: {
webPreferences: {
nodeIntegration: true,
- contextIsolation: false
+ contextIsolation: false,
},
- width: 600
+ width: 600,
},
preloadWindow: true,
- icon: path.join(__dirname, 'icon.png')
+ icon: path.join(__dirname, 'icon.png'),
});
mb.on('ready', function ready() {
- ensureConnected().then(function (message) {
+ ensureConnected().then(function(message) {
mb.showWindow();
- }, function (reason) {
+ }, function(reason) {
mb.showWindow();
});
});
-mb.app.on('open-url', function (e, urlStr) {
+mb.app.on('open-url', function(e, urlStr) {
e.preventDefault();
if (ensureLoggedIn()) {
- ensureConnected().then(function () {
- var { id, path, type } = parseUrl(urlStr);
+ ensureConnected().then(function() {
+ const {id, path, type} = parseUrl(urlStr);
if (type === 'packs' && id) {
api.getPack(path, id, loadPack);
} else if (type === 'patches' && id) {
@@ -89,7 +88,7 @@ mb.app.on('open-url', function (e, urlStr) {
mb.on('after-show', function show() {
if (ensureLoggedIn()) {
- ensureConnected().catch(function (reason) {
+ ensureConnected().catch(function(reason) {
// noop
});
};
@@ -99,18 +98,18 @@ ipcMain.on('show-popup-menu', (event, args) => {
let menu;
if (args.view === 'login') {
menu = Menu.buildFromTemplate([
- { role: 'quit' }
+ {role: 'quit'},
]);
} else {
menu = Menu.buildFromTemplate([
- { label: 'Account Settings', click: () => {
+ {label: 'Account Settings', click: () => {
mb.window.webContents.send('go-to-view', 'login');
}},
- { type: 'separator' },
- { role: 'quit' }
+ {type: 'separator'},
+ {role: 'quit'},
]);
}
-
+
menu.popup(mb.window);
});
@@ -119,7 +118,7 @@ ipcMain.on('show-in-finder', (event, arg) => {
});
ipcMain.on('mount-op1', (event, arg) => {
- ensureConnected().catch(function (reason) {
+ ensureConnected().catch(function(reason) {
// noop
});
});
@@ -130,7 +129,7 @@ ipcMain.on('show-config-menu', (event, arg) => {
function loadPatch(patch, packDir) {
mb.showWindow();
- var dir = [mountpoint];
+ const dir = [mountpoint];
if (patch['patch-type'] === 'drum') {
dir.push('drum');
} else {
@@ -139,41 +138,43 @@ function loadPatch(patch, packDir) {
if (packDir) {
dir.push(packDir);
} else {
- mb.window.webContents.send('start-download', { patch: patch });
+ mb.window.webContents.send('start-download', {patch: patch});
}
- result = download(mb.window, patch.links.file, { directory: dir.join("/") });
+ result = download(mb.window, patch.links.file, {directory: dir.join('/')});
if (!packDir) {
- result = result.then(function () {
- mb.window.webContents.send('finish-download', { patch: patch });
+ result = result.then(function() {
+ mb.window.webContents.send('finish-download', {patch: patch});
});
}
return result;
}
function loadPack(pack) {
- mb.window.webContents.send('start-download', { pack: pack });
- var result = Promise.resolve();
- pack.patches.forEach(function (patch) {
+ mb.window.webContents.send('start-download', {pack: pack});
+ let result = Promise.resolve();
+ pack.patches.forEach(function(patch) {
result = result.then(() => loadPatch(patch, pack.id));
});
- result = result.then(function () {
- mb.window.webContents.send('finish-download', { pack: pack });
- })
+ result = result.then(function() {
+ mb.window.webContents.send('finish-download', {pack: pack});
+ });
return result;
}
function parseUrl(urlStr) {
- var parsed = Url.parse(urlStr);
- var path = parsed.pathname
- while (path.charAt(0) === "/") { path = path.slice(1); }
- var parts = path.split("/");
- return { type: parts[2], id: parts[3], path: path };
+ const parsed = Url.parse(urlStr);
+ let path = parsed.pathname;
+ while (path.charAt(0) === '/') {
+ path = path.slice(1);
+ }
+ const parts = path.split('/');
+ return {type: parts[2], id: parts[3], path: path};
}
function ensureLoggedIn() {
if (!api.isLoggedIn()) {
mb.window.webContents.send('show-login', {
- message: 'Please login to download packs and patches.'
+ message: 'Please login to download packs and patches.',
});
return false;
}
@@ -186,10 +187,10 @@ function ensureConnected() {
return Promise.resolve(true);
} else if (!settingUpWatcher) {
settingUpWatcher = true;
- return watchOP1().then(function () {
+ return watchOP1().then(function() {
mb.window.webContents.send('op1-connected', true);
settingUpWatcher = false;
- }, function (error) {
+ }, function(error) {
mb.window.webContents.send('op1-connected', false);
settingUpWatcher = false;
return Promise.reject();
@@ -212,7 +213,7 @@ async function watchOP1() {
const drives = await drivelist.list();
for (let i = 0; i < drives.length; i++) {
- if (drives[i].description.indexOf("OP-1") > -1) {
+ if (drives[i].description.indexOf('OP-1') > -1) {
const m = drives[i].mountpoints[0];
if (m) {
mountpoint = m.path;
@@ -223,25 +224,25 @@ async function watchOP1() {
if (!mountpoint) {
mounted = false;
- throw new Error("OP-1 not found");
+ throw new Error('OP-1 not found');
} else {
mounted = true;
}
watcher = chokidar.watch(mountpoint, {
ignored: /(^|[\/\\])\../,
- awaitWriteFinish: true
+ awaitWriteFinish: true,
}).on('all', (event, path) => {
if (mountpoint) {
const relPath = path.slice(mountpoint.length);
- const parts = relPath.split("/");
+ const parts = relPath.split('/');
if (
// ignore album, tape and user preset patches
- ((parts[1] === "synth") || (parts[1] === "drum")) && parts[2] != "user"
+ ((parts[1] === 'synth') || (parts[1] === 'drum')) && parts[2] != 'user'
) {
if (event === 'add') {
try {
- const patch = new OP1Patch({ path: path, relPath: relPath });
+ const patch = new OP1Patch({path: path, relPath: relPath});
if (patch.metadata) {
patches.push(patch);
mb.window.webContents.send('render-patches', patches);
@@ -250,14 +251,16 @@ async function watchOP1() {
console.log(e);
}
} else if (event === 'unlink') {
- patches = patches.filter(function (p) { return p.relPath !== relPath });
+ patches = patches.filter(function(p) {
+ return p.relPath !== relPath;
+ });
mb.window.webContents.send('render-patches', patches);
}
} else {
// console.log(event, path);
}
}
- }).on('raw', function (event, path, details) {
+ }).on('raw', function(event, path, details) {
if (
(details.event === 'root-changed') ||
(details.event === 'deleted' && path === mountpoint)