├── .gitignore ├── LICENSE ├── README.md ├── angular-electron.js ├── angular-electron.min.js ├── bower.json ├── gulpfile.js ├── index.js ├── package.json ├── src ├── external-link.js ├── process.js ├── remote.js ├── rendererModules.js └── safeShutdown.js └── test ├── index.html ├── index.js ├── main.js └── package.json /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | 3 | node_modules/ 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Oz 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # angular-electron 2 | 3 | angularjs helpers for electron apps 4 | 5 | ## Installation 6 | 7 | ```bash 8 | npm install angular-electron 9 | ``` 10 | 11 | ```bash 12 | bower install angular-electron 13 | ``` 14 | 15 | > Use 0.1.x for electron < 0.35.0 and 0.2.x for electron > 0.35.0 16 | 17 | ## Usage 18 | 19 | ```html 20 |
21 | 22 | 23 | 24 | ``` 25 | 26 | ```js 27 | angular.module('myModule', ['angular-electron']); 28 | ``` 29 | 30 | ## API 31 | 32 | ### renderer modules 33 | 34 | These are all the **renderer modules** that are available as angular services: 35 | 36 | `desktopCapturer, ipcRenderer, webFrame, clipboard, crashReporter, nativeImage, screen, shell` 37 | 38 | To use them, simply inject them to your components: 39 | 40 | ```js 41 | angular.module('myModule').controller('myCtrl', ['shell', function(shell) { 42 | shell.showItemInFolder(pathToItem); 43 | }]); 44 | ``` 45 | 46 | ### remote and node modules 47 | 48 | These are all the **main modules** that are available as angular services: 49 | 50 | `app, autoUpdater, BrowserWindow, contentTracing, dialog, globalShortcut, Menu, MenuItem, powerMonitor, 51 | powerSaveBlocker, protocol, webContents, tray` 52 | 53 | **Node modules**: 54 | 55 | `buffer, child_process, cluster, crypto, dns, events, fs, http, https, net, os, path, punycode, 56 | querystring, readline, stream, string_decoder, tls, dgram, url, util, v8, vm, zlib` 57 | 58 | > All of the modules are lazy required (required only on use). 59 | 60 | ### remoteProvider 61 | 62 | In order to use a node package (e.g. moment), use the remoteProvider to 63 | register the package to an angular service. 64 | 65 | ```js 66 | angular.module('myModule').config(['remoteProvider', function(remoteProvider) { 67 | remoteProvider.register('moment'); 68 | }]); 69 | ``` 70 | 71 | or 72 | 73 | ```js 74 | angular.module('myModule').config(['remoteProvider', function(remoteProvider) { 75 | remoteProvider.register({name: 'newName', require: 'moment'}); 76 | }]); 77 | ``` 78 | 79 | then inject it as a regular service 80 | 81 | ```js 82 | angular.module('myModule').controller('myCtrl', ['moment', function(moment) { 83 | 84 | }]); 85 | ``` 86 | 87 | or 88 | 89 | ```js 90 | angular.module('myModule').controller('myCtrl', ['newName', function(moment) { 91 | 92 | }]); 93 | ``` 94 | 95 | You can also register a module by function: 96 | 97 | ```js 98 | angular.module('myModule').config(['remoteProvider', function(remoteProvider) { 99 | remoteProvider.register('exec', function(remote) { 100 | return remote.require('child_process').exec; 101 | }); 102 | }]); 103 | ``` 104 | 105 | then use it 106 | 107 | ```js 108 | angular.module('myModule').controller('myCtrl', ['exec', function(exec) { 109 | exec('ls'); 110 | }]); 111 | ``` 112 | 113 | ### process objects 114 | 115 | electron process objects are available as angularjs constants. 116 | 117 | ```js 118 | angular.module('myModule').controller('myCtrl', ['process', 'remoteProcess', 119 | function(process, remoteProcess) { 120 | 121 | }]); 122 | ``` 123 | 124 | ### current window 125 | 126 | The current window is also available as angularjs constant. 127 | 128 | ```js 129 | angular.module('myModule').controller('myCtrl', ['currentWindow', 130 | function(currentWindow) { 131 | 132 | }]); 133 | ``` 134 | 135 | ### current web contents 136 | 137 | The current web contents module is also available as angularjs constant. 138 | 139 | ```js 140 | angular.module('myModule').controller('myCtrl', ['currentWebContents', 141 | function(currentWebContents) { 142 | 143 | }]); 144 | ``` 145 | 146 | ### external link 147 | 148 | This is a directive which opens a link in the default desktop browser. 149 | 150 | ```html 151 | google 152 | 153 | ``` 154 | 155 | ### safe shutdown 156 | 157 | safe shutdown is a service which handles pre-shudown actions. 158 | 159 | ```js 160 | angular.module('myModule').controller('myCtrl', ['safeShutdown', 161 | function(safeShutdown) { 162 | safeShutdown.register(function() { 163 | logout(); 164 | }); 165 | }]); 166 | ``` 167 | 168 | > The function can return a promise to handle async operations. 169 | 170 | > You can register multiple functions 171 | 172 | Then use `currentWindow.safeReload` or `app.safeQuit` to reload/quit your app. 173 | 174 | > These methods are available only after safeShutdown is instantiated. 175 | -------------------------------------------------------------------------------- /angular-electron.js: -------------------------------------------------------------------------------- 1 | (function(angular, electronRequire, electronProcess, undefined) {'use strict'; 2 | 3 | angular.module('angular-electron', []); 4 | 5 | angular.module('angular-electron').directive('externalLink', ['shell', function (shell) { 6 | return { 7 | restrict: 'A', 8 | link: function(scope, elem, attrs) { 9 | elem.on('click', function(event) { 10 | event.preventDefault(); 11 | 12 | shell.openExternal(attrs.href || attrs.externalLink); 13 | }); 14 | } 15 | }; 16 | }]); 17 | 18 | angular.module('angular-electron').constant('process', electronProcess); 19 | 20 | var remoteModules = ['app', 'autoUpdater', 'BrowserWindow', 'contentTracing', 'dialog', 21 | 'globalShortcut', 'Menu', 'MenuItem', 'powerMonitor', 'powerSaveBlocker', 22 | 'protocol', 'webContents', 'tray']; 23 | var nodeModules = ['buffer', 'child_process', 'cluster', 'crypto', 'dns', 'events', 'fs', 'http', 24 | 'https', 'net', 'os', 'path', 'punycode', 'querystring', 'readline', 'stream', 25 | 'string_decoder', 'tls', 'dgram', 'url', 'util', 'v8', 'vm', 'zlib']; 26 | 27 | angular.module('angular-electron').provider('remote', ['$provide', function($provide) { 28 | var remote = electronRequire('electron').remote; 29 | 30 | function registerElectronModule(_module) { 31 | $provide.service(_module, function() { 32 | return remote[_module]; 33 | }); 34 | } 35 | 36 | function registerNodeModule(name, _require) { 37 | _require = _require || name; 38 | 39 | $provide.service(name, function() { 40 | return typeof _require === 'function' ? _require(remote) : remote.require(_require); 41 | }); 42 | } 43 | 44 | this.register = registerNodeModule; 45 | 46 | this.$get = [function() { 47 | return remote; 48 | }]; 49 | 50 | $provide.constant('remoteProcess', remote.process); 51 | $provide.constant('currentWindow', remote.getCurrentWindow()); 52 | $provide.constant('currentWebContents', remote.getCurrentWebContents()); 53 | 54 | angular.forEach(remoteModules, function(remoteModule) { 55 | registerElectronModule(remoteModule); 56 | }); 57 | 58 | angular.forEach(nodeModules, function(nodeModule) { 59 | registerNodeModule(nodeModule.name || nodeModule, nodeModule.require); 60 | }); 61 | }]); 62 | 63 | var wrapModules = ['desktopCapturer', 'ipcRenderer', 'webFrame', 'clipboard', 'crashReporter', 'nativeImage', 'screen', 'shell']; 64 | 65 | angular.forEach(wrapModules, function (_module) { 66 | angular.module('angular-electron').service(_module.name || _module, [function() { 67 | return electronRequire('electron')[_module.require || _module]; 68 | }]); 69 | }); 70 | 71 | angular.module('angular-electron').service('safeShutdown', ['$q', 'currentWindow', 'app', function($q, currentWindow, app) { 72 | var actions = []; 73 | 74 | function register(fn) { 75 | actions.push(fn); 76 | } 77 | 78 | function exec() { 79 | var promises = []; 80 | 81 | angular.forEach(actions, function (action) { 82 | var res = action(); 83 | 84 | if (res !== undefined && res.then !== undefined) { 85 | promises.push(res); 86 | } 87 | }); 88 | 89 | return $q.all(promises); 90 | } 91 | 92 | currentWindow.safeReload = function() { 93 | exec().then(function() { 94 | currentWindow.reload(); 95 | }); 96 | }; 97 | 98 | app.safeQuit = function() { 99 | exec().then(function() { 100 | app.quit(); 101 | }); 102 | }; 103 | 104 | return { 105 | register: register 106 | }; 107 | }]); 108 | 109 | })(window.angular, window.require, window.process); 110 | -------------------------------------------------------------------------------- /angular-electron.min.js: -------------------------------------------------------------------------------- 1 | !function(e,n,r,t){"use strict";e.module("angular-electron",[]),e.module("angular-electron").directive("externalLink",["shell",function(e){return{restrict:"A",link:function(n,r,t){r.on("click",function(n){n.preventDefault(),e.openExternal(t.href||t.externalLink)})}}}]),e.module("angular-electron").constant("process",r);var o=["app","autoUpdater","BrowserWindow","contentTracing","dialog","globalShortcut","Menu","MenuItem","powerMonitor","powerSaveBlocker","protocol","webContents","tray"],c=["buffer","child_process","cluster","crypto","dns","events","fs","http","https","net","os","path","punycode","querystring","readline","stream","string_decoder","tls","dgram","url","util","v8","vm","zlib"];e.module("angular-electron").provider("remote",["$provide",function(r){function t(e){r.service(e,function(){return i[e]})}function u(e,n){n=n||e,r.service(e,function(){return"function"==typeof n?n(i):i.require(n)})}var i=n("electron").remote;this.register=u,this.$get=[function(){return i}],r.constant("remoteProcess",i.process),r.constant("currentWindow",i.getCurrentWindow()),r.constant("currentWebContents",i.getCurrentWebContents()),e.forEach(o,function(e){t(e)}),e.forEach(c,function(e){u(e.name||e,e.require)})}]);var u=["desktopCapturer","ipcRenderer","webFrame","clipboard","crashReporter","nativeImage","screen","shell"];e.forEach(u,function(r){e.module("angular-electron").service(r.name||r,[function(){return n("electron")[r.require||r]}])}),e.module("angular-electron").service("safeShutdown",["$q","currentWindow","app",function(n,r,o){function c(e){i.push(e)}function u(){var r=[];return e.forEach(i,function(e){var n=e();n!==t&&n.then!==t&&r.push(n)}),n.all(r)}var i=[];return r.safeReload=function(){u().then(function(){r.reload()})},o.safeQuit=function(){u().then(function(){o.quit()})},{register:c}}])}(window.angular,window.require,window.process); -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "angular-electron", 3 | "description": "angularjs helpers for electron apps", 4 | "main": "angular-electron.js", 5 | "authors": [ 6 | "Oz Sayag" 7 | ], 8 | "license": "MIT", 9 | "keywords": [ 10 | "angular", 11 | "angularjs", 12 | "electron" 13 | ], 14 | "homepage": "https://github.com/ozsay/angular-electron", 15 | "ignore": [ 16 | "**/.*", 17 | "node_modules", 18 | "bower_components", 19 | "test", 20 | "tests" 21 | ] 22 | } 23 | -------------------------------------------------------------------------------- /gulpfile.js: -------------------------------------------------------------------------------- 1 | var gulp = require('gulp'), 2 | concat = require('gulp-concat'), 3 | insert = require('gulp-insert'), 4 | uglify = require('gulp-uglify'); 5 | 6 | var HEADER = "(function(angular, electronRequire, electronProcess, undefined) {'use strict';\n\n" + 7 | "angular.module('angular-electron', []);\n\n"; 8 | var FOOTER = "\n})(window.angular, window.require, window.process);\n"; 9 | 10 | gulp.task('build:dev', function () { 11 | return gulp.src('./src/*') 12 | .pipe(concat('angular-electron.js')) 13 | .pipe(insert.prepend(HEADER)) 14 | .pipe(insert.append(FOOTER)) 15 | .pipe(gulp.dest('./')); 16 | }); 17 | 18 | gulp.task('build:prod', function () { 19 | return gulp.src('./src/*') 20 | .pipe(concat('angular-electron.min.js')) 21 | .pipe(insert.prepend(HEADER)) 22 | .pipe(insert.append(FOOTER)) 23 | .pipe(uglify()) 24 | .pipe(gulp.dest('./')); 25 | }); 26 | 27 | gulp.task('build', ['build:dev', 'build:prod'], function() { 28 | }); 29 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | require('./angular-electron'); 2 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "angular-electron", 3 | "version": "0.2.1", 4 | "description": "angularjs helpers for electron apps", 5 | "repository": { 6 | "type": "git", 7 | "url": "git+https://github.com/ozsay/angular-electron.git" 8 | }, 9 | "main": "index.js", 10 | "keywords": [ 11 | "angular", 12 | "angularjs", 13 | "electron" 14 | ], 15 | "author": "Oz Sayag", 16 | "license": "MIT", 17 | "bugs": { 18 | "url": "https://github.com/ozsay/angular-electron/issues" 19 | }, 20 | "homepage": "https://github.com/ozsay/angular-electron", 21 | "dependencies": { 22 | "angular": "^1.2.29" 23 | }, 24 | "devDependencies": { 25 | "gulp": "^3.9.0", 26 | "gulp-concat": "^2.6.0", 27 | "gulp-insert": "^0.5.0", 28 | "gulp-uglify": "^1.4.2" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/external-link.js: -------------------------------------------------------------------------------- 1 | angular.module('angular-electron').directive('externalLink', ['shell', function (shell) { 2 | return { 3 | restrict: 'A', 4 | link: function(scope, elem, attrs) { 5 | elem.on('click', function(event) { 6 | event.preventDefault(); 7 | 8 | shell.openExternal(attrs.href || attrs.externalLink); 9 | }); 10 | } 11 | }; 12 | }]); 13 | -------------------------------------------------------------------------------- /src/process.js: -------------------------------------------------------------------------------- 1 | angular.module('angular-electron').constant('process', electronProcess); 2 | -------------------------------------------------------------------------------- /src/remote.js: -------------------------------------------------------------------------------- 1 | var remoteModules = ['app', 'autoUpdater', 'BrowserWindow', 'contentTracing', 'dialog', 2 | 'globalShortcut', 'Menu', 'MenuItem', 'powerMonitor', 'powerSaveBlocker', 3 | 'protocol', 'webContents', 'tray']; 4 | var nodeModules = ['buffer', 'child_process', 'cluster', 'crypto', 'dns', 'events', 'fs', 'http', 5 | 'https', 'net', 'os', 'path', 'punycode', 'querystring', 'readline', 'stream', 6 | 'string_decoder', 'tls', 'dgram', 'url', 'util', 'v8', 'vm', 'zlib']; 7 | 8 | angular.module('angular-electron').provider('remote', ['$provide', function($provide) { 9 | var remote = electronRequire('electron').remote; 10 | 11 | function registerElectronModule(_module) { 12 | $provide.service(_module, function() { 13 | return remote[_module]; 14 | }); 15 | } 16 | 17 | function registerNodeModule(name, _require) { 18 | _require = _require || name; 19 | 20 | $provide.service(name, function() { 21 | return typeof _require === 'function' ? _require(remote) : remote.require(_require); 22 | }); 23 | } 24 | 25 | this.register = registerNodeModule; 26 | 27 | this.$get = [function() { 28 | return remote; 29 | }]; 30 | 31 | $provide.constant('remoteProcess', remote.process); 32 | $provide.constant('currentWindow', remote.getCurrentWindow()); 33 | $provide.constant('currentWebContents', remote.getCurrentWebContents()); 34 | 35 | angular.forEach(remoteModules, function(remoteModule) { 36 | registerElectronModule(remoteModule); 37 | }); 38 | 39 | angular.forEach(nodeModules, function(nodeModule) { 40 | registerNodeModule(nodeModule.name || nodeModule, nodeModule.require); 41 | }); 42 | }]); 43 | -------------------------------------------------------------------------------- /src/rendererModules.js: -------------------------------------------------------------------------------- 1 | var wrapModules = ['desktopCapturer', 'ipcRenderer', 'webFrame', 'clipboard', 'crashReporter', 'nativeImage', 'screen', 'shell']; 2 | 3 | angular.forEach(wrapModules, function (_module) { 4 | angular.module('angular-electron').service(_module.name || _module, [function() { 5 | return electronRequire('electron')[_module.require || _module]; 6 | }]); 7 | }); 8 | -------------------------------------------------------------------------------- /src/safeShutdown.js: -------------------------------------------------------------------------------- 1 | angular.module('angular-electron').service('safeShutdown', ['$q', 'currentWindow', 'app', function($q, currentWindow, app) { 2 | var actions = []; 3 | 4 | function register(fn) { 5 | actions.push(fn); 6 | } 7 | 8 | function exec() { 9 | var promises = []; 10 | 11 | angular.forEach(actions, function (action) { 12 | var res = action(); 13 | 14 | if (res !== undefined && res.then !== undefined) { 15 | promises.push(res); 16 | } 17 | }); 18 | 19 | return $q.all(promises); 20 | } 21 | 22 | currentWindow.safeReload = function() { 23 | exec().then(function() { 24 | currentWindow.reload(); 25 | }); 26 | }; 27 | 28 | app.safeQuit = function() { 29 | exec().then(function() { 30 | app.quit(); 31 | }); 32 | }; 33 | 34 | return { 35 | register: register 36 | }; 37 | }]); 38 | -------------------------------------------------------------------------------- /test/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 |