diff --git a/apps/picsa-apps/extension-app-native/android/.idea/.gitignore b/apps/picsa-apps/extension-app-native/android/.idea/.gitignore
deleted file mode 100644
index 26d33521a..000000000
--- a/apps/picsa-apps/extension-app-native/android/.idea/.gitignore
+++ /dev/null
@@ -1,3 +0,0 @@
-# Default ignored files
-/shelf/
-/workspace.xml
diff --git a/apps/picsa-apps/extension-app-native/android/.idea/compiler.xml b/apps/picsa-apps/extension-app-native/android/.idea/compiler.xml
deleted file mode 100644
index b589d56e9..000000000
--- a/apps/picsa-apps/extension-app-native/android/.idea/compiler.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/apps/picsa-apps/extension-app-native/android/.idea/jarRepositories.xml b/apps/picsa-apps/extension-app-native/android/.idea/jarRepositories.xml
deleted file mode 100644
index de647e0db..000000000
--- a/apps/picsa-apps/extension-app-native/android/.idea/jarRepositories.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/apps/picsa-apps/extension-app-native/android/.idea/misc.xml b/apps/picsa-apps/extension-app-native/android/.idea/misc.xml
deleted file mode 100644
index d64a7f74c..000000000
--- a/apps/picsa-apps/extension-app-native/android/.idea/misc.xml
+++ /dev/null
@@ -1,17 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/apps/picsa-apps/extension-app-native/android/app/capacitor.build.gradle b/apps/picsa-apps/extension-app-native/android/app/capacitor.build.gradle
index 26842e92c..b673116e3 100644
--- a/apps/picsa-apps/extension-app-native/android/app/capacitor.build.gradle
+++ b/apps/picsa-apps/extension-app-native/android/app/capacitor.build.gradle
@@ -22,6 +22,7 @@ dependencies {
implementation project(':capacitor-screen-orientation')
implementation project(':capacitor-camera')
implementation project(':capacitor-share')
+ implementation project(':capacitor-push-notifications')
implementation "androidx.webkit:webkit:1.4.0"
implementation "androidx.legacy:legacy-support-v4:1.0.0"
}
diff --git a/apps/picsa-apps/extension-app-native/android/capacitor.settings.gradle b/apps/picsa-apps/extension-app-native/android/capacitor.settings.gradle
index 9a8d4b1b4..f79333c67 100644
--- a/apps/picsa-apps/extension-app-native/android/capacitor.settings.gradle
+++ b/apps/picsa-apps/extension-app-native/android/capacitor.settings.gradle
@@ -40,3 +40,6 @@ project(':capacitor-camera').projectDir = new File('../../../../node_modules/@ca
include ':capacitor-share'
project(':capacitor-share').projectDir = new File('../../../../node_modules/@capacitor/share/android')
+
+include ':capacitor-push-notifications'
+project(':capacitor-push-notifications').projectDir = new File('../../../../node_modules/@capacitor/push-notifications/android')
diff --git a/apps/picsa-apps/extension-app-native/android/gradle/wrapper/gradle-wrapper.properties b/apps/picsa-apps/extension-app-native/android/gradle/wrapper/gradle-wrapper.properties
index d951fac2b..18330fcba 100644
--- a/apps/picsa-apps/extension-app-native/android/gradle/wrapper/gradle-wrapper.properties
+++ b/apps/picsa-apps/extension-app-native/android/gradle/wrapper/gradle-wrapper.properties
@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-all.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
diff --git a/apps/picsa-apps/extension-app-native/capacitor.config.ts b/apps/picsa-apps/extension-app-native/capacitor.config.ts
index fd7f436cc..30fdd4268 100644
--- a/apps/picsa-apps/extension-app-native/capacitor.config.ts
+++ b/apps/picsa-apps/extension-app-native/capacitor.config.ts
@@ -1,3 +1,4 @@
+///
import { CapacitorConfig } from '@capacitor/cli';
const config: CapacitorConfig = {
@@ -31,7 +32,13 @@ const config: CapacitorConfig = {
'@capacitor/screen-orientation',
'@capacitor/camera',
"@capacitor/share",
+ '@capacitor/push-notifications',
],
+ plugins:{
+ PushNotifications: {
+ presentationOptions: ["alert"],
+ },
+ },
// Enable app to use native http for requests (bypass cors)
// https://capacitorjs.com/docs/apis/http
// TODO - check if resources still work as intended once enabled
@@ -49,6 +56,7 @@ const config: CapacitorConfig = {
*/
cleartext: true,
},
+
};
/**
diff --git a/apps/picsa-apps/extension-app/src/app/app.component.ts b/apps/picsa-apps/extension-app/src/app/app.component.ts
index 451b971e7..73233a3d3 100644
--- a/apps/picsa-apps/extension-app/src/app/app.component.ts
+++ b/apps/picsa-apps/extension-app/src/app/app.component.ts
@@ -1,5 +1,5 @@
/* eslint-disable @nx/enforce-module-boundaries */
-import { Component, Injector, OnInit, signal } from '@angular/core';
+import { AfterViewInit, Component, Injector, OnInit, signal } from '@angular/core';
import { Router } from '@angular/router';
import { ENVIRONMENT } from '@picsa/environments';
import { PicsaMigrationService } from '@picsa/migrations';
@@ -8,6 +8,7 @@ import { ResourcesToolService } from '@picsa/resources/src/app/services/resource
import { AnalyticsService } from '@picsa/shared/services/core/analytics.service';
import { CrashlyticsService } from '@picsa/shared/services/core/crashlytics.service';
import { PerformanceService } from '@picsa/shared/services/core/performance.service';
+import { PicsaPushNotificationService } from '@picsa/shared/services/core/push-notifications.service';
@Component({
selector: 'picsa-root',
@@ -15,7 +16,7 @@ import { PerformanceService } from '@picsa/shared/services/core/performance.serv
styleUrls: ['./app.component.scss'],
standalone: false,
})
-export class AppComponent implements OnInit {
+export class AppComponent implements OnInit, AfterViewInit {
title = 'extension-toolkit';
public ready = signal(false);
public showLoader = signal(false);
@@ -28,21 +29,29 @@ export class AppComponent implements OnInit {
private resourcesService: ResourcesToolService,
private monitoringService: MonitoringToolService,
private migrationService: PicsaMigrationService,
+ private pushNotificationService: PicsaPushNotificationService,
private injector: Injector
) {}
async ngOnInit() {
+ // wait for migrations to run
+ await this.runMigrations();
+
+ this.ready.set(true);
+ }
+ async ngAfterViewInit() {
this.performanceService.setEnabled({ enabled: ENVIRONMENT.production });
- this.crashlyticsService.ready().then(() => null);
+ this.crashlyticsService.ready();
// eagerly enable analytics collection
this.analyticsService.init(this.router);
- // wait for migrations to run
- await this.runMigrations();
// eagerly load resources service to populate hardcoded resources
this.resourcesService.ready();
// eagerly load monitoring service to sync form data
this.monitoringService.ready();
- this.ready.set(true);
+ // delay push notification as will prompt for permissions
+ setTimeout(() => {
+ this.pushNotificationService.initializePushNotifications();
+ }, 1000);
}
private async runMigrations() {
diff --git a/libs/shared/src/services/core/push-notifications.service.ts b/libs/shared/src/services/core/push-notifications.service.ts
new file mode 100644
index 000000000..6546d9cbe
--- /dev/null
+++ b/libs/shared/src/services/core/push-notifications.service.ts
@@ -0,0 +1,72 @@
+import { Injectable } from '@angular/core';
+import { ActionPerformed, PushNotifications, PushNotificationSchema, Token } from '@capacitor/push-notifications';
+
+@Injectable({
+ providedIn: 'root',
+})
+export class PicsaPushNotificationService {
+ //constructor() {}
+
+ public async initializePushNotifications() {
+ try {
+ // Check if permission is already granted
+ const permResult = await PushNotifications.checkPermissions();
+
+ if (permResult.receive === 'prompt' || permResult.receive === 'prompt-with-rationale') {
+ // Request permissions
+ const reqResult = await PushNotifications.requestPermissions();
+ if (reqResult.receive !== 'granted') {
+ console.error('Push notification permission was denied');
+ return;
+ }
+ }
+ // Register with Apple / Google to receive push via FCM
+ await PushNotifications.register();
+
+ // Remove any existing listeners to prevent duplicates
+ await PushNotifications.removeAllListeners();
+
+ // Add listeners
+ PushNotifications.addListener('registration', (token: Token) => {
+ console.log('Push registration success');
+ // in case we have logic to save and update device tokens
+ //this.sendTokenToServer(token.value);
+ });
+
+ PushNotifications.addListener('registrationError', (error: any) => {
+ // handle error logic
+ console.error('Error on registration:', error);
+ });
+
+ PushNotifications.addListener('pushNotificationReceived', (notification: PushNotificationSchema) => {
+ console.log('Push received');
+ // Handle foreground notification if required
+ this.handleForegroundNotification(notification);
+ });
+
+ PushNotifications.addListener('pushNotificationActionPerformed', (notification: ActionPerformed) => {
+ console.log('Push action performed');
+ // Handle notification click
+ this.handleNotificationClick(notification);
+ });
+ } catch (err) {
+ console.error('Error initializing push notifications:', err);
+ }
+ }
+
+ private async sendTokenToServer(token: string) {
+ //TODO: Implement sending token to your backend if required
+ //guidence on where we can save this
+ }
+
+ private handleForegroundNotification(notification: PushNotificationSchema) {
+ // Implement custom foreground notification handling
+ }
+
+ private handleNotificationClick(actionPerformed: ActionPerformed) {
+ // Implement navigation or other actions when notification is clicked
+ const notification = actionPerformed.notification;
+ // in the case notification has extra infromations like a route to navigate to
+ // this.router.navigate([notification.data.route]);
+ }
+}
diff --git a/package.json b/package.json
index b9e16c8ef..c624d7ac0 100644
--- a/package.json
+++ b/package.json
@@ -70,6 +70,7 @@
"@capacitor/filesystem": "^6.0.2",
"@capacitor/geolocation": "^6.1.0",
"@capacitor/network": "^6.0.3",
+ "@capacitor/push-notifications": "^6.0.4",
"@capacitor/screen-orientation": "^6.0.3",
"@capacitor/share": "^6.0.3",
"@ngx-translate/core": "~16.0.4",
diff --git a/yarn.lock b/yarn.lock
index d1a6670c3..e17a948ac 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2299,6 +2299,15 @@ __metadata:
languageName: node
linkType: hard
+"@capacitor/push-notifications@npm:^6.0.4":
+ version: 6.0.4
+ resolution: "@capacitor/push-notifications@npm:6.0.4"
+ peerDependencies:
+ "@capacitor/core": ^6.0.0
+ checksum: 10c0/c16315ebebfc0ec15f171f0330aeced3b851761f96522fefaca79c16b260ab9606198e021a3370b419308307efedec522af3dc5be4bfeec34d103836e79086b9
+ languageName: node
+ linkType: hard
+
"@capacitor/screen-orientation@npm:^6.0.3":
version: 6.0.3
resolution: "@capacitor/screen-orientation@npm:6.0.3"
@@ -19013,6 +19022,7 @@ __metadata:
"@capacitor/filesystem": "npm:^6.0.2"
"@capacitor/geolocation": "npm:^6.1.0"
"@capacitor/network": "npm:^6.0.3"
+ "@capacitor/push-notifications": "npm:^6.0.4"
"@capacitor/screen-orientation": "npm:^6.0.3"
"@capacitor/share": "npm:^6.0.3"
"@ngx-translate/core": "npm:~16.0.4"