autoupdate, notifications
autoupdate, notifications

--- a/Gruntfile.js
+++ b/Gruntfile.js
@@ -10,8 +10,8 @@
                 description: '<%= pkg.description %>',
                 exe: '<%= pkg.name %>.exe',
                 title : '<%= pkg.name %>',
-                iconUrl: 'file://app/app.ico',
-                //setupIcon: "file://app/app.ico"
+                iconUrl: 'file://app/deadline.ico',
+                //setupIcon: "file://app/deadline.ico"
             }
         },
         electron: {
@@ -23,7 +23,8 @@
                     version: '0.36.5',
                     platform: 'win32',
                     arch: 'x64',
-                    icon: 'app/app.ico',
+                    icon: 'app/deadline.ico',
+                    overwrite: true,
                     'version-string' : {
                         CompanyName : 'Webstyler',
                         FileDescription : '<%= pkg.description %>',

file:b/app/deadline.ico (new)
 Binary files /dev/null and b/app/deadline.ico differ
file:b/app/deadline.png (new)
 Binary files /dev/null and b/app/deadline.png differ
 Binary files /dev/null and b/app/deadline_notification.ico differ
 Binary files /dev/null and b/app/deadline_notification.png differ
--- a/app/main.js
+++ b/app/main.js
@@ -1,29 +1,28 @@
 'use strict';
 
 const electron = require('electron');
-// Module to control application life.
 const app = electron.app;
-// Module to create native browser window.
 const BrowserWindow = electron.BrowserWindow;
 const globalShortcut = electron.globalShortcut;
+const ipcMain = electron.ipcMain;
 
 const path = require('path');
 const cp = require('child_process');
 
-const AppMenus = require("./menus.js");
+const appMenus = require("./menus.js");
+const appUpdate = require("./update.js");
 
-var handleSquirrelEvent = function() {
+let handleSquirrelEvent = function() {
     if (process.platform != 'win32') {
         return false;
     }
 
     function executeSquirrelCommand(args, done) {
-      var updateDotExe = path.resolve(path.dirname(process.execPath),
-         '..', 'update.exe');
-      var child = cp.spawn(updateDotExe, args, { detached: true });
-      child.on('close', function(code) {
-         done();
-      });
+        let updateDotExe = path.resolve(path.dirname(process.execPath), '..', 'update.exe');
+        let child = cp.spawn(updateDotExe, args, { detached: true });
+        child.on('close', function(code) {
+            done();
+        });
     };
 
     function install(done) {
@@ -59,9 +58,23 @@
    return;
 }
 
+let getOsRelease = function() {
+    if(process.platform !== 'win32') {
+        return os.release();
+    }
+
+    let matchVersion = cp.execSync('ver.exe', { encoding: 'utf8', timeout: 10000 }).match(/([\d-.])+/g);
+
+    return matchVersion[matchVersion.length - 1];
+};
+const osRelease = getOsRelease();
+
+app.setAppUserModelId('DeadlineApp');
+
 // Keep a global reference of the window object, if you don't, the window will
 // be closed automatically when the JavaScript object is garbage collected.
-let mainWindow;
+let appMainWindow
+let appMenuInstance;
 
 function createWindow() {
     // Create the browser window.
@@ -69,57 +82,56 @@
     let size = electronScreen.getPrimaryDisplay().workAreaSize;
     let width = 9 * size.width/10;
     let height = 9 * size.height/10;
-    mainWindow = new BrowserWindow({width: width, height: height, show: true, skipTaskbar: true});
-    //mainWindow = new BrowserWindow({width: 1000, height: 800, show: false});
+    appMainWindow = new BrowserWindow({width: width, height: height, show: true, skipTaskbar: true});
 
     // and load the index.html of the app.
-    //mainWindow.loadURL('file://' + __dirname + '/index.html');
-    mainWindow.loadURL('http://deadline-app.dev.webstyler.ro/backend_base/backend-dashboard');
+    let loaded = appMainWindow.loadURL('http://deadline-app.dev.webstyler.ro/backend_base/backend-dashboard');
+    if (loaded == false) {
+        //appMainWindow.loadURL('file://' + __dirname + '/index.html');
+    }
 
     // Open the DevTools.
-    //mainWindow.webContents.openDevTools();
+    //appMainWindow.webContents.openDevTools();
 
     // Emitted when the window is closed.
-    mainWindow.on('closed', function() {
+    appMainWindow.on('closed', function() {
         // Dereference the window object, usually you would store windows
         // in an array if your app supports multi windows, this is the time
         // when you should delete the corresponding element.
-        mainWindow = null;
+        appMainWindow = null;
     });
 
     // Emitted when the window is closed.
-    mainWindow.on('close', function(event) {
+    appMainWindow.on('close', function(event) {
         event.preventDefault();
         this.hide();
     });
 
-    mainWindow.on('minimize', function() {
+    appMainWindow.on('minimize', function() {
         // Hide window
         this.hide();
     });
 
-    /*mainWindow.setThumbarButtons([
+    /*appMainWindow.setThumbarButtons([
         {
             tooltip: "button1",
             icon: path.join(__dirname, 'button1.png'),
             click: function() { console.log("button2 clicked"); }
         }
     ]);*/
-    mainWindow.setAutoHideMenuBar(true);
+    appMainWindow.setAutoHideMenuBar(true);
 
-    /*new Notification('Demo', {
-        body: 'Notification with icon',
-        icon: 'icon.ico'
-    });*/
-
-    let ap = new AppMenus(mainWindow, electron).render();
+    appMenuInstance = new appMenus(appMainWindow, electron).menu().tray();
 
     let accelerator = 'CmdOrCtrl+Shift+D';
     if (globalShortcut.isRegistered(accelerator) == false) {
         globalShortcut.register(accelerator, function() {
-            mainWindow.show();
+            appMainWindow.show();
         });
     }
+
+    appMainWindow.webContents.send('console-log', 'Starting version ' + app.getVersion());
+    appUpdate();
 }
 
 // This method will be called when Electron has finished
@@ -142,16 +154,16 @@
 app.on('activate', function () {
     // On OS X it's common to re-create a window in the app when the
     // dock icon is clicked and there are no other windows open.
-    if (mainWindow === null) {
+    if (appMainWindow === null) {
         createWindow();
     }
 });
 
 let shouldQuit = app.makeSingleInstance(function(commandLine, workingDirectory) {
-    if (mainWindow) {
-        mainWindow.show();
-        if (mainWindow.isMinimized()) mainWindow.restore();
-            mainWindow.focus();
+    if (appMainWindow) {
+        appMainWindow.show();
+        if (appMainWindow.isMinimized()) appMainWindow.restore();
+            appMainWindow.focus();
         }
     return true;
 });
@@ -159,3 +171,15 @@
 if (shouldQuit) {
     app.exit(0);
 }
+
+ipcMain.on('notification', function(event, arg) {
+    appMenuInstance.activateNotification(arg);
+});
+
+ipcMain.on('os-release', function(event, arg) {
+    event.returnValue = osRelease;
+});
+
+setInterval(function(){
+    appUpdate();
+}, 1000 * 60 * 60);

--- a/app/menus.js
+++ b/app/menus.js
@@ -1,55 +1,57 @@
 'use strict';
 
-let mainWindow;
-let app;
-let Menu;
-let Tray;
-let globalShortcut;
+const appUpdate = require("./update.js");
 
-class AppMenus {
+class appMenus {
     constructor(win, electron) {
-        mainWindow = win;
-        app = electron.app;
-        Menu = electron.Menu;
-        Tray = electron.Tray;
-        globalShortcut = electron.globalShortcut;
-        return this;
+        this.notification = false;
+        this.appMainWindow = win;
+        this.app = electron.app;
+        this.appMenu = electron.Menu;
+        this.trayInstance = new electron.Tray('resources/app/deadline.ico');
     }
 
     tray() {
-        let appIcon = null;
-        appIcon = new Tray('resources/app/app.ico');
-        let contextMenu = Menu.buildFromTemplate([
+        let instance = this;
+        let contextMenu = this.appMenu.buildFromTemplate([
             {
-                label: 'Show',
-                accelerator: 'CmdOrCtrl+Shift+D',
+                label: 'Check for updates to v' + this.app.getVersion(),
                 click: function() {
-                    mainWindow.show();
+                    appUpdate(true);
                 }
             },
             {
                 label: 'Toggle DevTools',
                 click: function() {
-                    mainWindow.show();
-                    mainWindow.toggleDevTools();
+                    instance.appMainWindow.show();
+                    instance.appMainWindow.toggleDevTools();
+                }
+            },
+            {
+                label: 'Mark notifications read',
+                click: function() {
+                    instance.handleNotification();
                 }
             },
             {
                 label: 'Quit',
                 selector: 'terminate:',
                 click: function() {
-                    app.exit(0);
+                    instance.app.exit(0);
                 }
             }
         ]);
-        appIcon.setToolTip('DeadlineApp by Webstyler');
-        appIcon.setContextMenu(contextMenu);
-        appIcon.on('double-click', function() {
-            mainWindow.show();
+        this.trayInstance.setToolTip('DeadlineApp by Webstyler');
+        this.trayInstance.setContextMenu(contextMenu);
+        this.trayInstance.on('double-click', function() {
+            //instance.handleNotification();
+            instance.appMainWindow.show();
         });
-        appIcon.on('click', function() {
-            mainWindow.show();
+        this.trayInstance.on('click', function() {
+            //instance.handleNotification();
+            instance.appMainWindow.show();
         });
+        return this;
     }
 
     menu() {
@@ -100,7 +102,8 @@
                 accelerator: 'F5',
                 click: function(item, focusedWindow) {
                   if (focusedWindow)
-                    focusedWindow.reload();
+                    //focusedWindow.reload();
+                    focusedWindow.reloadIgnoringCache();
                 }
               },
               {
@@ -146,27 +149,26 @@
                     role: 'close'
                 },
             ]
-          },
-          /*{
-            label: 'Help',
-            role: 'help',
-            submenu: [
-              {
-                label: 'Learn More',
-                click: function() { require('electron').shell.openExternal('http://electron.atom.io') }
-              },
-            ]
-          },*/
+          }
         ];
 
-        let menu = Menu.buildFromTemplate(template);
-        Menu.setApplicationMenu(menu);
+        let menu = this.appMenu.buildFromTemplate(template);
+        this.appMenu.setApplicationMenu(menu);
+        return this;
     }
 
-    render() {
-        this.tray();
-        this.menu();
+    activateNotification(arg) {
+        this.notification = true;
+        this.trayInstance.setImage('resources/app/deadline_notification.ico');
+        this.trayInstance.displayBalloon({image:'resources/app/deadline_notification.ico', title:arg.title, content:arg.content});
+    }
+
+    handleNotification() {
+        if (this.notification == true) {
+            this.notification = false;
+            this.trayInstance.setImage('resources/app/deadline.ico');
+        }
     }
 }
 
-module.exports = AppMenus;
+module.exports = appMenus;

--- a/app/package.json
+++ b/app/package.json
@@ -1,6 +1,6 @@
 {
   "name"    : "DeadlineApp",
   "description" : "DeadlineApp by Webstyler",
-  "version" : "0.1.0",
+  "version" : "0.2.4",
   "main"    : "main.js"
 }

file:b/app/update.js (new)
--- /dev/null
+++ b/app/update.js
@@ -1,1 +1,48 @@
+'use strict';
 
+const dialog = require('dialog');
+const path = require('path');
+const cp = require('child_process');
+
+function appUpdate(manual) {
+    let updateDotExe = path.resolve(path.dirname(process.execPath), '..', 'update.exe');
+    let child = cp.spawn(updateDotExe, ['--download', 'http://deadline-app.dev.webstyler.ro/releases/'], { detached: true });
+    let stdout = '';
+    child.stdout.setEncoding('utf8');
+    let jsonStarted = false;
+    child.stdout.on('data', function (d) {
+        if (!jsonStarted && d.startsWith('{')) {
+            jsonStarted = true;
+            return stdout += d;
+        }
+        if (!jsonStarted) {
+            return;
+        }
+        return stdout += d;
+    });
+    child.on('close', function(code) {
+        //appMainWindow.webContents.send('console-log', stdout);
+        if (jsonStarted && stdout) {
+            let data = JSON.parse(stdout);
+            if (stdout.length > 0 && data.futureVersion > data.currentVersion) {
+                dialog.showMessageBox({ message: 'Update to version ' + data.futureVersion + '?',
+                    buttons: ['Not Now', 'Update'] }, function (choice) {
+                        if (choice == 1) {
+                            let child = cp.spawn(updateDotExe, ['--update', 'http://deadline-app.dev.webstyler.ro/releases/'], { detached: true });
+                            dialog.showMessageBox({
+                                message: 'The update should be available next time you start the application.',
+                                buttons: ['Awesome']
+                            });
+                        }
+                });
+            } else if (manual == true && data.futureVersion <= data.currentVersion) {
+                dialog.showMessageBox({
+                    message: 'No updates available right now.',
+                    buttons: ['Awesome']
+                });
+            }
+        }
+    });
+}
+
+module.exports = appUpdate;

comments