Ionic 6 capacitor `pushNotificationActionPerformed ` event is not getting triggered on clicking push notification - ionic-framework

I am implementing push notification in my Ionic 6 App. I am using #capacitor/push-notifications plugin to manage push notification in my Ionic App.
import { Injectable } from '#angular/core';
import { Capacitor } from '#capacitor/core';
import { PushNotifications } from '#capacitor/push-notifications';
import { Router } from '#angular/router';
#Injectable({
providedIn: 'root',
})
export class FcmService {
constructor(private router: Router) {}
initPush() {
const fcmtoken = localStorage.getItem('fcmtoken');
if (Capacitor.platform !== 'web' && !fcmtoken) {
this.registerNotifications();
}
}
registerNotifications = async () => {
let permStatus = await PushNotifications.checkPermissions();
if (permStatus.receive === 'prompt') {
permStatus = await PushNotifications.requestPermissions();
}
if (permStatus.receive !== 'granted') {
throw new Error('User denied permissions!');
}
await PushNotifications.register();
await PushNotifications.addListener('registration', token => {
console.info('Registration token: ', token.value);
localStorage.setItem('fcmtoken', token.value);
});
await PushNotifications.addListener('registrationError', err => {
console.error('Registration error: ', err.error);
});
await PushNotifications.addListener('pushNotificationReceived', notification => {
console.log('Push notification received: ', notification);
});
await PushNotifications.addListener('pushNotificationActionPerformed', notification => {
alert(JSON.stringify(notification));
console.log('Push notification action performed', notification.actionId, notification.inputValue);
});
}
getDeliveredNotifications = async () => {
const notificationList = await PushNotifications.getDeliveredNotifications();
console.log('delivered notifications', notificationList);
}
}
I am calling the initPush() from AppComponent and i am receiving notification in my app. But when i tap on that notification nothing happens. pushNotificationActionPerformed event is not getting triggered. Am i missing some configuration. I am using it in Android app.
Please help if someone has implemented it.

Related

Turn In API giving no response

I'm trying to integrate google classroom API where student can submit their work on a particular
assignment and then update the state to hand in/turn in. I'm using turn in API endpoint but the API
doesn't update the state nor return any response.
import { Injectable } from '#nestjs/common';
import { ConfigService } from '#nestjs/config';
import { google, classroom_v1, Auth } from 'googleapis';
#Injectable()
export class GoogleApiService {
oauth2Client: Auth.OAuth2Client;
classroom: classroom_v1.Classroom;
constructor(private configService: ConfigService) {
const clientId = this.configService.get('GOOGLE_CLIENT_ID');
const clientSecret = this.configService.get('GOOGLE_SECRET_KEY');
const redirectUrl = this.configService.get('GOOGLE_REDIRECT_URL');
this.oauth2Client = new google.auth.OAuth2(
clientId,
clientSecret,
redirectUrl,
);
google.options({
http2: true,
});
this.classroom = google.classroom({
version: 'v1',
auth: this.oauth2Client,
});
}
setRefreshToken(token: string) {
this.oauth2Client.setCredentials({
refresh_token: token,
});
}
async turnIn(courseId: string, courseWorkId: string, submissionId: string) {
try {
const turnInParam: classroom_v1.Params$Resource$Courses$Coursework$Studentsubmissions$Turnin =
{
courseId,
courseWorkId,
id: submissionId,
};
const res =
await this.classroom.courses.courseWork.studentSubmissions.turnIn(
turnInParam,
);
return res;
} catch (error) {
console.log(error);
return false;
}
}
}
after this nothing executes.
const res =
await this.classroom.courses.courseWork.studentSubmissions.turnIn(
turnInParam,
);

How to get data from next auth signIn Google provider in custom signIn page?

I need to get the data from the custom signIn page in order to write a user to the sanity database. But these signIn data is only obtained in [...nextauth].js file.
Code:
[...nextauth].js
import NextAuth from 'next-auth'
import GoogleProvider from 'next-auth/providers/google'
export default NextAuth({
// Configure one or more authentication providers
providers: [
GoogleProvider({
clientId: "xxxxxx",
clientSecret: "xxxxx",
}),
// ...add more providers here
],
secret: "something",
pages: {
signIn: '/auth/signin',
},
callbacks: {
async session({ session, token, user }) {
session.user.username = session.user.name
.split(' ')
.join('')
.toLocaleLowerCase()
session.user.uid = token.sub
return session
},
},
})
And these session data can be used inside components using useSession from next-auth.
But while trying to get the data to my custom signIn page, session is undefined.
import { getProviders, signIn as signIntoProvider } from "next-auth/react";
import { sanityClient } from "../../sanity";
import { useSession } from 'next-auth/react';
function signIn({users}) {
const { data: session } = useSession()
const onSubmit = (data) => {
fetch("/api/createUser", {
method: "POST",
body: JSON.stringify(data),
})
.then((resp) => {
console.log(resp);
})
.catch((err) => {
console.log(err);
});
};
const checkIfUserThere = async () => {
let newUser = session.user.email;
for (const data of users) {
if (data.email === newUser) {
return true;
}
}
return false;
};
useEffect(() => {
(async () => {
const userExists = await checkIfUserThere();
if(userExists === false ){
onSubmit(session.user); //write to sanity database
}
})();
}, []);
return (
<>
<button
className="rounded-lg bg-blue-500 p-3 text-white"
onClick={() =>
signIntoProvider("google", { callbackUrl: "/" })
}
>
Sign in with Google
</button>
</>
);
}
The above code is for a custom signIn page.
What is expected :
Once the user clicks the sign-in with the Google button, the session data must be added to the sanity database. But in my case, session here is undefined.
A simple way to do this is to write the logic inside the [...nextAuth].js file.
To solve the task of popularizing a document in Sanity from a Google authentication, you must first establish a connection to your Sanity project. Note that this import comes from the 'npm i #sanity/client' package or 'yarn add #sanity/client' and is not a reference to the configuration located in the sanity.js file. To do this, you can import the #sanity/client library and set up a configuration to connect to your project:
import sanityClient from "#sanity/client";
const config = {
dataset: "DATASET_NAME",
projectId: "PROJECT_ID",
useCdn: 'CDN'
token: "YOUR_TOKEN_SANITY",
};
export const client = sanityClient(config);
After setting up authentication with Google, you must set up a callback to run every time a user authenticates. This callback should look in Sanity to see if the user already exists, and if not, create a new user document in Sanity with the authenticated user's information:
const populateSanityUser = async (user) => {
const sanityUser = await client.fetch(
`*[_type == "users" && email == "${user.email}"]{ //check if the email exists
email
}`
);
if (sanityUser.length > 0) { //if exists
return sanityUser;
} else { //if not, create a new user with Google user session data
try {
await client.create({
_type: "user",
name: user.name,
email: user.email,
urlImage: user.image,
... // another field in your document
});
return user;
} catch (error) {
return error;
}
}
};
export default NextAuth({
...authOptions,
callbacks: {
async signIn(user) {
const isAllowedToSignIn = true; //optional
if (isAllowedToSignIn) {
const sanityUser = await populateSanityUser(user.user);
return sanityUser;
} else {
return false;
}
},
},
});
Important: Make sure that when you pass the user coming from NextAuth callback function you use user.user, as it comes nested with more data.
More information about callbacks in NextAuth here: https://next-auth.js.org/configuration/callbacks

How to inject $axios into Pinia store SSR

I'm trying to inject my axios instance into the store so that I'm able to login into the app but unfortunately I'm being unable to. I have the followed boot file
import { boot } from 'quasar/wrappers';
import axios from 'axios';
import type {AxiosResponse} from 'axios';
import type { StatusCodes } from 'http-status-codes';
export type WrappedResponse = { response?: AxiosResponse };
export const isError = (e: WrappedResponse, statusCode: StatusCodes) =>
e.response && e.response.status === statusCode;
export default boot(({ app, store }) => {
const api = axios.create({ baseURL: import.meta.env.VITE_APP_API_BASE_URL });
app.provide('axios', api);
store.$axios = api;
});
Then on my store I have:
import { defineStore } from 'pinia';
export const useAppStore = defineStore('app', {
state: () => ({
}),
getters: {
},
actions: {
async login() {
console.log(this.$axios);
console.log('Logging in from store');
}
},
});
Whenever login is called it prints undefined. Any idea on what I'm doing wrong?
You simply have to create a Pinia plugin:
export default boot(({ app, store }) => {
const api = axios.create({ baseURL: import.meta.env.VITE_APP_API_BASE_URL });
app.provide('axios', api);
store.use(() => ({ api })); // 👈
});

Ionic 4 LoadingController

I am trying to add a LoadingController to my Ionic 5 app.
With the below code, the loading spinner is appearing:
async presentLoading() {
const loading = await this.loadingCtrl.create({
message: 'Please wait...',
});
await loading.present();
}
getPosts() {
this.posts = [];
this.presentLoading();
query.get()
.then((docs) => {
docs.forEach((doc) => {
this.posts.push(doc);
})
}).catch((err) => {
console.log(err)
})
}
But I don't know how to dismiss the LoadingController once the posts array has been populated.
Can someone please show me how this is done?
You have to dismiss the controller. For that you will have to keep a reference to it, something like this,
async presentLoading() {
this.loading = await this.loadingCtrl.create({
message: 'Please wait...',
});
await this.loading.present();
}
getPosts() {
this.posts = [];
this.presentLoading();
query.get()
.then((docs) => {
docs.forEach((doc) => {
this.posts.push(doc);
this.loading.dismiss();
})
}).catch((err) => {
console.log(err)
})
}
If you need to get notice when the dismiss occurs, you can listen to onDidDismiss event.
Links:
Ionic Docs - LoadingController

How to test axios interceptors using jest?

I'm trying to test the following code:
import axios from 'axios';
import { history } from './ReduxService';
axios.interceptors.response.use(response => response,
(error) => {
if ((error.response && error.response.status === 408) || error.code === 'ECONNABORTED') {
history.push('/error');
}
return Promise.reject(error);
}
);
Any advice on how to cover it?
First, modify the code so that you can pass a mocked version of axios in:
import axios, { AxiosInstance } from 'axios';
import { history } from './ReduxService';
export const addResponseInterceptor(client: AxiosInstance) => {
client.interceptors.response.use(response => response,
(error) => {
if ((error.response && error.response.status === 408) || error.code ===
'ECONNABORTED') {
history.push('/error');
}
return Promise.reject(error);
});
};
Then set up your tests like this:
import { addResponseInterceptor } from './yourInterceptorFile'
import axios from 'axios';
jest.mock('axios', () => {
return {
create: jest.fn(),
interceptors: {
request: {
use: jest.fn(),
eject: jest.fn(),
},
response: {
use: jest.fn(),
eject: jest.fn(),
},
}
};
});
describe('addResponseInterceptor tests', () => {
beforeEach(() => {
(axios.create as jest.Mock).mockReset();
(axios.interceptors.request.use as jest.Mock).mockReset();
(axios.interceptors.request.eject as jest.Mock).mockReset();
(axios.interceptors.response.use as jest.Mock).mockReset();
(axios.interceptors.response.eject as jest.Mock).mockReset();
});
it('should add a response interceptor to the axios instance', () => {
addResponseInterceptor(axios);
expect(axios.interceptors.response.use).toHaveBeenCalled();
});
it('should push to history when an error occurs', async() => {
const historySpy = jest.spyOn(history, 'push');
const axiosClient = axios;
addResponseInterceptor(axios);
const interceptorErrorHandler = (axiosClient.interceptors.response.use as jest.Mock).mock.calls[0][1];
try {
await interceptorErrorHandler({
response: {
status: 408
}
});
//this should not be called--the promise should be rejected
expect(true).toBe(false);
} catch {
expect(historySpy).toHaveBeenCalledWith('/error');
}
});
. . .
});