From c480156fd3b6b2c96a62ebb873af71b3a997d797 Mon Sep 17 00:00:00 2001 From: Ramiro Saenz Date: Fri, 29 Jul 2016 16:51:53 -0300 Subject: [PATCH] AutoUpdate Referencing #127 --- app.js | 56 +++++++++++++++++++++++++++++++-- app/Application.js | 77 +++++++++++++++++++++++---------------------- app/package.json | 11 +++++-- electron/main.js | 29 +++++++++-------- electron/menu.js | 10 ++++++ electron/updater.js | 18 +++++++++++ package.json | 46 ++++++++++++++++++--------- 7 files changed, 175 insertions(+), 72 deletions(-) create mode 100644 electron/updater.js diff --git a/app.js b/app.js index e23f6418..66de4636 100644 --- a/app.js +++ b/app.js @@ -3,7 +3,7 @@ var firebase = require('firebase/app'); require('firebase/database'); require('firebase/auth'); -// Firebug Config +// Firebase Config var config = { apiKey: "", authDomain: "", @@ -24,6 +24,58 @@ Ext.application({ ,autoCreateViewport: 'Rambox.view.main.Main' }); -require('electron').ipcRenderer.on('showAbout', function(event, message) { +// auto update logic +const ipc = require('electron').ipcRenderer; +ipc.on('showAbout', function(event, message) { !Ext.cq1('about') ? Ext.create('Rambox.view.main.About') : ''; }); +ipc.on('autoUpdater:checking-for-update:', function() { + Ext.Msg.wait('Please wait...', 'Checking for update'); +}); +ipc.on('autoUpdater:update-not-available', function() { + Ext.Msg.show({ + title: 'You are up to date!' + ,message: 'You have the latest version of Rambox.' + ,icon: Ext.Msg.INFO + ,buttons: Ext.Msg.OK + }); +}); +ipc.on('autoUpdater:update-available', function() { + Ext.Msg.show({ + title: 'New Version available!' + ,message: 'Please wait until Rambox download the new version and ask you for install it.' + ,icon: Ext.Msg.INFO + ,buttons: Ext.Msg.OK + }); +}); +ipc.on('autoUpdater:update-downloaded', function(e, releaseNotes, releaseName, releaseDate, updateURL) { + Ext.cq1('app-main').addDocked({ + xtype: 'toolbar' + ,dock: 'top' + ,ui: 'newversion' + ,items: [ + '->' + ,{ + xtype: 'label' + ,html: 'New version is available! ('+releaseName+')' + } + ,{ + xtype: 'button' + ,text: 'Install' + ,handler: function(btn) { ipc.send('autoUpdater:quit-and-install'); } + } + ,{ + xtype: 'button' + ,text: 'Changelog' + ,href: 'https://github.com/saenzramiro/rambox/releases/tag/'+releaseName + } + ,'->' + ,{ + glyph: 'xf00d@FontAwesome' + ,baseCls: '' + ,style: 'cursor:pointer;' + ,handler: function(btn) { Ext.cq1('app-main').removeDocked(btn.up('toolbar'), true); } + } + ] + }); +}); diff --git a/app/Application.js b/app/Application.js index 12c12dc0..f2844511 100644 --- a/app/Application.js +++ b/app/Application.js @@ -6,6 +6,7 @@ Ext.define('Rambox.Application', { ,requires: [ 'Rambox.ux.Firebase' ,'Rambox.util.MD5' + ,'Ext.window.Toast' ] ,stores: [ @@ -125,44 +126,46 @@ Ext.define('Rambox.Application', { ] }); - fireRef.database().ref('config').on('value', function(snapshot) { - var appVersion = new Ext.Version(require('electron').remote.app.getVersion()); - if ( appVersion.isLessThan(snapshot.val().latestVersion) ) { - console.info('New version is available', snapshot.val().latestVersion); - var newVersionTB = Ext.cq1('app-main').addDocked({ - xtype: 'toolbar' - ,dock: 'top' - ,ui: 'newversion' - ,items: [ - '->' - ,{ - xtype: 'label' - ,html: 'New version is available! ('+snapshot.val().latestVersion+')' - } - ,{ - xtype: 'button' - ,text: 'Download' - ,href: 'https://getrambox.herokuapp.com/download' - } - ,{ - xtype: 'button' - ,text: 'Changelog' - ,href: 'https://github.com/saenzramiro/rambox/releases/tag/'+snapshot.val().latestVersion - } - ,'->' - ,{ - glyph: 'xf00d@FontAwesome' - ,baseCls: '' - ,style: 'cursor:pointer;' - ,handler: function(btn) { Ext.cq1('app-main').removeDocked(btn.up('toolbar'), true); } - } - ] - }); - return; - } + if ( process.platform !== 'win32' && process.platform !== 'darwin' ) { + fireRef.database().ref('config').on('value', function(snapshot) { + var appVersion = new Ext.Version(require('electron').remote.app.getVersion()); + if ( appVersion.isLessThan(snapshot.val().latestVersion) ) { + console.info('New version is available', snapshot.val().latestVersion); + Ext.cq1('app-main').addDocked({ + xtype: 'toolbar' + ,dock: 'top' + ,ui: 'newversion' + ,items: [ + '->' + ,{ + xtype: 'label' + ,html: 'New version is available! ('+snapshot.val().latestVersion+')' + } + ,{ + xtype: 'button' + ,text: 'Download' + ,href: 'https://getrambox.herokuapp.com/download/'+process.platform+'_'+process.arch + } + ,{ + xtype: 'button' + ,text: 'Changelog' + ,href: 'https://github.com/saenzramiro/rambox/releases/tag/'+snapshot.val().latestVersion + } + ,'->' + ,{ + glyph: 'xf00d@FontAwesome' + ,baseCls: '' + ,style: 'cursor:pointer;' + ,handler: function(btn) { Ext.cq1('app-main').removeDocked(btn.up('toolbar'), true); } + } + ] + }); + return; + } - console.info('Your version is the latest. No need to update.') - }); + console.info('Your version is the latest. No need to update.') + }); + } if ( localStorage.getItem('locked') ) { console.info('Lock Rambox:', 'Enabled'); diff --git a/app/package.json b/app/package.json index 3f3653b7..9ed1ec13 100644 --- a/app/package.json +++ b/app/package.json @@ -1,5 +1,5 @@ { - "name": "Rambox", + "name": "rambox", "productName": "Rambox", "version": "0.4.1", "description": "Free and Open Source messaging and emailing app that combines common web applications into one.", @@ -7,8 +7,12 @@ "private": true, "repository": { "type": "git", - "url": "git+https://github.com/saenzramiro/rambox.git" + "url": "https://github.com/saenzramiro/rambox.git" }, + "bugs": { + "url": "https://github.com/saenzramiro/rambox/issues" + }, + "homepage": "http://rambox.pro", "keywords": [ "Rambox", "messaging", @@ -30,6 +34,7 @@ "firebase": "^3.0.5", "firebase-token-generator": "^2.0.0", "tmp": "0.0.28", - "mime": "^1.3.4" + "mime": "^1.3.4", + "electron-is-dev": "^0.1.1" } } diff --git a/electron/main.js b/electron/main.js index a6dcf90f..ffb6c00a 100644 --- a/electron/main.js +++ b/electron/main.js @@ -1,21 +1,18 @@ '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; -// Module for shell -const shell = require('electron').shell; -// Require for menu file +const {app, protocol, BrowserWindow, dialog, shell, Menu, ipcMain} = require('electron'); +// Menu const appMenu = require('./menu'); -// Require for tray file +// Tray const tray = require('./tray'); // Window State Plugin const windowStateKeeper = require('electron-window-state'); // Global Settings var globalSettings = require('./global_settings.js'); +const isDev = require('electron-is-dev'); +const updater = require('./updater'); + // this should be placed at top of main.js to handle setup events quickly if (handleSquirrelEvent()) { // squirrel event handled and app will exit in 1000ms, so don't do anything else @@ -131,10 +128,12 @@ function createWindow () { // and load the index.html of the app. mainWindow.loadURL('file://' + __dirname + '/../index.html'); - electron.Menu.setApplicationMenu(appMenu); + Menu.setApplicationMenu(appMenu); tray.create(mainWindow, mainWindowState); + if ( !isDev ) updater.initialize(mainWindow); + mainWindow.on('page-title-updated', (e, title) => updateBadge(title)); // Open links in default browser @@ -193,7 +192,7 @@ if (shouldQuit) { } var allowedURLCertificates = []; -electron.ipcMain.on('allowCertificate', (event, url) => { +ipcMain.on('allowCertificate', (event, url) => { allowedURLCertificates.push(require('url').parse(url).host); }); app.on('certificate-error', function(event, webContents, url, error, certificate, callback) { @@ -202,7 +201,7 @@ app.on('certificate-error', function(event, webContents, url, error, certificate callback(true); } else { callback(false); - electron.dialog.showMessageBox(mainWindow, { + dialog.showMessageBox(mainWindow, { title: 'Certification Error' ,message: 'The service with the following URL has an invalid authority certification.\n\n'+url+'\n\nYou have to remove the service and add it again, enabling the "Trust invalid authority certificates" in the Options.' ,buttons: ['OK'] @@ -219,11 +218,11 @@ app.on('certificate-error', function(event, webContents, url, error, certificate const tmp = require('tmp'); const mime = require('mime'); var imageCache = {}; -electron.ipcMain.on('image:download', function(event, url, partition) { +ipcMain.on('image:download', function(event, url, partition) { let file = imageCache[url]; if (file) { if (file.complete) { - electron.shell.openItem(file.path); + shell.openItem(file.path); } // Pending downloads intentionally do not proceed @@ -247,7 +246,7 @@ electron.ipcMain.on('image:download', function(event, url, partition) { downloadItem.once('done', () => { tmpWindow.destroy(); tmpWindow = null; - electron.shell.openItem(file.path); + shell.openItem(file.path); file.complete = true; }); }); diff --git a/electron/menu.js b/electron/menu.js index 22d85b68..a73b6df7 100644 --- a/electron/menu.js +++ b/electron/menu.js @@ -382,6 +382,16 @@ if (process.platform === 'darwin') { helpSubmenu.push({ type: 'separator' }); + helpSubmenu.push({ + label: `Check for updates...`, + click(item, win) { + const webContents = win.webContents; + const send = webContents.send.bind(win.webContents); + electron.autoUpdater.checkForUpdates(); + electron.autoUpdater.once('update-available', (event) => send('autoUpdater:update-available')); + electron.autoUpdater.once('update-not-available', (event) => send('autoUpdater:update-not-available')); + } + }); helpSubmenu.push({ label: `About ${appName}`, click() { diff --git a/electron/updater.js b/electron/updater.js new file mode 100644 index 00000000..65d8938d --- /dev/null +++ b/electron/updater.js @@ -0,0 +1,18 @@ +const {app, autoUpdater, ipcMain} = require('electron'); +const version = app.getVersion(); +const platform = process.platform === 'darwin' ? 'osx' : process.platform; +const url = `https://getrambox.herokuapp.com/update/${platform}/${version}`; + +const initialize = (window) => { + const webContents = window.webContents; + const send = webContents.send.bind(window.webContents); + autoUpdater.on('checking-for-update', (event) => send('autoUpdater:checking-for-update:')); + autoUpdater.on('update-downloaded', (event, ...args) => send('autoUpdater:update-downloaded', ...args)); + ipcMain.on('autoUpdater:quit-and-install', (event) => autoUpdater.quitAndInstall()); + webContents.on('did-finish-load', () => { + autoUpdater.setFeedURL(url); + autoUpdater.checkForUpdates(); + }); +}; + +module.exports = {initialize}; diff --git a/package.json b/package.json index 6f040e0a..fe6af25b 100644 --- a/package.json +++ b/package.json @@ -10,13 +10,13 @@ "clean:osx": "rm -rf ./dist/Rambox-darwin-*", "clean:win": "rm -rf ./dist/Rambox-win32-*", "pack": "npm run pack:osx && npm run pack:win", - "pack:osx": "electron-packager \"./build/production/Rambox/\" \"Rambox\" --out=dist --platform=darwin --arch=x64 --version=1.2.7 --icon=resources/installer/Icon.icns --app-version=0.2.0 --build-version=64-bit --version-string.CompanyName=\"Rambox\" --version-string.ProductName=\"Rambox\" --asar --prune --overwrite", + "pack:osx": "electron-packager \"./build/production/Rambox/\" \"Rambox\" --out=dist --platform=darwin --arch=x64 --version=1.3.1 --icon=resources/installer/Icon.icns --app-version=0.2.0 --build-version=64-bit --version-string.CompanyName=\"Rambox\" --version-string.ProductName=\"Rambox\" --asar --prune --overwrite", "pack:win": "npm run pack:win32 && npm run pack:win64", - "pack:win32": "electron-packager \"./build/production/Rambox/\" \"Rambox\" --out=dist --platform=win32 --arch=ia32 --version=1.2.7 --icon=resources/installer/Icon.ico --app-version=0.2.0 --build-version=32-bit --version-string.CompanyName=\"Rambox\" --version-string.ProductName=\"Rambox\" --asar --prune --overwrite", - "pack:win64": "electron-packager \"./build/production/Rambox/\" \"Rambox\" --out=dist --platform=win32 --arch=x64 --version=1.2.7 --icon=resources/installer/Icon.ico --app-version=0.2.0 --build-version=64-bit --version-string.CompanyName=\"Rambox\" --version-string.ProductName=\"Rambox\" --asar --prune --overwrite", + "pack:win32": "electron-packager \"./build/production/Rambox/\" \"Rambox\" --out=dist --platform=win32 --arch=ia32 --version=1.3.1 --icon=resources/installer/Icon.ico --app-version=0.2.0 --build-version=32-bit --version-string.CompanyName=\"Rambox\" --version-string.ProductName=\"Rambox\" --asar --prune --overwrite", + "pack:win64": "electron-packager \"./build/production/Rambox/\" \"Rambox\" --out=dist --platform=win32 --arch=x64 --version=1.3.1 --icon=resources/installer/Icon.ico --app-version=0.2.0 --build-version=64-bit --version-string.CompanyName=\"Rambox\" --version-string.ProductName=\"Rambox\" --asar --prune --overwrite", "pack:linux": "npm run pack:linux32 && npm run pack:linux64", - "pack:linux32": "electron-packager \"./build/production/Rambox/\" \"Rambox\" --out=dist --platform=linux --arch=ia32 --version=1.2.7 --icon=resources/installer/Icon.ico --app-version=0.2.0 --build-version=64-bit --version-string.CompanyName=\"Rambox\" --version-string.ProductName=\"Rambox\" --asar --prune --overwrite", - "pack:linux64": "electron-packager \"./build/production/Rambox/\" \"Rambox\" --out=dist --platform=linux --arch=x64 --version=1.2.7 --icon=resources/installer/Icon.ico --app-version=0.2.0 --build-version=64-bit --version-string.CompanyName=\"Rambox\" --version-string.ProductName=\"Rambox\" --asar --prune --overwrite", + "pack:linux32": "electron-packager \"./build/production/Rambox/\" \"Rambox\" --out=dist --platform=linux --arch=ia32 --version=1.3.1 --icon=resources/installer/Icon.ico --app-version=0.2.0 --build-version=64-bit --version-string.CompanyName=\"Rambox\" --version-string.ProductName=\"Rambox\" --asar --prune --overwrite", + "pack:linux64": "electron-packager \"./build/production/Rambox/\" \"Rambox\" --out=dist --platform=linux --arch=x64 --version=1.3.1 --icon=resources/installer/Icon.ico --app-version=0.2.0 --build-version=64-bit --version-string.CompanyName=\"Rambox\" --version-string.ProductName=\"Rambox\" --asar --prune --overwrite", "build": "npm run build:linux && npm run build:osx && npm run build:win", "build:osx": "build \"dist/Rambox-darwin-x64/Rambox.app\" --platform=osx", "build:linux": "npm run build:linux32 && npm run build:linux64", @@ -24,7 +24,7 @@ "build:linux64": "build --linux --x64", "build:win": "node ./build/winstaller.js ia32 && node ./build/winstaller.js x64", "build:win32": "node ./build/winstaller.js ia32", - "build:win64": "node ./build/winstaller.js x64", + "build:win64": "build --win --x64", "setup:osx": "npm run sencha:clean && npm run sencha:compile && npm run clean:osx && npm run pack:osx && npm run build:osx", "setup:win": "npm run sencha:clean && npm run sencha:compile && npm run clean:win && npm run pack:win && npm run build:win", "zip:win32": "bestzip \"dist/Rambox-win32-ia32-portable.zip\" \"dist/Rambox-win32-ia32/*\"", @@ -43,7 +43,15 @@ "homepage": "http://www.rambox.pro", "build": { "productName": "Rambox", + "appId": "com.saenzramiro.rambox", + "app-category-type": "public.app-category.productivity", "asar": true, + "protocols": [ + { + "name": "Rambox", + "schemes": ["rambox"] + } + ], "dmg": { "title": "Rambox", "icon-size": 128, @@ -63,19 +71,26 @@ }, "win": { "title": "Rambox", - "target": ["squirrel", "zip"], + "target": [ + "squirrel", + "zip" + ], "loadingGif": "./resources/installer/loading.gif", + "iconUrl": "https://raw.githubusercontent.com/saenzramiro/rambox/master/resources/Icon.ico", "icon": "./resources/Icon.ico", "msi": false }, "linux": { "target": [ + "AppImage", "deb", "zip", - "tar.gz", - "rpm" + "tar.gz" + ], + "depends": [ + "libappindicator1", + "libnotify-bin" ], - "depends": ["libappindicator1", "libnotify-bin"], "icon": "./resources/Icon.png" } }, @@ -85,12 +100,12 @@ "app": "build/production/Rambox/" }, "devDependencies": { - "asar": "^0.11.0", + "asar": "^0.12.1", "bestzip": "^1.1.3", - "electron-builder": "5.12.1", + "electron-builder": "5.17.0", "electron-installer-windows": "^0.2.0", - "electron-packager": "7.0.1", - "electron-prebuilt": "1.2.7", + "electron-packager": "7.3.0", + "electron-prebuilt": "1.3.1", "electron-squirrel-startup": "^1.0.0", "electron-winstaller": "^2.3.0", "spectron": "^3.2.3" @@ -111,6 +126,7 @@ "firebase": "^3.0.5", "firebase-token-generator": "^2.0.0", "tmp": "0.0.28", - "mime": "^1.3.4" + "mime": "^1.3.4", + "electron-is-dev": "^0.1.1" } }