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.
Related
I have a problem testing my ionic app on my phone and android studio, when i press the hardware back button the application inmediatly exits, i've tried many solutions, but it simply won't work and won't listen to whatever i code into it.
Here is my attempt
import { Component, Renderer2, ViewChild } from '#angular/core';
import { IonRouterOutlet, Platform } from '#ionic/angular';
import { SplashScreen } from '#ionic-native/splash-screen/ngx';
import { StatusBar } from '#ionic-native/status-bar/ngx';
import { TranslateService } from '#ngx-translate/core';
import { Location } from '#angular/common';
#Component({
selector: 'app-root',
templateUrl: 'app.component.html',
styleUrls: ['app.component.scss']
})
export class AppComponent {
#ViewChild(IonRouterOutlet, {static: true}) routerOutlet: IonRouterOutlet
constructor(
private platform: Platform,
private splashScreen: SplashScreen,
private statusBar: StatusBar,
private renderer: Renderer2,
private translate: TranslateService,
private location: Location
) {
this.initializeApp();
}
initializeApp() {
this.translate.setDefaultLang( localStorage.getItem('default-language') ? localStorage.getItem('default-language') : navigator.language.slice(0, 2) )
this.platform.ready().then(() => {
this.statusBar.styleDefault();
this.splashScreen.hide();
this.backButtonEvent();
if (localStorage.getItem('color-theme')) {
this.renderer.setAttribute(document.body, 'color-theme', localStorage.getItem('color-theme'))
} else {
if(window.matchMedia && window.matchMedia('(prefers-color-scheme: light)').matches === true)
this.renderer.setAttribute(document.body, 'color-theme', 'light')
else
this.renderer.setAttribute(document.body, 'color-theme', 'dark')
}
});
}
backButtonEvent() {
this.platform.backButton.subscribeWithPriority(0, async () => {
if(!this.routerOutlet.canGoBack())
navigator["app"].exitApp()
else
this.location.back()
});
}
}
Try it this way using the #capacitor/app package:
import { App } from '#capacitor/app';
App.addListener('backButton', ({ canGoBack }) => {
if(canGoBack){
window.history.back();
} else {
App.exitApp();
}
});
I am a beginner in Ionic and I am developing an app which requires a user to sign in before he places an order.
Right now, if the user tries to place an order and he is not signed in, I need a logic where I can redirect him to the login page and on success, I can redirect him back to the order page. This would have been possible in android using start activity for the result. But how can I achieve this in Ionic?
I have a solution of opening the login page using modal and dismissing it on success but I do not want to implement that solution as of now.
Here is an example whcih open modal via login. Path and IonicPage should be adjusted before using the below code. Maybe you can get a point from the code.
home.ts
import { Component } from '#angular/core';
import { AuthProvider } from '../../providers/auth/auth.provider'
#Component({
selector: 'page-home',
templateUrl: 'home.html'
})
export class HomePage {
constructor(public authService:AuthProvider) {
}
goToOrder(){
this.authService.openModalViaLogin('OrderPage', {}, ()=>{})
}
}
login.ts
import { Component } from '#angular/core';
import { IonicPage, ViewController } from 'ionic-angular';
import { AuthProvider } from '../../providers/auth/auth.provider';
#IonicPage()
#Component({
selector: 'page-login',
templateUrl: 'login.html',
})
export class LoginPage {
constructor(public authService:AuthProvider, public viewCtrl:ViewController) {
}
login(){
this.authService.isAuthenticated = true;
this.viewCtrl.dismiss()
}
close(){
this.viewCtrl.dismiss()
}
}
auth.provider.ts
import { Injectable } from '#angular/core';
import { ModalController } from 'ionic-angular';
#Injectable()
export class AuthProvider {
public isAuthenticated:boolean = false;
constructor(public modalCtrl:ModalController) {
console.log('Hello AuthProvider Provider');
}
public openModalViaLogin(modalPage:string, params:any, callbackOnDidDismissed:Function){
if(this.isAuthenticated){
let modal = this.modalCtrl.create(modalPage,params)
modal.onDidDismiss(()=>{
callbackOnDidDismissed()
})
modal.present()
}else{
let loginModal = this.modalCtrl.create('LoginPage')
loginModal.onDidDismiss(()=>{
if(this.isAuthenticated){
let modal = this.modalCtrl.create(modalPage,params)
modal.onDidDismiss(()=>{
callbackOnDidDismissed()
})
modal.present()
}else{
console.log("failed to authenticate")
}
})
loginModal.present()
}
}
}
p.s. I think there is a more flexible way to achieve it by nav but that can be quite confusing with this short anwser.
Good evening. I am trying to handle notification click in such a way that when the user click on a notification, a specific page of my application is opened.
I am using FIREBASE COULD MESSAGING AND IONIC 3
Here is the code of the app.component.ts file in witch the code for handling notification is written :
import { Platform, Nav, ToastController } from 'ionic-angular';
import { HomePage } from '../pages/home/home';
import { Component, ViewChild } from '#angular/core';
import { FCM } from '#ionic-native/fcm';
import { Signup } from '../pages/signup/signup';
#Component({
templateUrl: 'app.html',
selector: 'Myappname',
})
export class MyApp {
#ViewChild(Nav) nv: Nav;
rootPage: any = HomePage;
constructor(public fcm: FCM, platform: Platform) {
platform.ready().then(() => {
fcm.onNotification().subscribe(data => {
if (data.wasTapped) {
this.nv.push(Signup);
} else {
console.log("Received in foreground");
}
})
});
}
}
When the nofication is received on the mobile device, if the user click on it, only the home page is displayed and he is note redirected to the signup page as specified in the code.
Any helps ?
Thanks.
I finally found the solution. as i was using firebase cloud functions to send the notification, here is the code i used to make the onNotification() work when a user click on the notification received.
exports.Hello = functions.database.ref('/users/{userId}').onCreate(event=>{
admin.messaging().sendToTopic('all', {
data:{
"key1": value1,
"key2": value2
},
notification: {
clickAction : "FCM_PLUGIN_ACTIVITY",
sound : "default",
title : "Notification title",
body : "message content"
}
});
});
So We must set clickAction property of the notification object to FCM_PLUGIN_ACTIVITY to make onNotification() method execute when the user tapped on the notification.
Here is a code exemple for the app.component.ts in witch the onNotification() method is implemented.
import { Platform, Nav, ToastController } from 'ionic-angular';
import { HomePage } from '../pages/home/home';
import { Component, ViewChild } from '#angular/core';
import { FCM } from '#ionic-native/fcm';
import { Signup } from '../pages/signup/signup';
#Component({
templateUrl: 'app.html',
selector: 'Myappname',
})
export class MyApp {
#ViewChild(Nav) nv: Nav;
rootPage: any = HomePage;
constructor(public fcm: FCM, platform: Platform) {
platform.ready().then(() => {
fcm.onNotification().subscribe(data => {
if (data.wasTapped) {
this.nv.push(Signup);
} else {
console.log("Received in foreground");
}
})
});
}
}
AND now, it works fine !
Try setting the root page as the signup page, hopefully it will work:
this.nv.setRoot(Signup);
and if that doesnt work try adding this before your fcm.onNotification()
var $this = this;
and then use $this to reference inside your if statement // (wasTapped)
$this.nv.setRoot(Signup);
Consider this scenario. I have an ionic2 app and I am using the the FCM plugin for push notifications. Now let us say a push notification arrives when the app is in the background. User, views the notification in the App drawer and then clicks the notification for further information. I would like the user to navigate to a particular path using this.nav.push(PushPage). How can I tap into the notification click event?
app.component.ts
import { Component,ViewChild } from '#angular/core';
import { Platform,NavController,AlertController } from 'ionic-angular';
import { StatusBar } from '#ionic-native/status-bar';
import { SplashScreen } from '#ionic-native/splash-screen';
import { FCM } from '#ionic-native/fcm';
import { HomePage } from '../pages/home/home';
import {PushPage} from '../pages/push/push';
declare var FCMPlugin;
#Component({
templateUrl: 'app.html',
providers :[FCM]
})
export class MyApp {
rootPage:any = HomePage;
#ViewChild(NavController) nav;
constructor(platform: Platform, statusBar: StatusBar, splashScreen:
SplashScreen,private fcm: FCM,
private alertCtrl: AlertController) {
platform.ready().then(() => {
statusBar.styleDefault();
splashScreen.hide();
fcm.subscribeToTopic('marketing');
fcm.getToken().then(token=>{
})
fcm.onNotification().subscribe(data=>{
if(data.wasTapped){
console.log("Received in background");
this.nav.push(PushPage);
} else {
console.log("Received in foreground");
this.nav.push(PushPage);
};
})
fcm.onTokenRefresh().subscribe(token=>{
this.nav.push(PushPage);
})
fcm.unsubscribeFromTopic('marketing');
});
}
}
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);
}
}