Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Electron: Construindo Aplicações Desktop Multi-...

Electron: Construindo Aplicações Desktop Multi-Plataforma com HTML, CSS e JS

Palestra apresentada por Rafa Jaques no 17º Fórum Internacional de Software Livre

O objetivo dessa palestra é apresentar a ferramenta open source Atom Electron que permite a criação de aplicativos desktop multi-plataforma com a util ização de tecnologias web. HTML, CSS, JavaScript e NodeJS estão entre as tecnologias disponíveis no Electron. Exemplos de código e aplicações que vão te inspirar a desenvolver seus próprios programas.

Rafa Jaques

July 15, 2016
Tweet

More Decks by Rafa Jaques

Other Decks in Programming

Transcript

  1. “Os que confiam no SENHOR serão como o monte de

    Sião, que não se abala, mas permanece para sempre.” (Salmo 125.1)
  2. Rafael Jaques @rafajaques Professor do IFRS Desenvolvedor web e viciado

    em segurança Entusiasta Open Source Evangelista PHP e Electron rafajaques.com.br phpit.com.br github.com/rafajaques speakerdeck.com/rafajaques
  3. O que veremos? O que é o Electron? Como funciona?

    O que já existe? Primeiros passos Distribuindo a aplicação E várias outras coisas…
  4. Plataformas suportadas Electron >= 1.0.0 >= 7 x86; x64 Ubuntu

    >= 12 Fedora >= 21 Debian >= 8 Possivelmente outras x86; x64; arm >= 10.9 x64
  5. Renderer Página Web Main Ciclo de vida da app browser-window

    ipc Node.js menu dialog web-frame ipc Node.js DOM remote
  6. main.js const {app,BrowserWindow} = require('electron'); let mainWindow = null; app.on('ready',

    () => { mainWindow = new BrowserWindow({width:800, height:600}); mainWindow.loadURL('file://' + __dirname + '/index.html'); });
  7. Main Renderer Ambos app autoUpdater BrowserWindow contentTracing dialog DownloadItem globalShortcut

    ipcMain Menu MenuItem powerMonitor powerSaveBlocker protocol session systemPreferences Tray webContents desktopCapturer File Object ipcRenderer remote webFrame clipboard crashReporter nativeImage process screen shell
  8. app Controla o ciclo de vida da aplicação app.quit() app.relaunch()

    app.focus() app.getLocale() app.setBadgeCount() [OSX,Linux] app.dock.bounce() [OSX] http://electron.atom.io/docs/api/app/
  9. BrowserWindow // No processo principal const {BrowserWindow} = require('electron'); //

    Ou no processo renderer const {BrowserWindow} = require('electron').remote; let win = new BrowserWindow({width: 800, height: 600}); win.on('closed', () => { win = null; }); win.loadURL('http://rafajaques.com.br'); // http://electron.atom.io/docs/api/browser-window/
  10. dialog Manipula janelas nativas do sistema (abrir, salvar etc.) dialog.showOpenDialog()

    dialog.showSaveDialog() dialog.showMessageBox() dialog.showErrorBox() http://electron.atom.io/docs/api/dialog/
  11. dialog let win = ...; // BrowserWindow na qual será

    aberta a janela const {dialog} = require('electron'); console.log(dialog.showOpenDialog({ properties: [ 'openFile', // Janela para abrir arquivo 'openDirectory', // Permitir abrir diretórios 'multiSelections' // Permitir selecionar vários itens ] }));
  12. screen // Criar uma janela que ocupa toda a tela

    const electron = require('electron'); const {app, BrowserWindow} = electron; let win app.on('ready', () => { const {width, height} = electron.screen.getPrimaryDisplay().workAreaSize; win = new BrowserWindow({width, height}); }); // http://electron.atom.io/docs/api/screen/
  13. Tray Adiciona ícones e menus à área de notificação do

    sistema Existem algumas limitações http://electron.atom.io/docs/api/tray/
  14. Tray const {app, Menu, Tray} = require('electron'); let tray =

    null; app.on('ready', () => { tray = new Tray('/caminho/para/o/icone'); const contextMenu = Menu.buildFromTemplate([ {label: 'Opção 1', type: 'radio'}, {label: 'Opção 2', type: 'radio'}, {label: 'Opção 3', type: 'radio', checked: true}, {label: 'Opção 4', type: 'radio'} ]); tray.setToolTip('Balãozinho da aplicação'); tray.setContextMenu(contextMenu); });
  15. IPC - Assíncrono // Processo principal const {ipcMain} = require('electron');

    ipcMain.on('mensagem-assincrona', (event, arg) => { console.log(arg); // "ping" event.sender.send('resposta-assincrona', 'pong'); }); // No processo renderer (página web) const {ipcRenderer} = require('electron'); ipcRenderer.on('resposta-assincrona', (event, arg) => { console.log(arg); // "pong" }); ipcRenderer.send('mensagem-assincrona', 'ping');
  16. IPC - Síncrono // Processo principal const {ipcMain} = require('electron');

    ipcMain.on('mensagem-sincrona', (event, arg) => { console.log(arg); // "ping" event.returnValue = 'pong'; }); // No processo renderer (página web) const {ipcRenderer} = require('electron'); console.log(ipcRenderer.sendSync('mensagem-sincrona', 'ping')); // "pong"
  17. Executar JS via webContents // Caso a sua janela esteja

    na variável "mainWindow" mainWindow.webContents.executeJavaScript( 'alert("Funcionando!")' ); Tente evitar…
  18. // Não tem Electron envolvido, apenas Node.js const fs =

    require('fs'); fs.writeFileSync('arquivo.txt', 'Aqui eu escrevo!');
  19. const electron = require('electron'); const {app, BrowserWindow} = require('electron'); let

    win; app.on('ready', () => { let displays = electron.screen.getAllDisplays(); let externalDisplay = displays.find((display) => { return display.bounds.x !== 0 || display.bounds.y !== 0; }); if (externalDisplay) { win = new BrowserWindow({ x: externalDisplay.bounds.x + 50, y: externalDisplay.bounds.y + 50 }); } else { console.log('Sem monitor externo :('); } });
  20. const template = [ { label: 'Visualizar', submenu: [ {

    label: 'Recarregar', accelerator: 'CmdOrCtrl+R', click(item, focusedWindow) { if (focusedWindow) focusedWindow.reload(); } }, [...]
  21. { label: 'Toggle Developer Tools', accelerator: process.platform === 'darwin' ?

    'Alt+Command+I' : 'Ctrl+Shift+I', click(item, focusedWindow) { if (focusedWindow) focusedWindow.webContents.toggleDevTools(); } }, ] }, [...]
  22. { role: 'window', submenu: [ { role: 'minimize' }, {

    role: 'close' }, ] } ]; const menu = Menu.buildFromTemplate(template); Menu.setApplicationMenu(menu);
  23. Electron Builder 1. Dependências NPM compiladas nativamente 2. Code Signing

    3. Auto Update (Windows e Mac) 4. Publica para o GitHub Releases
  24. Mas não precisa se preocupar com isso… Um servidor de

    integração contínua resolve o problema
  25. 1º passo Estrutura com dois package.json Electron Builder Raiz ʮʒʒ

    app ʔ ʮʒʒ index.html ʔ ʮʒʒ main.js ʔ ʦʒʒ package.json ʮʒʒ build ʮʒʒ node_modules ʦʒʒ package.json devDependencies dependencies
  26. 2º passo Definir os campos obrigatórios do package.json Electron Builder

    name description version author homepage license
  27. Artefatos Todas as plataformas: 7z, zip, tar.xz, tar.lz, tar.gz, tar.bz2

    Mac OS: dmg, mas Linux: AppImage, deb, rpm, freebsd, pacman, p5p, apk Windows: NSIS, Squirrel.Windows (ambos exe)
  28. +

  29. .travis.yml language: node_js matrix: include: - os: osx osx_image: xcode7.3

    node_js: '4' - os: linux env: CC=clang CXX=clang++ npm_config_clang=1 compiler: clang sudo: required dist: trusty node_js: ‘4' [...]
  30. .travis.yml cache: directories: - node_modules - app/node_modules - "$HOME/.electron" addons:

    apt: packages: - icnsutils - graphicsmagick - xz-utils - gcc-multilib - g++-multilib install: - npm install after_success: - npm run publish:$TRAVIS_OS_NAME
  31. appveyor.yml version: 0.1.{build} platform: - x64 cache: - node_modules -

    app\node_modules - '%APPDATA%\npm-cache' - '%USERPROFILE%\.electron' install: - git reset --hard HEAD - npm install npm -g - npm install electron-builder - npm install - npm prune build_script: - npm run publish:win
  32. package.json { "scripts": { "publish:osx": "build --osx --publish onTagOrDraft", "publish:linux":

    "build --linux deb rpm freebsd pacman tar.xz --publish onTagOrDraft", "publish:linux32": "build --linux tar.xz --ia32 --publish onTagOrDraft", "publish:linux64": "build --linux tar.xz --x64 --publish onTagOrDraft", "publish:win": "build --windows --x64 --publish onTagOrDraft" } }