Skip to content
Open
Show file tree
Hide file tree
Changes from 12 commits
Commits
Show all changes
58 commits
Select commit Hold shift + click to select a range
082e946
Minor
bistaastha Jan 21, 2026
03f0a14
Minor
bistaastha Jan 21, 2026
f5879c7
Update org-user.service.spec.ts
bistaastha Jan 21, 2026
2e73a08
Minor
bistaastha Jan 21, 2026
060f63f
Merge branch 'fyle-api-integration-for-notifs' of github.com:fylein/f…
bistaastha Jan 21, 2026
178a224
Minor
bistaastha Jan 22, 2026
ce1f560
Minor
bistaastha Jan 22, 2026
249829c
Minor
bistaastha Jan 22, 2026
e112f85
Minor
bistaastha Jan 22, 2026
b8832ae
Minor
bistaastha Jan 22, 2026
56ea99a
Minor
bistaastha Jan 23, 2026
be63e04
Minor
bistaastha Jan 23, 2026
52554fb
Minor
bistaastha Jan 23, 2026
5897bb6
Merge branch 'fyle-fix-setup-keys' into fyle-add-redirection-for-noti…
bistaastha Jan 23, 2026
d787bac
Merge remote-tracking branch 'origin/fyle-fix-setup-keys' into fyle-a…
bistaastha Jan 23, 2026
b26d6e0
Merge branch 'fyle-fix-setup-keys' into fyle-add-redirection-for-noti…
bistaastha Jan 23, 2026
88cfed2
Merge branch 'fyle-fix-setup-keys' into fyle-add-redirection-for-noti…
bistaastha Jan 23, 2026
f6ec718
Minor
bistaastha Jan 27, 2026
a440a25
Minor
bistaastha Jan 27, 2026
7cf5cfa
Minor
bistaastha Jan 27, 2026
ccbf3f7
Minor
bistaastha Jan 27, 2026
2ce020f
Minor
bistaastha Jan 28, 2026
8d22251
Update push-notification.service.ts
bistaastha Jan 28, 2026
53013f3
Minor
bistaastha Jan 29, 2026
448562f
Minor
bistaastha Jan 29, 2026
2d25b9b
Merge branch 'fyle-add-redirection-for-notifications' of github.com:f…
bistaastha Jan 29, 2026
2b867db
Minor
bistaastha Jan 29, 2026
f418f33
Minor
bistaastha Jan 29, 2026
3462fde
Minor
bistaastha Jan 29, 2026
82f5600
Minor
bistaastha Jan 29, 2026
f070816
Minor
bistaastha Jan 30, 2026
721d8ac
Minor
bistaastha Jan 30, 2026
c0ba3eb
Minor
bistaastha Jan 30, 2026
0815453
Minor
bistaastha Jan 30, 2026
d4f18d1
Minor
bistaastha Jan 30, 2026
50e8495
Minor
bistaastha Jan 30, 2026
7750455
Minor
bistaastha Jan 30, 2026
bc25593
Minor
bistaastha Jan 30, 2026
a575594
Minor
bistaastha Jan 30, 2026
8d3a4ae
Minor
bistaastha Jan 30, 2026
4cbbf17
Minor
bistaastha Jan 30, 2026
d21b725
Minor
bistaastha Jan 30, 2026
afaa507
Minor
bistaastha Jan 30, 2026
e55921e
Minor
bistaastha Jan 30, 2026
b37f3c8
Minor
bistaastha Jan 30, 2026
b32f422
Minor
bistaastha Jan 31, 2026
fc141cf
Minor
bistaastha Jan 31, 2026
ba510e3
Minor
bistaastha Jan 31, 2026
adb990b
Minor
bistaastha Jan 31, 2026
ca32a7a
Minor
bistaastha Jan 31, 2026
fe356a4
Minor
bistaastha Jan 31, 2026
a44f505
Minor
bistaastha Feb 1, 2026
67d5a95
Merge remote-tracking branch 'origin/fyle-fix-setup-keys' into fyle-a…
amit429 Feb 2, 2026
99782e3
testing
amit429 Feb 2, 2026
2603fdc
Commented get device token logic for testing purposes
amit429 Feb 4, 2026
6424719
testing the deeplinks
amit429 Feb 5, 2026
3534acc
fix the redirection from app killed state
amit429 Feb 5, 2026
b280e92
testing
amit429 Feb 5, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions src/app/app.component.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import { NavController } from '@ionic/angular/standalone';
import { UserEventService } from './core/services/user-event.service';
import { DeviceService } from './core/services/device.service';
import { GmapsService } from './core/services/gmaps.service';
import { PushNotificationService } from './core/services/push-notification.service';

import { SplashScreen } from '@capacitor/splash-screen';
import { StatusBar } from '@capacitor/status-bar';
Expand Down Expand Up @@ -73,6 +74,7 @@ describe('AppComponent', () => {
let gmapsService: jasmine.SpyObj<GmapsService>;
let menuController: jasmine.SpyObj<MenuController>;
let backButtonService: jasmine.SpyObj<BackButtonService>;
let pushNotificationService: jasmine.SpyObj<PushNotificationService>;
beforeEach(waitForAsync(() => {
// Mock Capacitor plugins before component creation
// Create spies that return resolved promises
Expand Down Expand Up @@ -155,6 +157,7 @@ describe('AppComponent', () => {
const gmapsServiceSpy = jasmine.createSpyObj('GmapsService', ['loadLibrary']);
const menuControllerSpy = jasmine.createSpyObj('MenuController', ['swipeGesture']);
const backButtonServiceSpy = jasmine.createSpyObj('BackButtonService', ['showAppCloseAlert']);
const pushNotificationServiceSpy = jasmine.createSpyObj('PushNotificationService', ['unregister']);

// Configure tracking service with missing methods
trackingServiceSpy.updateIdentityIfNotPresent = jasmine.createSpy('updateIdentityIfNotPresent').and.resolveTo();
Expand Down Expand Up @@ -190,6 +193,7 @@ describe('AppComponent', () => {
{ provide: GmapsService, useValue: gmapsServiceSpy },
{ provide: MenuController, useValue: menuControllerSpy },
{ provide: BackButtonService, useValue: backButtonServiceSpy },
{ provide: PushNotificationService, useValue: pushNotificationServiceSpy },
],
})
.overrideComponent(AppComponent, {
Expand Down Expand Up @@ -220,6 +224,7 @@ describe('AppComponent', () => {
gmapsService = TestBed.inject(GmapsService) as jasmine.SpyObj<GmapsService>;
menuController = TestBed.inject(MenuController) as jasmine.SpyObj<MenuController>;
backButtonService = TestBed.inject(BackButtonService) as jasmine.SpyObj<BackButtonService>;
pushNotificationService = TestBed.inject(PushNotificationService) as jasmine.SpyObj<PushNotificationService>;
}));

describe('ngAfterViewInit', () => {
Expand Down
4 changes: 4 additions & 0 deletions src/app/app.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import { NgClass } from '@angular/common';
import { FyConnectionComponent } from './shared/components/fy-connection/fy-connection.component';
import { Capacitor } from '@capacitor/core';
import { AppShortcuts } from '@capawesome/capacitor-app-shortcuts';
import { PushNotificationService } from './core/services/push-notification.service';

@Component({
selector: 'app-root',
Expand All @@ -53,6 +54,8 @@ export class AppComponent implements OnInit, AfterViewInit {

private router = inject(Router);

private pushNotificationService = inject(PushNotificationService);

private activatedRoute = inject(ActivatedRoute);

private userEventService = inject(UserEventService);
Expand Down Expand Up @@ -293,6 +296,7 @@ export class AppComponent implements OnInit, AfterViewInit {
this.userEventService.onLogout(() => {
this.trackingService.onSignOut();
this.freshChatService.destroy();
this.pushNotificationService.unregister();
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unregisters a token on log out

this.isSwitchedToDelegator = false;
Comment on lines 301 to 305
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Handle unregister promise (and avoid double-unregister).
unregister() returns a Promise; unhandled rejection can surface, and the service already auto-unregisters on logout. Pick one place, and if you keep this call, guard it.

🐛 Suggested fix (keep call, guard it)
-      this.pushNotificationService.unregister();
+      void this.pushNotificationService.unregister().catch(noop);
🤖 Prompt for AI Agents
In `@src/app/app.component.ts` around lines 296 - 300, The logout handler
registered with userEventService.onLogout calls
pushNotificationService.unregister() but doesn't handle its returned Promise and
may double-unregister; update the onLogout callback (in the block where
trackingService.onSignOut(), freshChatService.destroy(),
pushNotificationService.unregister(), isSwitchedToDelegator = false are called)
to guard and handle the promise: first check a registration state (e.g.
pushNotificationService.isRegistered or an internal flag) before calling
unregister, and if keeping the call always, ensure you handle the Promise by
awaiting it or attaching .catch(...) to swallow or log harmless "already
unregistered" errors to avoid unhandled rejections and duplicate unregister
attempts.

this.router.navigate(['/', 'auth', 'sign_in']);
});
Expand Down
43 changes: 39 additions & 4 deletions src/app/core/services/push-notification.service.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,27 @@
import { Injectable } from '@angular/core';
import { Injectable, inject } from '@angular/core';
import { PushNotifications, Token } from '@capacitor/push-notifications';
import { DeepLinkService } from './deep-link.service';
import { TrackingService } from './tracking.service';
import { UserEventService } from './user-event.service';

@Injectable({
providedIn: 'root',
})
export class PushNotificationService {
private listenersInitialized = false;

private deepLinkService: DeepLinkService = inject(DeepLinkService);

private trackingService: TrackingService = inject(TrackingService);

private userEventService: UserEventService = inject(UserEventService);

constructor() {
this.userEventService.onLogout(() => {
void this.unregister();
});
}

async initializePushNotifications(): Promise<void> {
const permission = await PushNotifications.requestPermissions();

Expand All @@ -16,18 +31,38 @@
}
}

async unregister(): Promise<void> {
await PushNotifications.unregister();
}

private initListeners(): void {
if (this.listenersInitialized) {
return;
}

this.listenersInitialized = true;

PushNotifications.addListener('registration', (_token: Token) => {
// TODO: Integrate API for sending token to backend
PushNotifications.addListener('registration', (token: Token) => {
const tokenValue = token?.value;

Check failure on line 46 in src/app/core/services/push-notification.service.ts

View workflow job for this annotation

GitHub Actions / Run linters

'tokenValue' is assigned a value but never used
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
this.trackingService.eventTrack('Push Notification Registered');
});
PushNotifications.addListener('registrationError', () => undefined);
PushNotifications.addListener('pushNotificationActionPerformed', () => undefined);
PushNotifications.addListener('pushNotificationActionPerformed', (event) => {
const data = (event?.notification?.data as { url?: string; actionType?: string } | undefined) ?? {};
const url = data.url;
const actionType = data.actionType;

if (!url || typeof url !== 'string') {
return;
}

// eslint-disable-next-line @typescript-eslint/no-unsafe-call
this.trackingService.eventTrack('Push Notification Clicked', { actionType });

const redirectParams = this.deepLinkService.getJsonFromUrl(url);
this.deepLinkService.redirect(redirectParams);
});
Comment on lines 116 to 134
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Guard deep-link parsing to avoid crash.
Line 80 can throw if the URL is malformed — wrap in try/catch so a bad payload doesn’t kill the handler.

🛡️ Suggested fix
 this.trackingService.eventTrack('Push Notification Clicked', { actionType });

-const redirectParams = this.deepLinkService.getJsonFromUrl(url);
-this.deepLinkService.redirect(redirectParams);
+try {
+  const redirectParams = this.deepLinkService.getJsonFromUrl(url);
+  this.deepLinkService.redirect(redirectParams);
+} catch (error) {
+  this.trackingService.eventTrack('Push Notification Redirect Failed', { error });
+}
🤖 Prompt for AI Agents
In `@src/app/core/services/push-notification.service.ts` around lines 68 - 82, The
push notification click handler in addNotificationClickListener uses
deepLinkService.getJsonFromUrl(url) and deepLinkService.redirect(redirectParams)
without guarding against malformed URLs; wrap the parsing and redirect logic in
a try/catch inside the PushNotifications.addListener callback so exceptions from
getJsonFromUrl or redirect are caught, log or handle the error (via
trackingService or a logger) and return gracefully instead of throwing; keep the
early checks for url and event the same and ensure
trackingService.eventTrack('Push Notification Clicked', { actionType }) still
runs before the guarded parse/redirect block.

}
}

Loading