From 88307cca2863ac905f45d3d9de3cd5ab50101159 Mon Sep 17 00:00:00 2001 From: Erwin-N <111194281+Erwin-N@users.noreply.github.com> Date: Fri, 13 Mar 2026 20:19:56 +0100 Subject: [PATCH] Task/eliminate OnDestroy lifecycle hook from portfolio analysis page (#6524) * Eliminate OnDestroy lifecycle hook --- .../analysis/analysis-page.component.ts | 37 ++++++++----------- 1 file changed, 15 insertions(+), 22 deletions(-) diff --git a/apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts b/apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts index 5cd24777c..47845ea6f 100644 --- a/apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts +++ b/apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts @@ -24,10 +24,11 @@ import { Clipboard } from '@angular/cdk/clipboard'; import { ChangeDetectorRef, Component, - OnDestroy, + DestroyRef, OnInit, ViewChild } from '@angular/core'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { MatButtonModule } from '@angular/material/button'; import { MatCardModule } from '@angular/material/card'; import { MatMenuModule, MatMenuTrigger } from '@angular/material/menu'; @@ -42,8 +43,6 @@ import { isNumber, sortBy } from 'lodash'; import ms from 'ms'; import { DeviceDetectorService } from 'ngx-device-detector'; import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader'; -import { Subject } from 'rxjs'; -import { takeUntil } from 'rxjs/operators'; @Component({ imports: [ @@ -64,7 +63,7 @@ import { takeUntil } from 'rxjs/operators'; styleUrls: ['./analysis-page.scss'], templateUrl: './analysis-page.html' }) -export class GfAnalysisPageComponent implements OnDestroy, OnInit { +export class GfAnalysisPageComponent implements OnInit { @ViewChild(MatMenuTrigger) actionsMenuButton!: MatMenuTrigger; public benchmark: Partial; @@ -102,12 +101,11 @@ export class GfAnalysisPageComponent implements OnDestroy, OnInit { public unitLongestStreak: string; public user: User; - private unsubscribeSubject = new Subject(); - public constructor( private changeDetectorRef: ChangeDetectorRef, private clipboard: Clipboard, private dataService: DataService, + private destroyRef: DestroyRef, private deviceService: DeviceDetectorService, private impersonationStorageService: ImpersonationStorageService, private snackBar: MatSnackBar, @@ -135,13 +133,13 @@ export class GfAnalysisPageComponent implements OnDestroy, OnInit { this.impersonationStorageService .onChangeHasImpersonation() - .pipe(takeUntil(this.unsubscribeSubject)) + .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe((impersonationId) => { this.hasImpersonationId = !!impersonationId; }); this.userService.stateChanged - .pipe(takeUntil(this.unsubscribeSubject)) + .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe((state) => { if (state?.user) { this.user = state.user; @@ -163,11 +161,11 @@ export class GfAnalysisPageComponent implements OnDestroy, OnInit { public onChangeBenchmark(symbolProfileId: string) { this.dataService .putUserSetting({ benchmark: symbolProfileId }) - .pipe(takeUntil(this.unsubscribeSubject)) + .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe(() => { this.userService .get(true) - .pipe(takeUntil(this.unsubscribeSubject)) + .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe((user) => { this.user = user; @@ -193,7 +191,7 @@ export class GfAnalysisPageComponent implements OnDestroy, OnInit { mode, filters: this.userService.getFilters() }) - .pipe(takeUntil(this.unsubscribeSubject)) + .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe(({ prompt }) => { this.clipboard.copy(prompt); @@ -207,7 +205,7 @@ export class GfAnalysisPageComponent implements OnDestroy, OnInit { snackBarRef .onAction() - .pipe(takeUntil(this.unsubscribeSubject)) + .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe(() => { window.open('https://duck.ai', '_blank'); }); @@ -222,11 +220,6 @@ export class GfAnalysisPageComponent implements OnDestroy, OnInit { }); } - public ngOnDestroy() { - this.unsubscribeSubject.next(); - this.unsubscribeSubject.complete(); - } - private fetchDividendsAndInvestments() { this.isLoadingDividendTimelineChart = true; this.isLoadingInvestmentTimelineChart = true; @@ -237,7 +230,7 @@ export class GfAnalysisPageComponent implements OnDestroy, OnInit { groupBy: this.mode, range: this.user?.settings?.dateRange }) - .pipe(takeUntil(this.unsubscribeSubject)) + .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe(({ dividends }) => { this.dividendsByGroup = dividends; @@ -252,7 +245,7 @@ export class GfAnalysisPageComponent implements OnDestroy, OnInit { groupBy: this.mode, range: this.user?.settings?.dateRange }) - .pipe(takeUntil(this.unsubscribeSubject)) + .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe(({ investments, streaks }) => { this.investmentsByGroup = investments; this.streaks = streaks; @@ -287,7 +280,7 @@ export class GfAnalysisPageComponent implements OnDestroy, OnInit { filters: this.userService.getFilters(), range: this.user?.settings?.dateRange }) - .pipe(takeUntil(this.unsubscribeSubject)) + .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe(({ chart, firstOrderDate, performance }) => { this.firstOrderDate = firstOrderDate ?? new Date(); @@ -346,7 +339,7 @@ export class GfAnalysisPageComponent implements OnDestroy, OnInit { filters: this.userService.getFilters(), range: this.user?.settings?.dateRange }) - .pipe(takeUntil(this.unsubscribeSubject)) + .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe(({ holdings }) => { const holdingsSorted = sortBy( holdings.filter(({ netPerformancePercentWithCurrencyEffect }) => { @@ -397,7 +390,7 @@ export class GfAnalysisPageComponent implements OnDestroy, OnInit { range: this.user?.settings?.dateRange, startDate: this.firstOrderDate }) - .pipe(takeUntil(this.unsubscribeSubject)) + .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe(({ marketData }) => { this.benchmarkDataItems = marketData.map(({ date, value }) => { return {