Ionic 2 local storage read issue when build with '--prod' - android

I am building an app that does an auto login for the user when app starts if it was closed without logging out the last time. This is done by setting a local storage value at successful login and reading it in the constructor of the landing page, which is the login page.
I used ionic build android -release to build and app worked fine. But it takes about 10 sec to load. After some search, I found building the app with --prod can reduce the load time and it did reduce my app load time to 4 sec.
But now the app can't read local storage value at the start. No errors., but, it just returns the value as null. In other pages the app can read the local storage though. Looks like some needed components are not fully loaded, when the app reaches the landing page. But, by the time user logins manually those are loaded. How do I implement an auto login while reducing the load time?
import { Component } from '#angular/core';
import { NavController, MenuController, NavParams } from 'ionic-angular';
import { AuthService } from '../../providers/auth-service';
import { Global } from '../../providers/global';
import { HomePage } from '../home/home';
import { Storage } from '#ionic/storage';
import { Network } from 'ionic-native';
#Component({
selector: 'page-login',
templateUrl: 'login.html'
})
export class LoginPage {
loginUserID: string = '';
loginUserPass: string = '';
showLogin = false;
constructor(private menu: MenuController, private navCtrl: NavController, private auth: AuthService, private global: Global, private storage: Storage, private navParams: NavParams) {
this.storage.get('user_id').then((value) => {
if(this.navParams.get('showLogin')){
this.showLogin = true;
}
else{
if(value && value != null){
this.navCtrl.setRoot(HomePage);
}
else{
this.showLogin = true;
}
}
});
if(this.global.hardwareBackAction != null){
this.global.hardwareBackAction();
}
}
ionViewDidLoad() {
this.menu.swipeEnable(false, 'side-menu');
}
public login() {
if (Network.type == 'none') {
this.global.showAlert('Information', 'No internet access');
}
else {
this.global.showLoading();
this.auth.login(this.loginUserID, this.loginUserPass).subscribe(allowed => {
this.global.loading.dismiss();
if (allowed) {
setTimeout(() => {
this.storage.set('user_id', this.loginUserID);
this.navCtrl.setRoot(HomePage);
});
}
},
error => {
this.showError(error);
});
}
}
showError(text) {
setTimeout(() => {
this.global.loading.dismiss();
});
this.global.showAlert('Error', text);
}
}

Related

How to conditionally set root page in ionic 4?

I'm working on ionic 4 application. when the user signs In, I added a checkbox to asks for Remember me, so the next time the user open the app it doesn't show the login page and directly forward the user to Home page. I have google and found this. However, while using the accepted solution, I encountered an issue, which it shows the login page for 2 or 3 seconds, then open the Home page. How I can safely achieve it without delay?
app.component.ts
import { SmsVerificationService } from 'src/app/services/SMS/sms-verification.service';
import { Component } from '#angular/core';
import { Platform } from '#ionic/angular';
import { SplashScreen } from '#ionic-native/splash-screen/ngx';
import { StatusBar } from '#ionic-native/status-bar/ngx';
import { FCM } from '#ionic-native/fcm/ngx';
import { Plugins, Capacitor } from '#capacitor/core';
import { Router } from '#angular/router';
import { Storage } from '#ionic/storage';
#Component({
selector: 'app-root',
templateUrl: 'app.component.html'
})
export class AppComponent {
constructor(
private platform: Platform,
private splashScreen: SplashScreen,
private statusBar: StatusBar,
private fcm: FCM,
private route: Router,
private storage: Storage
) {
this.initializeApp();
}
initializeApp() {
this.platform.ready().then(() => {
this.fcm.getToken().then(token => {
console.log(' token is ', token);
});
this.fcm.onTokenRefresh().subscribe(token => {
console.log('on token refresh ', token);
});
this.fcm.onNotification().subscribe(data => {
console.log(data);
if (data.wasTapped) {
console.log('Received in background');
// this.router.navigate([data.landing_page, data.price]);
} else {
console.log('Received in foreground');
// this.router.navigate([data.landing_page, data.price]);
}
});
this.storage.get('isLogined').then(data => {
if (data)
this.route.navigateByUrl('/main-tab');
})
this.statusBar.styleDefault();
this.splashScreen.hide();
if (Capacitor.isPluginAvailable('SplashScreen')) {
Plugins.SplashScreen.hide();
}
});
}
}
The codes that are supposed to change the page
this.storage.get('isLogined').then(data => {
if (data)
this.route.navigateByUrl('/main-tab');
})
Do you have a separate login component? If so, you can create and add a guard to your login component to navigate to your main page when Remember me was checked.

Where does my image been stored in Ionic application?

I am very new to Ionic and Cordova, for the last couple of days I am trying to download an image that I have upload in firebase storage. I want to transfer the image and store it in my mobile device through my mobile application. I have installed all the plugins needed to do that. I have created two buttons. The first button is to display the image in my application and the second button is to download the image in my device. The source code for that is in my storage.html
<ion-header>
<ion-navbar>
<ion-title>storage</ion-title>
</ion-navbar>
</ion-header>
<ion-content padding>
<button ion-button (click)="display()">Display</button>
<button ion-button (click)="download()">Download</button>
<img src="{{imgsource}}">
</ion-content>
The functionality is in my storage.ts
import { Component, NgZone } from '#angular/core';
import { NavController, Platform, AlertController } from 'ionic-angular';
//import {File,Transfer} from 'ionic-native';
import {FileTransferObject } from '#ionic-native/file-transfer';
import {TransferObject} from '#ionic-native/transfer';
import {Transfer} from '#ionic-native/transfer';
import {File} from '#ionic-native/file';
import firebase from 'firebase';
declare var cordova: any;
#Component({
selector: 'storage-home',
templateUrl: 'storage.html',
providers: [Transfer, TransferObject, File]
})
export class StoragePage {
storageDirectory: string = '';
fileTransfer: FileTransferObject;
nativepath: any;
firestore = firebase.storage();
imgsource: any;
constructor(public navCtrl: NavController, public platform: Platform, public alertCtrl: AlertController, public zone: NgZone) {
this.platform.ready().then(() => {
// make sure this is on a device, not an emulation (e.g. chrome tools device mode)
if(!this.platform.is('cordova')) {
return false;
}
if (this.platform.is('ios')) {
this.storageDirectory = cordova.file.documentsDirectory;
}
else if(this.platform.is('android')) {
this.storageDirectory = cordova.file.dataDirectory;
}
else {
// exit otherwise, but you could add further types here e.g. Windows
return false;
}
});
}
display() {
this.firestore.ref().child('image.jpg').getDownloadURL().then((url) => {
this.zone.run(() => {
this.imgsource = url;
this.fileTransfer.download(url,'image.jpg').then((entry) => {
console.log('download complete: ' + entry.toURL());
}, (error) => {
// handle error
});
})
})
}
downlad() {
this.firestore.ref().child('image.jpg').getDownloadURL().then((url) => {
this.zone.run(() => {
this.imgsource = url;
this.fileTransfer.download(url,cordova.file.dataDirectory +'image.jpg').then((entry) => {
console.log('download complete: ' + entry.toURL());
}, (error) => {
// handle error
});
})
})
}
}
The display button works perfectly as I can see my image when I install the application on my device. The problem though is with the download button as nothing is happening and I don’t know if it’s working as I can’t find my image anywhere in my device. Can anyone please guide me?
Thanks in regards
It looks like you may have a typo on your download function name. In the HTML module you refer to download() and in your code your function is labeled as downlad.

How to add Social share to a post Ionic wordpress app

I have been trying to insert a share button for a post in my app that is able to use the default apps installed in the android phone and can not seem to find a way through.
This is how my post.ts file looks like
import { Component } from '#angular/core';
import { NavParams, NavController, AlertController } from 'ionic-angular';
.
.
import { SocialSharing } from '#ionic-native/social-sharing';
/**
* Generated class for the PostPage page.
*/
#Component({
selector: 'page-post',
templateUrl: 'post.html'
})
export class PostPage {
post: any;
user: string;
comments: Array<any> = new Array<any>();
categories: Array<any> = new Array<any>();
morePagesAvailable: boolean = true;
constructor(
public navParams: NavParams,
public navCtrl: NavController,
public alertCtrl: AlertController,
private socialSharing: SocialSharing
) {
}
ionViewWillEnter(){
this.morePagesAvailable = true;
this.post = this.navParams.get('item');
Observable.forkJoin(
this.getAuthorData(),
this.getCategories(),
this.getComments())
.subscribe(data => {
this.user = data[0].name;
this.categories = data[1];
this.comments = data[2];
});
}
getAuthorData(){
return this.wordpressService.getAuthor(this.post.author);
}
getCategories(){
return this.wordpressService.getPostCategories(this.post);
}
getComments(){
return this.wordpressService.getComments(this.post.id);
}
loadMoreComments(infiniteScroll) {
let page = (this.comments.length/10) + 1;
this.wordpressService.getComments(this.post.id, page)
.subscribe(data => {
for(let item of data){
this.comments.push(item);
}
infiniteScroll.complete();
}, err => {
console.log(err);
this.morePagesAvailable = false;
})
}
goToCategoryPosts(categoryId, categoryTitle){
this.navCtrl.push(HomePage, {
id: categoryId,
title: categoryTitle
})
}
// Social sharing function is here
sharePost() {
this.socialSharing.share("Post Excerpt", "Post Title", "Post Image URL", "Post URL")
.then(() => {
console.log("sharePost: Success");
}).catch(() => {
console.error("sharePost: failed");
});
}
}
Problem
How do insert the post title, post url post image (REST API - JSON) into this.socialSharing.share("Post Excerpt", "Post Title", "Post Image URL", "Post URL")
so that the share button can look more like this
<button ion-fab class="btn share" mini (click)="sharePost()"></button>
EDIT
I have managed to make it work using
sharePost() {
this.socialSharing.share(this.post.excerpt.rendered, this.post.title.rendered, this.post.images.large, this.post.link)
.then(() => {
console.log("sharePost: Success");
}).catch(() => {
console.error("sharePost: failed");
});
}
However when i share like using gmail, the html special characters display
e.g title shows: catering & Cleaning Services
Excerpt shows: <p>Some text[…]</p>
How do i get rid of those html characters and just show some clean text.?
Thank you
One way i removed html tag from my wordpress post was to create a pipe and i pass the excerpt through the pipe before it gets rendered to the view
Pipe.ts was like so
import { Pipe, PipeTransform } from '#angular/core';
/**
* Generated class for the RemovehtmltagsPipe pipe.
*
* See https://angular.io/api/core/Pipe for more info on Angular Pipes.
*/
#Pipe({
name: 'RemovehtmltagsPipe',
})
export class RemovehtmltagsPipe implements PipeTransform {
/**
* Takes a value and makes it lowercase.
*/
transform(value: string) {
if (value) {
let result = value.replace(/<\/?[^>]+>/gi, "");
return result;
}
else {
}
}
}
Then i added the pipe as export in my component's module.ts
details.module.ts was like so
import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '#angular/core';
import { IonicPageModule } from 'ionic-angular';
import { DetailsPage } from './details';
import { RemovehtmltagsPipe } from
'../../pipes/removehtmltags/removehtmltags';
#NgModule({
declarations: [
DetailsPage,
],
imports: [
IonicPageModule.forChild(DetailsPage),
],
exports: [RemovehtmltagsPipe],
schemas: [CUSTOM_ELEMENTS_SCHEMA]
})
export class DetailsPageModule {}
Finally used the pipe inside my html code
details.html
<ion-row class="white-bg" padding>
<ion-col>
<h1 class="title">{{article.title.rendered | RemovehtmltagsPipe}}</h1>
<p class="date">Published: {{article.modified.split('T')[0]}} {{article.modified.split('T')[1]}}</p>
</ion-col>
</ion-row>
This should get rid of any html tags in your post.Hope this helps

How to handle hardware back button in PWA developed using Ionic3

I have developed a PWA (Tab based) using Ionic 3. It is working fine until hardware back button or browser's back button is pressed in android browser. If it is running from home screen, pressing hardware back will close app. If app is running in chrome in android (only tested in chrome), hardware back or browser's back will reload PWA's first page, not previously visited page. How to handle these events in Ionic 3 PWA?
I am using lazy load for all pages.
What I tried so far:
As per jgw96's comment here, I thought IonicPage will handle navigation itself. But it is not working.
Used platform.registerBackButtonAction, but it's not for PWA.
As per Webruster's suggestion below in Answers, tried code in app.component.ts. But no change.
Posting code:
import { Component, ViewChild } from '#angular/core';
import { Nav, Platform, AlertController, Alert, Events, App, IonicApp, MenuController } from 'ionic-angular';
#Component({
templateUrl: 'app.html'
})
export class MyApp {
#ViewChild(Nav) nav: Nav;
rootPage:any = 'TabsPage';
constructor(public platform: Platform,
public alertCtrl: AlertController, public events: Events,
public menu: MenuController,
private _app: App,
private _ionicApp: IonicApp) {
platform.ready().then(() => {
this.configureBkBtnprocess ();
});
}
configureBkBtnprocess() {
if (window.location.protocol !== "file:") {
window.onpopstate = (evt) => {
if (this.menu.isOpen()) {
this.menu.close ();
return;
}
let activePortal = this._ionicApp._loadingPortal.getActive() ||
this._ionicApp._modalPortal.getActive() ||
this._ionicApp._toastPortal.getActive() ||
this._ionicApp._overlayPortal.getActive();
if (activePortal) {
activePortal.dismiss();
return;
}
if (this._app.getRootNav().canGoBack())
this._app.getRootNav().pop();
};
this._app.viewDidEnter.subscribe((app) => {
history.pushState (null, null, "");
});
}
}
}
you have mentioned that you are working with the hardware back button on app and in browser so you didn't mention clearly what need to be done at what stage so i came up with the generalized solution which can be useful in most of the cases
app.component.ts
platform.ready().then(() => {
// your other plugins code...
this.configureBkBtnprocess ();
});
configureBkBtnprocess
private configureBkBtnprocess () {
// If you are on chrome (browser)
if (window.location.protocol !== "file:") {
// Register browser back button action and you can perform
// your own actions like as follows
window.onpopstate = (evt) => {
// Close menu if open
if (this._menu.isOpen()) {
this._menu.close ();
return;
}
// Close any active modals or overlays
let activePortal = this._ionicApp._loadingPortal.getActive() ||
this._ionicApp._modalPortal.getActive() ||
this._ionicApp._toastPortal.getActive() ||
this._ionicApp._overlayPortal.getActive();
if (activePortal) {
activePortal.dismiss();
return;
}
// Navigate back
if (this._app.getRootNav().canGoBack())
this._app.getRootNav().pop();
}
else{
// you are in the app
};
// Fake browser history on each view enter
this._app.viewDidEnter.subscribe((app) => {
history.pushState (null, null, "");
});
Solution 2
Try to Add the these event listener in the platform ready:
window.addEventListener('load', function() { window.history.pushState({}, '')
})
window.addEventListener('popstate', function() { window.history.pushState({},
'') })
I have pretty much same requirement but none of the solution completely works, so i came up with my own. here i have used an array to keep track of visited page and removes it on back click event.
Note: window.onpopstate gets called even on pushing new page
import { Platform, Nav } from "ionic-angular";
import { HomePage } from "../pages/home/home";
#Component({
templateUrl: "app.html"
})
export class MyApp {
rootPage: any;
#ViewChild(Nav) nav: Nav;
pageHistory: string[] = [];//to track page history
constructor(
platform: Platform,
statusBar: StatusBar,
splashScreen: SplashScreen
) {
window.addEventListener("load", function() {
//adding a state to prevent app exit on back
window.history.pushState({ noBackExitsApp: true }, "");
});
platform.ready().then(() => {
window.onpopstate = evt => {
let view = this.nav.getActive();
if (this.pageHistory.find(x => x === view.name)) {
if (!view.name.startsWith("Home")) {//handle a condition where you want to go back
this.pageHistory = this.pageHistory.filter(n => n !== view.name);
this.nav.pop().catch(reason => {
console.log("Unable to pop :" + reason);
});
}
} else {
window.history.pushState({ noBackExitsApp: true }, "");
this.pageHistory.push(view.name);
}
};
this.rootPage = HomePage;
statusBar.styleDefault();
splashScreen.hide();
});
}
}

Native IONIC Geolocation not working on Android devices.

I am using Ionic together with the native Geolocation plugin to retrieve user position and sort a list of position by closest to the user.
The Geolocation plugin works perfectly using ionic serve or ionic lab as well as iOS devices but it does not work on Android devices (nor simulator).
What other solution can I use to retrieve longitude and latitude of the user?
I'll attach the class where I use the Geolocation plugin here.
The Location class I access has a public static variable where I store the userLocation since will be modified in more classes.
this.Location.load just uses the user position to call a method in Location class to sort the list of places.
import { Component } from '#angular/core';
import { ModalController, NavController, NavParams } from 'ionic-angular';
import { SharePopup } from '../share-popup/share-popup';
import { InAppBrowser } from 'ionic-native';
import { CamhsPage } from '../camhs-page/camhs-page';
import { Locations } from '../../providers/locations';
import { Platform } from 'ionic-angular';
import { Geolocation } from 'ionic-native';
#Component({
selector: 'contact',
templateUrl: 'contact.html'
})
export class Contact {
userPosition = [0, 0];
constructor(public navCtrl: NavController, public navParams: NavParams,
public modalCtrl: ModalController, public locations: Locations,public platform: Platform) {
}
openCamhsPage(){
this.platform.ready().then(() => {
let options = {
timeout: 10000,
enableHighAccuracy: true
};
Geolocation.getCurrentPosition(options).then((data) => {
Locations.userPosition[0] = Math.round(data.coords.latitude * 100)/100;
Locations.userPosition[1] = Math.round(data.coords.longitude * 100)/100;
// console.log("CONTACT "+Locations.userPosition);
});
});
this.locations.load();
this.navCtrl.push(CamhsPage);
console.log("CONTACT "+Locations.userPosition);
}
//Open WebPage
openPage(url) {
new InAppBrowser(url, '_system');
}
}
Prerequisite : Check whether you have switch ON your GPS service in Android.
Also it is good to have Success and Error Callbacks to identify the actual Error. Something like below :
..........
// Success callback for get geo coordinates
var onSuccess = function (data) {
Locations.userPosition[0] = Math.round(data.coords.latitude * 100)/100;
Locations.userPosition[1] = Math.round(data.coords.longitude * 100)/100;
}
var onError = function (data) {
console.log("Not Able to get Geolocation");
}
openCamhsPage(){
this.platform.ready().then(() => {
Geolocation.getCurrentPosition(onSuccess, onError, { enableHighAccuracy: true });
this.locations.load();
this.navCtrl.push(CamhsPage);
console.log("CONTACT "+Locations.userPosition);
}
.......
.......

Categories

Resources