= Ionic =
 * https://ionicframework.com/
Ionic Framework is an open source mobile UI toolkit for building high quality, cross-platform native and web app experiences.

== Run chrome ==
{{{
"/C/Program Files (x86)/Google/Chrome/Application/chrome.exe" --disable-web-security --disable-gpu --user-data-dir="c:\TempChrome" --disable-features=SameSiteByDefaultCookies,SameSiteDefaultChecksMethodRigorously
}}}

== Example app ==
 * Requires Android SDK, node 12.16.2 and npm 6.14.5
{{{#!highlight bash
cd ~
mkdir IonicTest
npm install @ionic/cli
node_modules/.bin/ionic start IonicTest
#framework angular
#starter template tabs
#integrate capacitor N
#create free ionic account N
cd IonicTest
npm i
npm install @ionic/cli
npm install cordova
npm install cordova-res
node_modules/.bin/ionic cordova plugin add cordova-plugin-advanced-http
npm install @ionic-native/http
node_modules/.bin/ionic cordova platform add android
node_modules/.bin/ionic cordova build android
scp ./platforms/android/app/build/outputs/apk/debug/app-debug.apk userx@example.net:/home/userx/www/ionic-test.apk
node_modules/.bin/ionic cordova platform add browser
node_modules/.bin/ionic cordova build browser
node_modules/.bin/ionic serve --cordova --platform=browser
# http://localhost:8100
# no CORS
google-chrome --disable-web-security --disable-gpu --user-data-dir="/tmp"
}}}

=== app.module.ts ===
{{{
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { RouteReuseStrategy } from '@angular/router';

import { IonicModule, IonicRouteStrategy } from '@ionic/angular';
import { SplashScreen } from '@ionic-native/splash-screen/ngx';
import { StatusBar } from '@ionic-native/status-bar/ngx';

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { HTTP } from '@ionic-native/http/ngx';

@NgModule({
  declarations: [AppComponent],
  entryComponents: [],
  imports: [BrowserModule, IonicModule.forRoot(), AppRoutingModule],
  providers: [
    HTTP,
    StatusBar,
    SplashScreen,
    { provide: RouteReuseStrategy, useClass: IonicRouteStrategy }
  ],
  bootstrap: [AppComponent]
})
export class AppModule {}
}}}

=== tab1.page.ts ===
{{{
import { Component } from '@angular/core';
import { HTTP } from '@ionic-native/http/ngx';

@Component({
  selector: 'app-tab1',
  templateUrl: 'tab1.page.html',
  styleUrls: ['tab1.page.scss']
})
export class Tab1Page {
  public res;

  constructor(private http: HTTP) {}

  public ionViewDidEnter(){
    console.log("Stuff");
    this.http.get("https://labs.bitarus.allowed.org/xapps/rest/version/", {}, {})
    .then(data => {
      console.log(data.status);
      console.log(data.data); // data received by server
      this.res=data.data;
      console.log(data.headers);
    })
    .catch(error => {
      console.log(error.status);
      console.log(error.error); // error message as string
      console.log(error.headers);
    });
  }
}
}}}

=== tab1.page.html ===
{{{
<ion-header [translucent]="true">
  <ion-toolbar>
    <ion-title>
      Tab 111 {{res}}
    </ion-title>
  </ion-toolbar>
</ion-header>

<ion-content [fullscreen]="true">
  <ion-header collapse="condense">
    <ion-toolbar>
      <ion-title size="large">Tab 111</ion-title>
    </ion-toolbar>
  </ion-header>

  <app-explore-container name="Tab 111 page {{res}}"></app-explore-container>
</ion-content>
}}}

=== tab2.page.html ===
{{{
<ion-header [translucent]="true">
  <ion-toolbar>
    <ion-title>
      Sum
    </ion-title>
  </ion-toolbar>
</ion-header>
<ion-content [fullscreen]="true">
  <ion-header collapse="condense">
    <ion-toolbar>
      <ion-title size="large">Sum</ion-title>
    </ion-toolbar>
  </ion-header>
  <ion-item>
    <ion-label>Value 1</ion-label>
    <ion-input [(ngModel)]="in1"></ion-input>
  </ion-item>
  <ion-item>
     <ion-label>Value 2</ion-label>
     <ion-input [(ngModel)]="in2"></ion-input>
  </ion-item>
  <ion-button color="primary" (click)="sumValuesButtonClicked()">Sum values</ion-button>
</ion-content>
}}}


=== tab2.page.ts ===
{{{
import { Component } from '@angular/core';
import { AlertController } from '@ionic/angular';

@Component({
  selector: 'app-tab2',
  templateUrl: 'tab2.page.html',
  styleUrls: ['tab2.page.scss']
})
export class Tab2Page {
  in1:string;
  in2:string;

  constructor(public alertController: AlertController) {}

  sumValuesButtonClicked(){
    let res:Number;
    res = parseInt(this.in1) + parseInt(this.in2);
    this.presentResult(res).then(()=>{
      console.log("Done");
    });
  }

  async presentResult(res:Number) {
    const alert = await this.alertController.create({
      header: 'Sum',
      subHeader: 'Result',
      message: res.toString(),
      buttons: ['OK'],
    });

    await alert.present();
    let result = await alert.onDidDismiss();
    console.log(result); 
  }
}
}}}

== EchoPlugin ==
 * echo-plugin/src/main/java/org/allowed/bitarus/EchoPlugin.java
{{{#!highlight java
package org.allowed.bitarus;

import org.apache.cordova.CordovaPlugin;
import org.apache.cordova.CallbackContext;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.apache.cordova.CordovaWebView;
import org.apache.cordova.CordovaInterface;

public class EchoPlugin extends CordovaPlugin {
    @Override
    public void initialize(CordovaInterface cordova, CordovaWebView webView) {
        super.initialize(cordova, webView);
    }

    @Override
    public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {        
        if (action.equals("echo")) {
            String message = "Echo " + args.getString(0) + " !!!";
            this.echo(message, callbackContext);
            return true;
        }

        if (action.equals("getintentdata")) {            
            this.getintentdata(callbackContext);
            return true;
        }


        return false;
    }

    private void echo(String message, CallbackContext callbackContext) {
        if (message != null && message.length() > 0) {
            callbackContext.success(message);
        } else {
            callbackContext.error("Expected one non-empty string argument.");
        }
    }

    private void getintentdata(CallbackContext callbackContext) {
        String data = this.cordova.getActivity().getIntent().getDataString() ;      
        String action = this.cordova.getActivity().getIntent().getAction();
        String result = String.format( "{\"data\":\"%s\" , \"action\":\"%s\"}",data,action );
        callbackContext.success(result);
    }    
}
}}}