From b32dfe4e74393ecb64aad4f83d415fa60f2f37bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20K=C3=B6hler?= <74658813+SebastianKohler@users.noreply.github.com> Date: Mon, 19 Feb 2024 10:20:45 +0200 Subject: [PATCH 1/2] fix: memory leak related to BehaviorSubject-subscription Also, as a precation, unsubscribe from all route subscriptions on component destruction. --- CHANGELOG.md | 4 ++++ .../modals/download-texts/download-texts.modal.ts | 14 +++++++++----- .../modals/named-entity/named-entity.modal.ts | 8 ++++++-- src/app/pages/ebook/ebook.page.ts | 12 +++++++++--- src/app/services/document-head.service.ts | 6 +++--- src/app/services/view-options.service.ts | 6 +++--- 6 files changed, 34 insertions(+), 16 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 63b309a..5f1e17a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/), and this ## [Unreleased] +### Fixes + +- Memory leak related to BehaviorSubject-subscription in the download-texts modal. Also, as a precation, unsubscribe from all route subscriptions on component destruction. + ## [1.3.0] – 2024-02-16 diff --git a/src/app/dialogs/modals/download-texts/download-texts.modal.ts b/src/app/dialogs/modals/download-texts/download-texts.modal.ts index ff268c3..b9ee78b 100644 --- a/src/app/dialogs/modals/download-texts/download-texts.modal.ts +++ b/src/app/dialogs/modals/download-texts/download-texts.modal.ts @@ -52,6 +52,7 @@ export class DownloadTextsModal implements OnDestroy, OnInit { manuscriptsList$: Observable; readTextLanguages: string[] = []; referenceData: any = null; + pageTitleSubscr: Subscription | null = null; printTextSubscription: Subscription | null = null; printTranslation: string = ''; publicationData$: Observable; @@ -167,11 +168,13 @@ export class DownloadTextsModal implements OnDestroy, OnInit { if (this.readTextsMode) { // Get publication title - this.headService.getCurrentPageTitle().subscribe((pubTitle: string) => { - this.publicationTitle = pubTitle?.slice(-1) === '.' - ? pubTitle.slice(0, -1) - : pubTitle; - }); + this.pageTitleSubscr = this.headService.getCurrentPageTitle().subscribe( + (pubTitle: string) => { + this.publicationTitle = pubTitle?.slice(-1) === '.' + ? pubTitle.slice(0, -1) + : pubTitle; + } + ); if (this.downloadFormatsEst.length || this.downloadFormatsCom.length) { // Get publication data in order to determine if reading-texts and @@ -214,6 +217,7 @@ export class DownloadTextsModal implements OnDestroy, OnInit { ngOnDestroy() { this.downloadTextSubscription?.unsubscribe(); this.printTextSubscription?.unsubscribe(); + this.pageTitleSubscr?.unsubscribe(); } dismiss() { diff --git a/src/app/dialogs/modals/named-entity/named-entity.modal.ts b/src/app/dialogs/modals/named-entity/named-entity.modal.ts index ba72593..52bc8d4 100644 --- a/src/app/dialogs/modals/named-entity/named-entity.modal.ts +++ b/src/app/dialogs/modals/named-entity/named-entity.modal.ts @@ -1,4 +1,4 @@ -import { Component, Input, OnInit } from '@angular/core'; +import { Component, Input, OnDestroy, OnInit } from '@angular/core'; import { AsyncPipe, NgFor, NgIf } from '@angular/common'; import { NavigationEnd, Router, RouterModule } from '@angular/router'; import { IonicModule, ModalController } from '@ionic/angular'; @@ -18,7 +18,7 @@ import { isEmptyObject } from '@utility-functions'; styleUrls: ['./named-entity.modal.scss'], imports: [AsyncPipe, NgFor, NgIf, IonicModule, OccurrencesAccordionComponent, RouterModule] }) -export class NamedEntityModal implements OnInit { +export class NamedEntityModal implements OnDestroy, OnInit { @Input() id: string = ''; @Input() type: string = ''; @@ -67,6 +67,10 @@ export class NamedEntityModal implements OnInit { }); } + ngOnDestroy() { + this.routerEventsSubscription?.unsubscribe(); + } + ionViewWillLeave() { this.routerEventsSubscription?.unsubscribe(); } diff --git a/src/app/pages/ebook/ebook.page.ts b/src/app/pages/ebook/ebook.page.ts index 617f362..72e490d 100644 --- a/src/app/pages/ebook/ebook.page.ts +++ b/src/app/pages/ebook/ebook.page.ts @@ -1,5 +1,6 @@ -import { Component, OnInit } from '@angular/core'; +import { Component, OnDestroy, OnInit } from '@angular/core'; import { ActivatedRoute } from '@angular/router'; +import { Subscription } from 'rxjs'; import { config } from '@config'; @@ -9,9 +10,10 @@ import { config } from '@config'; templateUrl: './ebook.page.html', styleUrls: ['./ebook.page.scss'], }) -export class EbookPage implements OnInit { +export class EbookPage implements OnDestroy, OnInit { ebookType: string = ''; filename: string = ''; + routeParamsSubscr: Subscription | null = null; title: string = ''; constructor( @@ -19,7 +21,7 @@ export class EbookPage implements OnInit { ) {} ngOnInit() { - this.route.params.subscribe(params => { + this.routeParamsSubscr = this.route.params.subscribe(params => { this.filename = ''; this.ebookType = ''; const availableEbooks: any[] = config.ebooks ?? []; @@ -36,4 +38,8 @@ export class EbookPage implements OnInit { }); } + ngOnDestroy() { + this.routeParamsSubscr?.unsubscribe(); + } + } diff --git a/src/app/services/document-head.service.ts b/src/app/services/document-head.service.ts index 49780c9..c177361 100644 --- a/src/app/services/document-head.service.ts +++ b/src/app/services/document-head.service.ts @@ -10,7 +10,7 @@ import { config } from '@config'; providedIn: 'root', }) export class DocumentHeadService { - private currentPageTitle: BehaviorSubject = new BehaviorSubject(''); + private currentPageTitle$: BehaviorSubject = new BehaviorSubject(''); private currentRouterUrl: string | undefined = undefined; private openGraphTags: any = undefined; private languages: any[] = []; @@ -203,11 +203,11 @@ export class DocumentHeadService { } setCurrentPageTitle(newTitle: string) { - this.currentPageTitle.next(newTitle); + this.currentPageTitle$.next(newTitle); } getCurrentPageTitle(): Observable { - return this.currentPageTitle.asObservable(); + return this.currentPageTitle$.asObservable(); } } diff --git a/src/app/services/view-options.service.ts b/src/app/services/view-options.service.ts index df4a4bc..26e99d7 100644 --- a/src/app/services/view-options.service.ts +++ b/src/app/services/view-options.service.ts @@ -23,7 +23,7 @@ export class ViewOptionsService { }; private epubAlertDismissed: boolean = false; - private textsizeSubject: BehaviorSubject = new BehaviorSubject(Textsize.Small); + private textsizeSubject$: BehaviorSubject = new BehaviorSubject(Textsize.Small); constructor() { const defaultViewOptions: string[] = config.page?.text?.defaultViewOptions ?? []; @@ -35,11 +35,11 @@ export class ViewOptionsService { } getTextsize(): Observable { - return this.textsizeSubject.asObservable(); + return this.textsizeSubject$.asObservable(); } setTextsize(textsize: Textsize) { - this.textsizeSubject.next(textsize); + this.textsizeSubject$.next(textsize); } epubAlertIsDismissed() { From 308186ecc7478f7c684989389d435fdc36489f92 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20K=C3=B6hler?= <74658813+SebastianKohler@users.noreply.github.com> Date: Mon, 19 Feb 2024 10:37:02 +0200 Subject: [PATCH 2/2] chore: release v1.3.1 PR: https://github.com/slsfi/digital-edition-frontend-ng/pull/107 --- CHANGELOG.md | 9 +++++++-- package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5f1e17a..c9ad65e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,9 +8,13 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/), and this ## [Unreleased] + + +## [1.3.1] – 2024-02-19 + ### Fixes -- Memory leak related to BehaviorSubject-subscription in the download-texts modal. Also, as a precation, unsubscribe from all route subscriptions on component destruction. +- Memory leak related to BehaviorSubject-subscription in the download-texts modal. Also, as a precation, unsubscribe from all route subscriptions on component destruction. ([b32dfe4](https://github.com/slsfi/digital-edition-frontend-ng/commit/b32dfe4e74393ecb64aad4f83d415fa60f2f37bb)) @@ -220,7 +224,8 @@ siteLogoDimensions: { -[unreleased]: https://github.com/slsfi/digital-edition-frontend-ng/compare/1.3.0...HEAD +[unreleased]: https://github.com/slsfi/digital-edition-frontend-ng/compare/1.3.1...HEAD +[1.3.1]: https://github.com/slsfi/digital-edition-frontend-ng/compare/1.3.0...1.3.1 [1.3.0]: https://github.com/slsfi/digital-edition-frontend-ng/compare/1.2.3...1.3.0 [1.2.3]: https://github.com/slsfi/digital-edition-frontend-ng/compare/1.2.2...1.2.3 [1.2.2]: https://github.com/slsfi/digital-edition-frontend-ng/compare/1.2.1...1.2.2 diff --git a/package-lock.json b/package-lock.json index 5da7b35..cdd53c7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "sls-digital-edition-frontend", - "version": "1.3.0", + "version": "1.3.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "sls-digital-edition-frontend", - "version": "1.3.0", + "version": "1.3.1", "license": "MIT", "dependencies": { "@angular/animations": "^17.2.1", diff --git a/package.json b/package.json index 75a9004..8a723cc 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "sls-digital-edition-frontend", - "version": "1.3.0", + "version": "1.3.1", "description": "Angular frontend app for the SLS Digital Edition Platform", "homepage": "https://github.com/slsfi/digital-edition-frontend-ng#readme", "license": "MIT",