Slide 1

Slide 1 text

Building Desktop Apps with and node-webkit Ember SF Meetup - April 29, 2014

Slide 2

Slide 2 text

PeterJihoon Kim Co-founder & CTO at NITROUS.IO @raingrove

Slide 3

Slide 3 text

Demo:
 Nitrous.IO and
 Nitrous Desktop

Slide 4

Slide 4 text

Desktop Apps

Slide 5

Slide 5 text

Responsive

Slide 6

Slide 6 text

Convenient

Slide 7

Slide 7 text

Works Offline

Slide 8

Slide 8 text

Platform Features

Slide 9

Slide 9 text

No content

Slide 10

Slide 10 text

is awesome

Slide 11

Slide 11 text

No content

Slide 12

Slide 12 text

App.UiSwitchComponent = Ember.Component.extend({ classNames: ['ui-switch'], classNameBindings: ['enabled:on'], enabled: false, ! click: function() { this.toggleProperty('enabled'); } }); {{ui-switch enabled=enabled}}

Slide 13

Slide 13 text

Demo:
 Building a Custom UI Component with Ember

Slide 14

Slide 14 text

a framework for creating ambitious web applications

Slide 15

Slide 15 text

a framework for creating ambitious web applications *html5 runtime required

Slide 16

Slide 16 text

Slide 17

Slide 17 text

Chromium

Slide 18

Slide 18 text

No content

Slide 19

Slide 19 text

node-webkit

Slide 20

Slide 20 text

Slide 21

Slide 21 text

No content

Slide 22

Slide 22 text

Demo:
 Ember Starter Kit
 in node-webkit

Slide 23

Slide 23 text

node-webkit Overview

Slide 24

Slide 24 text

var gui = require('nw.gui'); GUI module

Slide 25

Slide 25 text

 MyApp 7:40 PM File Edit gui.Menu gui.Tray gui.Window gui.App gui.Clipboard gui.Shell

Slide 26

Slide 26 text

File Dialog $('#open-file').click(); $('#open-file').val();

Slide 27

Slide 27 text

Slide 28

Slide 28 text

App.UiFileDialogComponent = Ember.Component.extend({ classNames: ['ui-file-dialog'], tagName: 'input', attributeBindings: [ 'type', 'accept', 'style', 'directory:nwdirectory', 'save:nwsaveas' ], type: 'file', style: 'display: none', ! value: '', accept: null, directory: false, save: false, ! open: function() { this.$().click(); }, ! change: function() { this.set('value', this.$().val()); } });

Slide 29

Slide 29 text

{{ui-file-dialog id="open-file" value=fileToOpen}}

Slide 30

Slide 30 text

Demo:
 File Dialog

Slide 31

Slide 31 text

Persisting State html5 local storage Web SQL IndexedDB node fs module

Slide 32

Slide 32 text

Debugging Dev Tools Refresh var gui = require('nw.gui'), win = gui.Window.get(); ! $('#debug .refresh').click(function() { win.reloadIgnoringCache(); }); ! $('#debug .devtools').click(function() { win.showDevTools(); });

Slide 33

Slide 33 text

Testing Run Tests $('#debug .run-tests').click(function() { gui.Window.open(location.href + '?test', { toolbar: true }); });

Slide 34

Slide 34 text

On/Offline Detection MyDesktopApp = Ember.Application.extend({ online: navigator.onLine, offline: Em.computed.not('online') }); ! App = MyDesktopApp.create(); ! $(window).on('online offline', function() { App.set('online', navigator.onLine); }); {{#if App.offline}} No Internet Connection? :-( {{else}} Yay! {{/if}}

Slide 35

Slide 35 text

Platform Detection var os = require('os'); ! MyDesktopApp = Ember.Application.extend({ platform: { isWindows: os.type() == 'Windows_NT', isMac: os.type() == 'Darwin', isLinux: os.type() == 'Linux' } });
 ! App = MyDesktopApp.create(); {{#if App.platform.isMac}} Hi, I am a Mac. {{else}}{{#if App.platform.isWindows}} I am a PC. {{/if}}{{/if}}

Slide 36

Slide 36 text

Window Reuse App.SignInRoute App.MainRoute

Slide 37

Slide 37 text

var win = require('nw.gui').Window.get(); ! App.SignInRoute = Em.Route.extend({ deactivate: function() { win.hide(); } }); ! App.MainRoute = Em.Route.extend({ activate: function() { win.resizeTo(1000, 500); win.moveTo(...); win.show(); } });

Slide 38

Slide 38 text

Packaging

Slide 39

Slide 39 text

Mac or folder containing
 app code named ‘app.nw’ zip archive containing
 app code named ‘app.nw’

Slide 40

Slide 40 text

Windows or place a folder containing
 app code named ‘package.nw’ place a zip archive containing
 app code named ‘package.nw’ copy /b nw.exe+package.nw myapp.exe optional

Slide 41

Slide 41 text

Thanks & We’re hiring! www.nitrous.io/jobs

Slide 42

Slide 42 text

PeterJihoon Kim [email protected] @raingrove @NitrousIO