diff --git a/.gitignore b/.gitignore index bc8caf7..d1e8e33 100644 --- a/.gitignore +++ b/.gitignore @@ -1,11 +1,17 @@ + +# Created by https://www.gitignore.io/api/node,windows,osx,linux + +### Node ### # Logs logs *.log +npm-debug.log* # Runtime data pids *.pid *.seed +*.pid.lock # Directory for instrumented libs generated by jscoverage/JSCover lib-cov @@ -13,6 +19,9 @@ lib-cov # Coverage directory used by tools like istanbul coverage +# nyc test coverage +.nyc_output + # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) .grunt @@ -22,10 +31,78 @@ coverage # Compiled binary addons (http://nodejs.org/api/addons.html) build/Release -# Dependency directory -# https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git +# Dependency directories node_modules -bower_components +jspm_packages + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Optional REPL history +.node_repl_history + + +### Windows ### +# Windows image file caches +Thumbs.db +ehthumbs.db + +# Folder config file +Desktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows Installer files +*.cab +*.msi +*.msm +*.msp + +# Windows shortcuts +*.lnk + + +### OSX ### +*.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + + +### Linux ### +*~ + +# temporary files which can be created if a process still has a handle open of a deleted file +.fuse_hidden* + +# KDE directory preferences +.directory -# OSX specific ignores -.DS_Store +# Linux trash folder which might appear on any partition or disk +.Trash-* diff --git a/Dockerfile.template b/Dockerfile.template index 069f544..710497b 100644 --- a/Dockerfile.template +++ b/Dockerfile.template @@ -1,17 +1,22 @@ -FROM resin/%%RESIN_MACHINE_NAME%%-node:latest +FROM resin/%%RESIN_MACHINE_NAME%%-node:slim -## uncomment if you want systemd -# ENV INITSYSTEM on +# Install wget and curl +RUN apt-get clean && apt-get update && apt-get install -y \ + wget \ + curl + +# WTF is going on with httpredir from debian? removing it the dirty way +RUN sed -i "s/httpredir.debian.org/`curl -s -D - http://httpredir.debian.org/demo/debian/ | awk '/^Link:/ { print $2 }' | sed -e 's@;@\1@g'`/" /etc/apt/sources.list -# Install apt deps -RUN apt-get update && apt-get install -y \ +# Install other apt deps +RUN apt-get clean && apt-get update && apt-get install -y \ apt-utils \ + build-essential \ + clang \ xserver-xorg-core \ xserver-xorg-input-all \ xserver-xorg-video-fbdev \ xorg \ - build-essential \ - clang \ libdbus-1-dev \ libgtk2.0-dev \ libnotify-dev \ @@ -26,42 +31,37 @@ RUN apt-get update && apt-get install -y \ fluxbox \ libsmbclient \ libssh-4 \ - python-dev \ - python-pip \ - build-essential \ - git \ - curl \ - psmisc \ - libraspberrypi0 \ - libpcre3 \ - fonts-freefont-ttf \ fbset \ - bind9 \ - libdbus-1-dev \ - libexpat-dev \ - usbutils \ - && rm -rf /var/lib/apt/lists/* + libexpat-dev && rm -rf /var/lib/apt/lists/* # Set Xorg and FLUXBOX preferences RUN mkdir ~/.fluxbox RUN echo "xset s off\nxserver-command=X -s 0 dpms" > ~/.fluxbox/startup -RUN echo "#!/bin/sh\n\nexec /usr/bin/X -s 0 dpms -nocursor -nolisten tcp "$@"" > /etc/X11/xinit/xserverrc +RUN echo '#!/bin/sh\n\nexec /usr/bin/X -s 0 dpms -nocursor -nolisten tcp "$@"' > /etc/X11/xinit/xserverrc # Set npm RUN npm config set unsafe-perm true -# Move package to filesystem -COPY ./package.json ./app/ +# Save source folder +RUN printf "%s\n" "${PWD##}" > SOURCEFOLDER -# NPM i app -RUN npm i --prefix /app +# Move to app dir +WORKDIR /usr/src/app + +# Move package.json to filesystem +COPY "$SOURCEFOLDER/app/package.json" ./ +# NPM i app +RUN JOBS=MAX npm i --production # Move app to filesystem -COPY . ./app +COPY "$SOURCEFOLDER/app" ./ # NPM rebuild node native modules after electron is installed. -RUN ./app/node_modules/.bin/electron-rebuild +RUN ./node_modules/.bin/electron-rebuild + +## uncomment if you want systemd +ENV INITSYSTEM on # Start app -CMD ["bash", "/app/start.sh"] +CMD ["bash", "/usr/src/app/start.sh"] diff --git a/README.md b/README.md index 55759cf..53b9f0e 100644 --- a/README.md +++ b/README.md @@ -5,30 +5,43 @@ a boilerplate for developing kiosks, digital signage or other human-machine inte This is the very basic layer on which [snappin.io](http://snappin.io) builds its touch-enabled apps. -### PRE-REQUISITES -this application is meant to be deployed to [RaspberryPi](https://www.raspberrypi.org/products/) devices via [resin.io](http://resin.io). +## Getting started -At least 64MB of GPU-dedicated RAM is required. You can achieve that locally following [these instructions](http://docs.resin.io/#/pages/hardware/i2c-and-spi.md#raspberry-pi-camera-module) (only the first parameter `gpu_mem=64` is required) or, __as we strongly suggest__, set it remotely with Resin's [Advanced Boot Configuration](http://docs.resin.io/#/pages/configuration/advanced.md#modifying-config-txt-remotely-) feature. +- Sign up on [resin.io](https://dashboard.resin.io/signup) +- go throught the [getting started guide](http://docs.resin.io/raspberrypi/nodejs/getting-started/) and create a new RPI zero application +- clone this repository to your local workspace +- add the _resin remote_ to your local workspace using the useful shortcut in the dashboard UI ![remoteadd](https://raw.githubusercontent.com/resin-io-playground/boombeastic/master/docs/gitresinremote.png) +- `git push resin master` +- see the magic happening, your device is getting updated Over-The-Air! + +## Configure via [environment variables](https://docs.resin.io/management/env-vars/) +Variable Name | Value | Description | Device-specific +------------ | ------------- | ------------- | ------------- +RESIN_HOST_CONFIG_gpu_mem | a value from `64` to `160` | the amount of RAM dedicated to the GPU | Raspberry Pi (all revs) ### WHY THIS TEMPLATE -Achieving kinda-smooth desktop application display on a raspberrypi is hard. This project aims to provide a quickstart template. +Achieving kinda-smooth desktop application display on a devices like the raspberrypi is hard. This project aims to provide a quickstart template. ### WHY FLUXBOX We did a lot of researches and tests with several window managers. [Fluxbox](http://fluxbox.org/) ended up being the most balanced between minimum footprint and features ### URL LAUNCHER config via ENV VARS +*__!!! Please note that since `0.1.0` the `bool`-based env vars dropped `true` / `false` strings in favour of `0` / `1` ones. !!!__* -simply set these [environment varables](http://docs.resin.io/#/pages/management/env-vars.md) in your app via the resin dashboard to configure the behaviour of your devices +simply set these [environment varables](http://docs.resin.io/#/pages/management/env-vars.md) in your app via the resin dashboard to configure the behaviour of your devices. +*__Please note that the `bool` type definition in the table is meant to accept to either `0` or `1` values.__* * **`URL_LAUNCHER_URL`** *string* - the URL to be loaded. use `file:///app/app/index.html` to load a local electronJS (or any website) app - *defaults to* `file:///app/app/index.html` -* **`URL_LAUNCHER_NODE`** *bool* (converted from *string*) - whether or not enable nodejs - *defaults to* `false` -* **`URL_LAUNCHER_KIOSK`** *bool* (converted from *string*) - whether or not enter KIOSK mode - *defaults to* `true` +* **`URL_LAUNCHER_NODE`** *bool* (converted from *string*) - whether or not enable nodejs - *defaults to* `0` +* **`URL_LAUNCHER_KIOSK`** *bool* (converted from *string*) - whether or not enter KIOSK mode - *defaults to* `1` * **`URL_LAUNCHER_TITLE`** *string* - the title of the window. Seen only with `URL_LAUNCHER_FRAME`=`true` - *defaults to* `RESIN.IO` -* **`URL_LAUNCHER_FRAME`** *bool* (converted from *string*) - set to "true" to display the window frame. Seen only with `URL_LAUNCHER_KIOSK`=`false` - *defaults to* `false` -* **`URL_LAUNCHER_CONSOLE`** *bool* (converted from *string*) - set to "true" to display the debug console - *defaults to* `false` +* **`URL_LAUNCHER_FRAME`** *bool* (converted from *string*) - set to "true" to display the window frame. Seen only with `URL_LAUNCHER_KIOSK`=`false` - *defaults to* `0` +* **`URL_LAUNCHER_CONSOLE`** *bool* (converted from *string*) - set to "true" to display the debug console - *defaults to* `0` * **`URL_LAUNCHER_WIDTH`** *int* (converted from *string*) - - *defaults to* `1920` * **`URL_LAUNCHER_HEIGHT`** *int* (converted from *string*) - - *defaults to* `1080` -* **`URL_LAUNCHER_TOUCH`** *bool* (converted from *string*) - enables touch events if your device supports them - *defaults to* `false` -* **`URL_LAUNCHER_TOUCH_SIMULATE`** *bool* (converted from *string*) - simulates touch events - might be useful for touchscreen with partial driver support - be aware this could be a performance hog - *defaults to* `false` +* **`URL_LAUNCHER_TOUCH`** *bool* (converted from *string*) - enables touch events if your device supports them - *defaults to* `0` +* **`URL_LAUNCHER_TOUCH_SIMULATE`** *bool* (converted from *string*) - simulates touch events - might be useful for touchscreen with partial driver support - be aware this could be a performance hog - *defaults to* `0` +* **`URL_LAUNCHER_ZOOM`** *float* (converted from *string*) - The default zoom factor of the page, 3.0 represents 300% - *defaults to* `1.0` +* **`URL_LAUNCHER_OVERLAY_SCROLLBARS`** *bool* (converted from *string*) - enables overlay scrollbars - *defaults to* `0` diff --git a/bower.json b/app/bower.json similarity index 86% rename from bower.json rename to app/bower.json index f8b64ce..9734157 100644 --- a/bower.json +++ b/app/bower.json @@ -12,7 +12,7 @@ "electron", "js" ], - "homepage": "https://github.com/fwrgit/resin-electronjs", + "homepage": "https://github.com/resin-io/resin-electronjs", "moduleType": [], "private": true, "ignore": [ diff --git a/app/index.html b/app/data/index.html similarity index 100% rename from app/index.html rename to app/data/index.html diff --git a/app/main.js b/app/main.js new file mode 100644 index 0000000..983cd8f --- /dev/null +++ b/app/main.js @@ -0,0 +1,70 @@ +{ + 'use strict'; + + const electron = require('electron'); + const app = electron.app; + const BrowserWindow = electron.BrowserWindow; + + // simple parameters initialization + let electronConfig = { + "URL_LAUNCHER_TOUCH": (process.env.URL_LAUNCHER_TOUCH == null) ? 0 : parseInt(process.env.URL_LAUNCHER_TOUCH), + "URL_LAUNCHER_TOUCH_SIMULATE": (process.env.URL_LAUNCHER_TOUCH_SIMULATE == null) ? 0 : parseInt(process.env.URL_LAUNCHER_TOUCH_SIMULATE), + "URL_LAUNCHER_FRAME": (process.env.URL_LAUNCHER_FRAME == null) ? 0 : parseInt(process.env.URL_LAUNCHER_FRAME), + "URL_LAUNCHER_KIOSK": (process.env.URL_LAUNCHER_KIOSK == null) ? 1 : parseInt(process.env.URL_LAUNCHER_KIOSK), + "URL_LAUNCHER_NODE": (process.env.URL_LAUNCHER_NODE == null) ? 0 : parseInt(process.env.URL_LAUNCHER_NODE), + "URL_LAUNCHER_WIDTH": (process.env.URL_LAUNCHER_WIDTH == null) ? 1920 : parseInt(process.env.URL_LAUNCHER_WIDTH), + "URL_LAUNCHER_HEIGHT": (process.env.URL_LAUNCHER_HEIGHT == null) ? 1080 : parseInt(process.env.URL_LAUNCHER_HEIGHT), + "URL_LAUNCHER_TITLE": (process.env.URL_LAUNCHER_TITLE == null) ? "RESIN.IO" : process.env.URL_LAUNCHER_TITLE, + "URL_LAUNCHER_CONSOLE": (process.env.URL_LAUNCHER_CONSOLE == null) ? 0 : parseInt(process.env.URL_LAUNCHER_CONSOLE), + "URL_LAUNCHER_URL": (process.env.URL_LAUNCHER_URL == null) ? "file:////usr/src/app/data/index.html" : process.env.URL_LAUNCHER_URL, + "URL_LAUNCHER_ZOOM": (process.env.URL_LAUNCHER_ZOOM == null) ? 1.0 : parseFloat(process.env.URL_LAUNCHER_ZOOM), + "URL_LAUNCHER_OVERLAY_SCROLLBARS": (process.env.URL_LAUNCHER_OVERLAY_SCROLLBARS == null) ? 0 : parseInt(process.env.URL_LAUNCHER_OVERLAY_SCROLLBARS) + }; + + let window = null; + + + // enable touch events if your device supports them + if (electronConfig.URL_LAUNCHER_TOUCH) { + app.commandLine.appendSwitch("--touch-devices"); + } + // simulate touch events - might be useful for touchscreen with partial driver support + if (electronConfig.URL_LAUNCHER_TOUCH_SIMULATE) { + app.commandLine.appendSwitch("--simulate-touch-screen-with-mouse"); + } + + /* + we initialize our application display as a callback of the electronJS "ready" event + */ + app.on('ready', () => { + + // here we actually configure the behavour of electronJS + window = new BrowserWindow({ + width: parseInt(electronConfig.URL_LAUNCHER_WIDTH), + height: parseInt(electronConfig.URL_LAUNCHER_HEIGHT), + frame: (electronConfig.URL_LAUNCHER_FRAME) ? true : false, + title: electronConfig.URL_LAUNCHER_TITLE, + kiosk: (electronConfig.URL_LAUNCHER_KIOSK) ? true : false, + webPreferences: { + nodeIntegration: (electronConfig.URL_LAUNCHER_NODE) ? true : false, + zoomFactor: electronConfig.URL_LAUNCHER_ZOOM, + overlayScrollbars: (electronConfig.URL_LAUNCHER_OVERLAY_SCROLLBARS) ? true : false + } + }); + + window.webContents.on('did-finish-load', () => { + setTimeout(() => { + window.show(); + }, 300); + + }); + + // if the env-var is set to true, a portion of the screen will be dedicated to the chrome-dev-tools + if (electronConfig.URL_LAUNCHER_CONSOLE) { + window.openDevTools(); + } + + // the big red button, here we go + window.loadURL(electronConfig.URL_LAUNCHER_URL); + }); +} diff --git a/package.json b/app/package.json similarity index 60% rename from package.json rename to app/package.json index 4c24271..c44a053 100644 --- a/package.json +++ b/app/package.json @@ -1,7 +1,7 @@ { "name": "resin-electronjs", - "version": "0.0.3", - "description": "electronJS-based rpi resin application", + "version": "0.1.0", + "description": "electronJS-based resin application", "main": "main.js", "scripts": { "start": "NODE_ENV=production startx ./node_modules/electron-prebuilt/dist/electron .", @@ -9,7 +9,7 @@ }, "repository": { "type": "git", - "url": "git+https://github.com/fwrgit/resin-electronjs.git" + "url": "git+https://github.com/resin-io/resin-electronjs.git" }, "keywords": [ "resin", @@ -18,15 +18,15 @@ "js" ], "dependencies": { - "electron-prebuilt": "^1.1.3", - "electron-rebuild" :"*" + "electron-prebuilt": "^1.3.4", + "electron-rebuild" :"^1.2.1" }, "author": "Carlo Maria Curinga", "license": "Apache-2.0", "bugs": { - "url": "https://github.com/fwrgit/resin-electronjs/issues" + "url": "https://github.com/resin-io/resin-electronjs/issues" }, - "homepage": "https://github.com/fwrgit/resin-electronjs#readme", + "homepage": "https://github.com/resin-io/resin-electronjs#readme", "jshintConfig": { "esnext": true, "strict": true diff --git a/start.sh b/app/start.sh similarity index 69% rename from start.sh rename to app/start.sh index 5f2669f..28e84b9 100644 --- a/start.sh +++ b/app/start.sh @@ -6,6 +6,6 @@ # it saves you a LOT of resources avoiding full-desktops envs while true; do - rm /tmp/.X0-lock || true - startx /app/node_modules/electron-prebuilt/dist/electron /app --enable-logging + rm /tmp/.X0-lock >/dev/null 2>&1 || true + startx /usr/src/app/node_modules/electron-prebuilt/dist/electron /usr/src/app --enable-logging done diff --git a/main.js b/main.js deleted file mode 100644 index 704697b..0000000 --- a/main.js +++ /dev/null @@ -1,69 +0,0 @@ -(function() { - 'use strict'; - // since we control the whole environment, we can safely use ES6 syntax: - const electron = require('electron'); - const app = electron.app; - const BrowserWindow = electron.BrowserWindow; - - // simple parameters initialization - let window = null; - let resin_toolbar = false; - let resin_kiosk = false; - let resin_node = true; - - - // enable touch events if your device supports them - if (process.env.URL_LAUNCHER_TOUCH && process.env.URL_LAUNCHER_TOUCH === "true") { - app.commandLine.appendSwitch("--touch-devices"); - } - // simulate touch events - might be useful for touchscreen with partial driver support - if (process.env.URL_LAUNCHER_TOUCH_SIMULATE && process.env.URL_LAUNCHER_TOUCH_SIMULATE === "true") { - app.commandLine.appendSwitch("--simulate-touch-screen-with-mouse"); - } - - /* - we initialize our application display as a callback of the electronJS "ready" event - */ - app.on('ready', function() { - - if (process.env.URL_LAUNCHER_FRAME && process.env.URL_LAUNCHER_FRAME === "false") { - resin_toolbar = false; - } - if (process.env.URL_LAUNCHER_KIOSK && process.env.URL_LAUNCHER_KIOSK === "true") { - resin_kiosk = true; - } - if (process.env.URL_LAUNCHER_NODE && process.env.URL_LAUNCHER_NODE === "false") { - resin_node = false; - } - - // here we actually configure the behavour of electronJS - window = new BrowserWindow({ - width: parseInt(process.env.URL_LAUNCHER_WIDTH || 1920), - height: parseInt(process.env.URL_LAUNCHER_HEIGHT || 1080), - frame: resin_toolbar, - title: process.env.URL_LAUNCHER_TITLE || "RESIN.IO", - kiosk: resin_kiosk, - webPreferences: { - nodeIntegration: resin_node - } - }); - - window.webContents.on('did-finish-load', function() { - // The flash of white is still present for a very short - // while after the WebView reports it finished loading - // taken from etcher - https://goo.gl/n5X0gY ) - setTimeout(function() { - window.show(); - }, 100); - - }); - - // if the env-var is set to true, a portion of the screen will be dedicated to the chrome-dev-tools - if (process.env.URL_LAUNCHER_CONSOLE && process.env.URL_LAUNCHER_CONSOLE === "true") { - window.openDevTools(); - } - - // the big red button, here we go - window.loadURL(process.env.URL_LAUNCHER_URL || "file:///app/app/index.html"); - }); -})();