Unleash your web skills on native!

A presentation at Frontend Connect in November 2019 in Warsaw, Poland by Rowdy Rabouw

Slide 1

Slide 1

FrontendCon 2019 - @rowdyrabouw

Slide 2

Slide 2

Czy miałeś miły lunch?

Slide 3

Slide 3

Unleash your web skills on native!

Slide 4

Slide 4

Slide 5

Slide 5

Web developer mood coaster

Slide 6

Slide 6

web developer in natural habitat

Slide 7

Slide 7

Slide 8

Slide 8

web developer • HTML • CSS • JavaScript • Sass • Node Package Manager #FrontendCon 2019 - @rowdyrabouw 8/157

Slide 9

Slide 9

web developer on native iOS / Android

Slide 10

Slide 10

Slide 11

Slide 11

web developer & native • App stores • Provisioning files • Java or Kotlin for Android • Objective-C or Swift for iOS #FrontendCon 2019 - @rowdyrabouw 11/157

Slide 12

Slide 12

web developer with nativescript

Slide 13

Slide 13

Slide 14

Slide 14

web developer & nativescript • App stores • Provisioning files • NativeScript • HTML, CSS, JavaScript • Sass • Node Package Manager #FrontendCon 2019 - @rowdyrabouw 14/157

Slide 15

Slide 15

web developer ❤ nativescript

Slide 16

Slide 16

Slide 17

Slide 17

who?

Slide 18

Slide 18

Rowdy Rabouw » @rowdyrabouw » Gouda, The Netherlands » Freelance web and app developer » Lead developer Nationale-Nederlanden Pension App » Progress Developer Expert for Nativescript » I ❤ superhero movies #FrontendCon 2019 - @rowdyrabouw 18/157

Slide 19

Slide 19

Slide 20

Slide 20

Slide 21

Slide 21

Slide 22

Slide 22

Mobile App framework decision guide

Slide 23

Slide 23

Mobile App framework decision guide Do you want/need a native User Interface and native performance? No #FrontendCon 2019 - @rowdyrabouw Yes 23/157

Slide 24

Slide 24

Mobile App framework decision guide Do you want/need a native User Interface and native performance? No Yes Phonegap / Cordova with Ionic • WebView • DOM to manipulate • HTML styled like native #FrontendCon 2019 - @rowdyrabouw 24/157

Slide 25

Slide 25

Mobile App framework decision guide Do you want/need a native User Interface and native performance? No Phonegap / Cordova with Ionic Yes continue • WebView • DOM to manipulate • HTML styled like native #FrontendCon 2019 - @rowdyrabouw 25/157

Slide 26

Slide 26

Mobile App framework decision guide Do you have too much money and time? Yes #FrontendCon 2019 - @rowdyrabouw No 26/157

Slide 27

Slide 27

Mobile App framework decision guide Do you have too much money and time? Yes No Native iOS and Android • Twice the work #FrontendCon 2019 - @rowdyrabouw 27/157

Slide 28

Slide 28

Mobile App framework decision guide Do you have too much money and time? Yes Native iOS and Android No continue • Twice the work #FrontendCon 2019 - @rowdyrabouw 28/157

Slide 29

Slide 29

Mobile App framework decision guide Do you potentially want/need to share code with the web? Or do you want/need to use web technologies? No #FrontendCon 2019 - @rowdyrabouw Yes 29/157

Slide 30

Slide 30

Mobile App framework decision guide Do you potentially want/need to share code with the web? Or do you want/need to use web technologies? No Yes Xamarin • .NET or C# • Cross compiling • Bindings to access native APIs #FrontendCon 2019 - @rowdyrabouw 30/157

Slide 31

Slide 31

Mobile App framework decision guide Do you potentially want/need to share code with the web? Or do you want/need to use web technologies? No Yes Flutter • Dart • Cross compiling #FrontendCon 2019 - @rowdyrabouw 31/157

Slide 32

Slide 32

Mobile App framework decision guide Do you potentially want/need to share code with the web? Or do you want/need to use web technologies? No Flutter Yes continue • Dart • Cross compiling #FrontendCon 2019 - @rowdyrabouw 32/157

Slide 33

Slide 33

Mobile App framework decision guide Do you want to use modern JavaScript? No #FrontendCon 2019 - @rowdyrabouw Yes 33/157

Slide 34

Slide 34

Mobile App framework decision guide Do you want to use modern JavaScript? No Yes Titanium • No ES6/ES2015 support • Can’t use NPM • Old MVC framework (Alloy) #FrontendCon 2019 - @rowdyrabouw 34/157

Slide 35

Slide 35

Mobile App framework decision guide Do you want to use modern JavaScript? No Titanium Yes continue • No ES6/ES2015 support • Can’t use NPM • Old MVC framework (Alloy) #FrontendCon 2019 - @rowdyrabouw 35/157

Slide 36

Slide 36

Mobile App framework decision guide Do you know and like React? Yes #FrontendCon 2019 - @rowdyrabouw No 36/157

Slide 37

Slide 37

Mobile App framework decision guide Do you know and like React? Yes No React Native • React • Bridge to access native APIs #FrontendCon 2019 - @rowdyrabouw 37/157

Slide 38

Slide 38

Mobile App framework decision guide Do you know and like React? Yes No React Native • React • Bridge to access native APIs • Hold my beer! #FrontendCon 2019 - @rowdyrabouw 38/157

Slide 39

Slide 39

Mobile App framework decision guide Do you know and like React? Yes React Native No continue • React • Bridge to access native APIs • Hold my beer! #FrontendCon 2019 - @rowdyrabouw 39/157

Slide 40

Slide 40

Slide 41

Slide 41

NATIVESCRIPT

Slide 42

Slide 42

NATIVESCRIPT

Slide 43

Slide 43

What is NativeScript? • Open source framework for building truly native mobile apps • JavaScript, markup (XML/HTML) and CSS • Native code inside your JavaScript if you want and dare • Cross Platform: one codebase for iOS and Android • Backed by software company Progress • Android 4.2 or a later stable official release • iOS 9.0 or later stable official release #FrontendCon 2019 - @rowdyrabouw 43/157

Slide 44

Slide 44

docs.nativescript.org

Slide 45

Slide 45

nativescript.org/get-the-nativescript-book

Slide 46

Slide 46

nativescripting.com

Slide 47

Slide 47

nativescriptcommunity.slack.com

Slide 48

Slide 48

nativescript.org/nativescript-sidekick

Slide 49

Slide 49

play.nativescript.org

Slide 50

Slide 50

Slide 51

Slide 51

markup like on the web

Slide 52

Slide 52

Markup http://2xr.nl/markup https://docs.nativescript.org/ui/components <ActionBar title=”Native elements”/> <StackLayout> <Button text=”Button” tap=”{{ onButtonTap }}”/> <Switch checked=”false”/> <SegmentedBar items=”{{ segmentedBarItems }}”/> <Progress value=”0” maxValue=”100”/> <Slider value=”0” minValue=”0” maxValue=”100”/> <DatePicker year=”2018” month=”1” day=”1” minDate=”1970-01-01” maxDate=”2100-12-31”/> </StackLayout> #FrontendCon 2019 - @rowdyrabouw 52/157

Slide 53

Slide 53

Slide 54

Slide 54

TextField https://docs.nativescript.org/api-reference/modules/ui_text_field.textfield <TextField/> <TextField text=”“/> <TextField hint=”Enter your name”/> #FrontendCon 2019 - @rowdyrabouw 54/157

Slide 55

Slide 55

TextField: autocapitalization https://docs.nativescript.org/api-reference/modules/ui_text_field.textfield <TextField autocapitalizationType=”allCharacters”/> <TextField autocapitalizationType=”sentences”/> <TextField autocapitalizationType=”words”/> #FrontendCon 2019 - @rowdyrabouw 55/157

Slide 56

Slide 56

TextField: autocapitalization https://docs.nativescript.org/api-reference/modules/ui_text_field.textfield <TextField autocapitalizationType=”allCharacters”/> <TextField autocapitalizationType=”sentences”/> <TextField autocapitalizationType=”words”/> <TextField autocapitalizationType=”none”/> #FrontendCon 2019 - @rowdyrabouw 56/157

Slide 57

Slide 57

TextField: autocorrect https://docs.nativescript.org/api-reference/modules/ui_text_field.textfield <TextField autocorrect=”true”/> <TextField autocorrect=”false”/> #FrontendCon 2019 - @rowdyrabouw 57/157

Slide 58

Slide 58

TextField: keyboardType http://2xr.nl/keyboardType https://docs.nativescript.org/api-reference/modules/ui_enums.keyboardtype <TextField keyboardType=”number”/> <TextField keyboardType=”datetime”/> <TextField keyboardType=”phone”/> <TextField keyboardType=”email”/> <TextField keyboardType=”url”/> #FrontendCon 2019 - @rowdyrabouw 58/157

Slide 59

Slide 59

Slide 60

Slide 60

TextField: more attributes https://docs.nativescript.org/api-reference/modules/ui_text_field.textfield <TextField textAlignment=”“/> <TextField visibility=”“/> <TextField width=”“/> <TextField maxLength=”“/> #FrontendCon 2019 - @rowdyrabouw 60/157

Slide 61

Slide 61

Layouts https://docs.nativescript.org/ui/layouts #FrontendCon 2019 - @rowdyrabouw 61/157

Slide 62

Slide 62

Layouts https://docs.nativescript.org/ui/layouts #FrontendCon 2019 - @rowdyrabouw 62/157

Slide 63

Slide 63

DockLayout https://docs.nativescript.org/ui/layouts <DockLayout height=”100%” stretchLastChild=”true”> <Label <Label <Label <Label text=”1” text=”2” text=”3” text=”4” dock=”top”/> dock=”bottom”/> dock=”right”/> dock=”left”/> </DockLayout> <!-1 + 2 have fixed height 3 has fixed width 4 will get all remaining space —> #FrontendCon 2019 - @rowdyrabouw 63/157

Slide 64

Slide 64

GridLayout https://docs.nativescript.org/ui/layouts <GridLayout rows=”100, auto, *” columns=”100, auto, *”> <Label text=”1” row=”0” <Label text=”2” row=”0” colSpan=”2”/> <Label text=”3” row=”1” rowSpan=”2”/> <Label text=”4” row=”1” <Label text=”5” row=”1” <Label text=”6” row=”2” <Label text=”7” row=”2” </GridLayout> #FrontendCon 2019 - @rowdyrabouw col=”0”> col=”1” col=”0” col=”1”/> col=”2”/> col=”1”/> col=”2”/> 64/157

Slide 65

Slide 65

Slide 66

Slide 66

Cascading Style Sheets

Slide 67

Slide 67

Cascading Style Sheets https://docs.nativescript.org/ui/styling • a large subset of CSS properties is supported • device-independent pixels • application-wide, page-specific or inline • platform-specific possible • animations • SASS #FrontendCon 2019 - @rowdyrabouw 67/157

Slide 68

Slide 68

{N} Core Themes https://docs.nativescript.org/ui/theme • ready to use color schemes • tailored for iOS and Android #FrontendCon 2019 - @rowdyrabouw

Slide 69

Slide 69

NativeScript Theme Builder https://www.nativescriptthemebuilder.com #FrontendCon 2019 - @rowdyrabouw 69/157

Slide 70

Slide 70

TabView <TabView height=”100%”> <StackLayout *tabItem=”{title: ‘Rocket Raccoon’}” class=”full rocket”/> <StackLayout *tabItem=”{title: ‘Harley Quinn’}” class=”full harley”/> <StackLayout *tabItem=”{title: ‘Hulk’}” class=”full hulk”/> </TabView> #FrontendCon 2019 - @rowdyrabouw 70/157

Slide 71

Slide 71

TabView .full { background-size: cover; background-position: center; background-repeat: no-repeat; } .rocket { background-image: url(“~/images/rocket-raccoon.jpg”); } .harley { background-image: url(“~/images/harley-quinn.jpg”); } .hulk { background-image: url(“~/images/hulk.jpg”); } #FrontendCon 2019 - @rowdyrabouw 71/157

Slide 72

Slide 72

Slide 73

Slide 73

Slide 74

Slide 74

4 Fantastic Choices

Slide 75

Slide 75

Slide 76

Slide 76

6 Big Heroes

Slide 77

Slide 77

JavaScript

Slide 78

Slide 78

TypeScript

Slide 79

Slide 79

Angular

Slide 80

Slide 80

Vue.js Igor Randjelovic (NativeScript-Vue)

Slide 81

Slide 81

Svelte David Pershouse (Svelte Native)

Slide 82

Slide 82

React Jamie Birch (React NativeScript)

Slide 83

Slide 83

Slide 84

Slide 84

Native Code Objective-C

Slide 85

Slide 85

{N} Angular directory structure app/components/slider/ slider.component.html slider.component.css slider.component.ts slider-routing.module.ts slider-module.ts #FrontendCon 2019 - @rowdyrabouw 85/157

Slide 86

Slide 86

slider.component.html <ActionBar> <NavigationButton visibility=”collapsed”></NavigationButton> </ActionBar> <StackLayout> <Slider></Slider> </StackLayout> #FrontendCon 2019 - @rowdyrabouw 86/157

Slide 87

Slide 87

slider.component.css ActionBar { background-color: #FFFFFF; } StackLayout { padding: 50; } #FrontendCon 2019 - @rowdyrabouw 87/157

Slide 88

Slide 88

slider.component.ts import { Component } from “@angular/core”; @Component({ selector: “app-slider”, moduleId: module.id, templateUrl: “slider.component.html”, styleUrls: [“slider.component.css”] }) export class SliderComponent { constructor() {} } #FrontendCon 2019 - @rowdyrabouw 88/157

Slide 89

Slide 89

slider-routing.module.ts import { NgModule } from “@angular/core”; import { Routes } from “@angular/router”; import { NativeScriptRouterModule } from “nativescript-angular/router”; import { SliderComponent } from “./slider.component”; const routes: Routes = [{ path: “”, component: SliderComponent }]; @NgModule({ imports: [NativeScriptRouterModule.forChild(routes)], exports: [NativeScriptRouterModule] }) export class SliderRoutingModule {} #FrontendCon 2019 - @rowdyrabouw 89/157

Slide 90

Slide 90

slider.module.ts import { NgModule, NO_ERRORS_SCHEMA } from “@angular/core”; import { NativeScriptModule } from “nativescript-angular/nativescript.module”; import { SliderRoutingModule } from “./slider-routing.module”; import { SliderComponent } from “./slider.component”; @NgModule({ imports: [NativeScriptModule, SliderRoutingModule], declarations: [SliderComponent], schemas: [NO_ERRORS_SCHEMA] }) export class SliderModule {} #FrontendCon 2019 - @rowdyrabouw 90/157

Slide 91

Slide 91

#FrontendCon 2019 - @rowdyrabouw 91/157

Slide 92

Slide 92

slider.component.html <ActionBar> <NavigationButton visibility=”collapsed”></NavigationButton> </ActionBar> <StackLayout> <Slider slider-icon></Slider> </StackLayout> • attribute directive • changes the appearance or behavior of an element #FrontendCon 2019 - @rowdyrabouw 92/157

Slide 93

Slide 93

slider.directive.ts import { Directive, ElementRef } from “@angular/core”; import { isIOS } from “platform”; @Directive({ selector: “[slider-icon]” }) export class SliderIconDirective { constructor(private el: ElementRef) { if (isIOS) { const uiSlider = this.el.nativeElement.ios; uiSlider.setThumbImageForState( UIImage.imageNamed(“image.png”), UIControlState.Normal); } } } #FrontendCon 2019 - @rowdyrabouw 93/157

Slide 94

Slide 94

slider.directive.ts import { Directive, ElementRef } from “@angular/core”; import { isIOS } from “platform”; @Directive({ selector: “[slider-icon]” }) export class SliderIconDirective { constructor(private el: ElementRef) { if (isIOS) { const uiSlider = this.el.nativeElement.ios; uiSlider.setThumbImageForState( UIImage.imageNamed(“image.png”), UIControlState.Normal); } } } #FrontendCon 2019 - @rowdyrabouw 94/157

Slide 95

Slide 95

slider.directive.ts import { Directive, ElementRef } from “@angular/core”; import { isIOS } from “platform”; @Directive({ selector: “[slider-icon]” }) export class SliderIconDirective { constructor(private el: ElementRef) { if (isIOS) { const uiSlider = this.el.nativeElement.ios; uiSlider.setThumbImageForState( UIImage.imageNamed(“image.png”), UIControlState.Normal); } } } #FrontendCon 2019 - @rowdyrabouw 95/157

Slide 96

Slide 96

slider.module.ts import { NgModule, NO_ERRORS_SCHEMA } from “@angular/core”; import { NativeScriptModule } from “nativescript-angular/nativescript.module”; import { SliderIconDirective } from “./slider.directive”; import { SliderRoutingModule } from “./slider-routing.module”; import { SliderComponent } from “./slider.component”; @NgModule({ imports: [NativeScriptModule, SliderRoutingModule], declarations: [SliderComponent, SliderIconDirective], schemas: [NO_ERRORS_SCHEMA] }) export class SliderModule {} #FrontendCon 2019 - @rowdyrabouw 96/157

Slide 97

Slide 97

#FrontendCon 2019 - @rowdyrabouw 97/157

Slide 98

Slide 98

slider.component.html <ActionBar> <NavigationButton visibility=”collapsed”></NavigationButton> </ActionBar> <StackLayout> <AbsoluteLayout> <StackLayout #background class=”captain” top=”0” left=”0”></StackLayout> <FlexboxLayout class=”flexcontainer” top=”0” left=”0”> <Slider slider-icon (valueChange)=”onSliderChange($event)”></Slider> </FlexboxLayout> </AbsoluteLayout> </StackLayout> #FrontendCon 2019 - @rowdyrabouw 98/157

Slide 99

Slide 99

slider.component.css .captain { background-image: url(“~/assets/images/captain-america.jpg”); background-repeat: no-repeat; background-position: center; background-size: cover; height: 100%; width: 100%; opacity: 0; } #FrontendCon 2019 - @rowdyrabouw 99/157

Slide 100

Slide 100

slider.component.css .flexcontainer { justify-content: center; align-items: center; height: 100%; width: 100%; } Slider { width: 80%; background-color: #BC1A0F; } #FrontendCon 2019 - @rowdyrabouw 100/157

Slide 101

Slide 101

slider.component.ts import import import import import { { { { { Component, OnInit, ViewChild, ElementRef } from “@angular/core”; Page } from “ui/page”; Slider } from “ui/slider”; StackLayout } from “ui/layouts/stack-layout”; TNSPlayer } from “nativescript-audio”; @Component({ selector: “app-slider”, moduleId: module.id, templateUrl: “slider.component.html”, styleUrls: [“slider.component.css”] }) #FrontendCon 2019 - @rowdyrabouw 101/157

Slide 102

Slide 102

slider.component.ts export class SliderComponent implements OnInit { @ViewChild(“background”) background: ElementRef; private viewStack: StackLayout; private player: TNSPlayer; constructor(private page: Page) {} ngOnInit() { this.page.actionBarHidden = true; this.viewStack = this.background.nativeElement; this.player = new TNSPlayer(); this.player.initFromFile({ audioFile: “~/assets/audio/captain.mp3”, loop: false }); } #FrontendCon 2019 - @rowdyrabouw 102/157

Slide 103

Slide 103

slider.component.ts onSliderValueChange(args) { let slider = <Slider>args.object; // opacity and volume range is 0 - 1 let sliderValue = slider.value / 100; this.viewStack.opacity = sliderValue; if (Math.round(slider.value) > 0) { this.player.play(); this.player.volume = sliderValue; } else { this.player.seekTo(0); this.player.pause(); } } } #FrontendCon 2019 - @rowdyrabouw 103/157

Slide 104

Slide 104

Slide 105

Slide 105

Packages & Libraries

Slide 106

Slide 106

Node Package Manager • commonly known as npm • ready to use JavaScript modules • about 650.000 packages of free, reusable code #FrontendCon 2019 - @rowdyrabouw 106/157

Slide 107

Slide 107

Android Arsenal • libraries for Android (Java / Kotlin) Cocoapods • libraries for iOS (Objective-C / Swift) #FrontendCon 2019 - @rowdyrabouw 107/157

Slide 108

Slide 108

Slide 109

Slide 109

ngx-translate

Slide 110

Slide 110

Multilingual: ngx-translate • internationalization library for Angular 2+ • define translations in different languages • switch between them easily • no hardcoded text/labels, all in one place • start directly, even with one language #FrontendCon 2019 - @rowdyrabouw 110/157

Slide 111

Slide 111

#FrontendCon 2019 - @rowdyrabouw 111/157

Slide 112

Slide 112

Multilingual: ngx-translate { “CHART”: { “BUTTONS”: { “SALARY”: “Salaris / inkomen”, “PENSIONS”: “Pensioenen”, “CHOICES”: “Keuzes voor later”, }, }, } #FrontendCon 2019 - @rowdyrabouw 112/157

Slide 113

Slide 113

Multilingual: ngx-translate { “CHART”: { “BUTTONS”: { “SALARY”: “Salary / income”, “PENSIONS”: “Pensions”, “CHOICES”: “Choices for later”, }, }, } #FrontendCon 2019 - @rowdyrabouw 113/157

Slide 114

Slide 114

Multilingual: ngx-translate <Button [text]=“‘CHART.BUTTONS.SALARY’ | translate” ></Button> <Button [text]=“‘CHART.BUTTONS.PENSIONS’ | translate”></Button> <Button [text]=“‘CHART.BUTTONS.CHOICES’ | translate”></Button> [] = one way data binding in Angular | = display-value transformations #FrontendCon 2019 - @rowdyrabouw 114/157

Slide 115

Slide 115

Slide 116

Slide 116

NativeScript Plugins

Slide 117

Slide 117

What are {N} plugins? When the NativeScript core modules do not provide the native device or platform capability that you need, you can use plugins. • usually for both iOS and Android • JavaScript interface to native platform code #FrontendCon 2019 - @rowdyrabouw 117/157

Slide 118

Slide 118

version-number plugin

Slide 119

Slide 119

version-number plugin » version-number.d.ts » version-number.ios.ts » version-number.android.ts » package.json #FrontendCon 2019 - @rowdyrabouw 119/157

Slide 120

Slide 120

version-number.d.ts export declare class VersionNumber { constructor(); getVersion(): string; } #FrontendCon 2019 - @rowdyrabouw 120/157

Slide 121

Slide 121

version-number.ios.ts declare let NSBundle: any; export class VersionNumber { constructor() {} getVersion(): string { let version = NSBundle.mainBundle.objectForInfoDictionaryKey( “CFBundleShortVersionString” ); return version; } } #FrontendCon 2019 - @rowdyrabouw 121/157

Slide 122

Slide 122

version-number.ios.ts declare let NSBundle: any; export class VersionNumber { constructor() {} getVersion(): string { let version = NSBundle.mainBundle.objectForInfoDictionaryKey( “CFBundleShortVersionString” ); return version; } } #FrontendCon 2019 - @rowdyrabouw 122/157

Slide 123

Slide 123

NSBundle NSView, NSStackView, NSButton, NSImageView, NSSwitch, NSMenu, NSStatusBar, NSPanel, NSWindowTab, NSAlert, NSColorPicker, NSAnimationEffect, NSSpeechRecognizer, NSHapticFeedbackPerformer, … #FrontendCon 2019 - @rowdyrabouw 123/157

Slide 124

Slide 124

NeXTSTEP side step

Slide 125

Slide 125

Slide 126

Slide 126

Slide 127

Slide 127

Slide 128

Slide 128

Slide 129

Slide 129

Slide 130

Slide 130

version-number.android.ts import * as application from “tns-core-modules/application”; declare let android: any; declare let java: any; export class VersionNumber { constructor() {} getVersion(): string { let PackageManager = android.content.pm.PackageManager; let pkg = application.android.context .getPackageManager() .getPackageInfo( application.android.context.getPackageName(), PackageManager.GET_META_DATA ); return java.lang.Integer.toString(pkg.versionCode); } } #FrontendCon 2019 - @rowdyrabouw 130/157

Slide 131

Slide 131

version-number.android.ts import * as application from “tns-core-modules/application”; declare let android: any; declare let java: any; export class VersionNumber { constructor() {} getVersion(): string { let PackageManager = android.content.pm.PackageManager; let pkg = application.android.context .getPackageManager() .getPackageInfo( application.android.context.getPackageName(), PackageManager.GET_META_DATA ); return java.lang.Integer.toString(pkg.versionCode); } } #FrontendCon 2019 - @rowdyrabouw 131/157

Slide 132

Slide 132

AndroidManifest.xml <?xml version=”1.0” encoding=”utf-8”?> <manifest xmlns:android=”http://schemas.android.com/apk/res/android” android:versionCode=”2”> …. </manifest> #FrontendCon 2019 - @rowdyrabouw 132/157

Slide 133

Slide 133

package.json { “name”: “nativescript-version-number”, “version”: “1.0.0”, “main”: “version-number”, “typings”: “version-number.d.ts”, “nativescript”: { “platforms”: { “android”: “6.0.0”, “ios”: “6.0.1” } } …. } #FrontendCon 2019 - @rowdyrabouw 133/157

Slide 134

Slide 134

Install # install from NPM tns plugin add nativescript-version-number # install from local tns plugin add ../nativescript-version-number #FrontendCon 2019 - @rowdyrabouw 134/157

Slide 135

Slide 135

usage import { VersionNumber } from “nativescript-version-number”; const version = new VersionNumber().getVersion(); #FrontendCon 2019 - @rowdyrabouw 135/157

Slide 136

Slide 136

Slide 137

Slide 137

PLUGIN BOILERPLATE

Slide 138

Slide 138

Slide 139

Slide 139

Slide 140

Slide 140

Nativescript Marketplace #FrontendCon 2019 - @rowdyrabouw 140/157

Slide 141

Slide 141

Nativescript Marketplace #FrontendCon 2019 - @rowdyrabouw 141/157

Slide 142

Slide 142

Nativescript Marketplace #FrontendCon 2019 - @rowdyrabouw 142/157

Slide 143

Slide 143

{N} Plugins demo

Slide 144

Slide 144

#FrontendCon 2019 - @rowdyrabouw 144/157

Slide 145

Slide 145

#FrontendCon 2019 - @rowdyrabouw 145/157

Slide 146

Slide 146

#FrontendCon 2019 - @rowdyrabouw 146/157

Slide 147

Slide 147

Philips Hue 147/157

Slide 148

Slide 148

#FrontendCon 2019 - @rowdyrabouw 148/157

Slide 149

Slide 149

#FrontendCon 2019 - @rowdyrabouw 149/157

Slide 150

Slide 150

nativescript-bluetooth import * as bluetooth from “nativescript-bluetooth”; bluetooth.startScanning({ seconds: 4, onDiscovered: peripheral => { if (peripheral.UUID == “CA9F644C-1920-4572-8833-1D137A6T2A05”) { bluetooth.connect({ UUID: peripheral.UUID, onConnected: peripheral => { bluetooth.stopScanning(); // do stuff } }); } } }); #FrontendCon 2019 - @rowdyrabouw 150/157

Slide 151

Slide 151

nativescript-accelerometer import { startAccelerometerUpdates } from “nativescript-accelerometer”; startAccelerometerUpdates(data => { // lean left (0 to -1) / right (0 to 1) let leftOrRight = data.x; // lean forward (0 to -1) / back (0 to 1) let forwardOrBack = data.y; // do stuff }); #FrontendCon 2019 - @rowdyrabouw 151/157

Slide 152

Slide 152

github.com EddyVerbruggen nativescript-pluginshowcase

Slide 153

Slide 153

#FrontendCon 2019 - @rowdyrabouw 153/157

Slide 154

Slide 154

Slide 155

Slide 155

2xr.nl/fc2019 #FrontendCon 2019 - @rowdyrabouw

Slide 156

Slide 156

Dziękuję bardzo! #FrontendCon 2019 - @rowdyrabouw

Slide 157

Slide 157

#FrontendCon 2019 - @rowdyrabouw