From 29afbd07df5e8a2594f129fe1c6a745caa888571 Mon Sep 17 00:00:00 2001 From: Noel Light-Hilary Date: Wed, 27 Nov 2024 14:37:25 +0000 Subject: [PATCH 1/5] =?UTF-8?q?DON-1092=20=E2=80=93=20fix=20campaign=20car?= =?UTF-8?q?d=20grid=20input=20focus=20breaking=20Safari=20scroll=20positio?= =?UTF-8?q?ns?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package-lock.json | 16 +++++++-------- package.json | 4 ++-- src/app/explore/explore.component.ts | 20 +++++++++++++++++-- .../meta-campaign/meta-campaign.component.ts | 11 ++++++++++ 4 files changed, 39 insertions(+), 12 deletions(-) diff --git a/package-lock.json b/package-lock.json index f11504606..1d0bba38c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -21,8 +21,8 @@ "@angular/platform-server": "^18.2.8", "@angular/router": "^18.2.8", "@angular/ssr": "^18.2.8", - "@biggive/components": "^202411151222.0.0", - "@biggive/components-angular": "^202411151222.0.0", + "@biggive/components": "^202411271427.0.0", + "@biggive/components-angular": "^202411271427.0.0", "@fortawesome/angular-fontawesome": "~0.15.0", "@fortawesome/free-brands-svg-icons": "^6.6.0", "@fortawesome/free-solid-svg-icons": "^6.6.0", @@ -2930,9 +2930,9 @@ } }, "node_modules/@biggive/components": { - "version": "202411151222.0.0", - "resolved": "https://registry.npmjs.org/@biggive/components/-/components-202411151222.0.0.tgz", - "integrity": "sha512-Kzoow0iumBQjgzvmLz7CGqLZRUl7kRpq+Dj65Zf9fqX4aYYHpuqVu4q+MK2+LKTAq17eo5sMo/zHWOD0XBMgQQ==", + "version": "202411271427.0.0", + "resolved": "https://registry.npmjs.org/@biggive/components/-/components-202411271427.0.0.tgz", + "integrity": "sha512-W6EqGHmO0fXYxMm2myNg7aYGXGSh/Odeit6YC56WSyJ1HJ8jSsuA7MkzWkDmmZ4P4gJ71SyV9mKiqz+44QWvzw==", "license": "MIT", "dependencies": { "@fortawesome/fontawesome-svg-core": "^6.6.0", @@ -2945,9 +2945,9 @@ } }, "node_modules/@biggive/components-angular": { - "version": "202411151222.0.0", - "resolved": "https://registry.npmjs.org/@biggive/components-angular/-/components-angular-202411151222.0.0.tgz", - "integrity": "sha512-grDQf0aUGB6ZHGQpy7pftje7x+feYjvCKlXpkgKR6BWL6b89CjWlMLOnjkfwjjXge6Mnkjom16kHhA4MFjyGNQ==", + "version": "202411271427.0.0", + "resolved": "https://registry.npmjs.org/@biggive/components-angular/-/components-angular-202411271427.0.0.tgz", + "integrity": "sha512-ccr4Yue1nsLtbVqS5SXbPhM4BCFIKWkX/2tsuosVfi4YVxn7oB0QXK+CyyzI1G+ltTWqqgXYxSvpWiHBZNvn0w==", "dependencies": { "tslib": "^2.6.2" }, diff --git a/package.json b/package.json index 4bc9fb3b7..c3672e183 100644 --- a/package.json +++ b/package.json @@ -44,8 +44,8 @@ "@angular/platform-server": "^18.2.8", "@angular/router": "^18.2.8", "@angular/ssr": "^18.2.8", - "@biggive/components": "^202411151222.0.0", - "@biggive/components-angular": "^202411151222.0.0", + "@biggive/components": "^202411271427.0.0", + "@biggive/components-angular": "^202411271427.0.0", "@fortawesome/angular-fontawesome": "~0.15.0", "@fortawesome/free-brands-svg-icons": "^6.6.0", "@fortawesome/free-solid-svg-icons": "^6.6.0", diff --git a/src/app/explore/explore.component.ts b/src/app/explore/explore.component.ts index 09eb84932..32f723650 100644 --- a/src/app/explore/explore.component.ts +++ b/src/app/explore/explore.component.ts @@ -1,6 +1,7 @@ -import {DatePipe, isPlatformBrowser} from '@angular/common'; -import {Component, HostListener, Inject, OnDestroy, OnInit, PLATFORM_ID} from '@angular/core'; +import {DatePipe, isPlatformBrowser, ViewportScroller} from '@angular/common'; +import {Component, HostListener, Inject, OnDestroy, OnInit, PLATFORM_ID, ViewChild} from '@angular/core'; import {ActivatedRoute, Router} from '@angular/router'; +import { BiggiveCampaignCardFilterGrid } from '@biggive/components-angular'; import {skip, Subscription} from 'rxjs'; import {currencyPipeDigitsInfo} from '../../environments/common'; @@ -19,15 +20,19 @@ import {HighlightCard} from "../highlight-cards/HighlightCard"; providers: [DatePipe] }) export class ExploreComponent implements OnDestroy, OnInit { + @ViewChild(BiggiveCampaignCardFilterGrid) cardGrid: BiggiveCampaignCardFilterGrid; + campaigns: CampaignSummary[]; currencyPipeDigitsInfo = currencyPipeDigitsInfo; loading = false; // Server render gets initial result set; set true when filters change. /** Whether any non-default search logic besides an order change has been applied. */ searched = false; + private blurredSinceLastMajorScroll = false; private offset = 0; private routeParamSubscription: Subscription; private searchServiceSubscription: Subscription; + private smallestSignificantScrollPx = 250; beneficiaryOptions: string[] = []; categoryOptions: string[] = []; @@ -47,6 +52,7 @@ export class ExploreComponent implements OnDestroy, OnInit { private route: ActivatedRoute, private router: Router, private pageMeta: PageMetaService, + private scroller: ViewportScroller, public searchService: SearchService, @Inject(PLATFORM_ID) private platformId: Object, ) {} @@ -124,6 +130,16 @@ export class ExploreComponent implements OnDestroy, OnInit { } onScroll() { + if (this.scroller.getScrollPosition()[1] < this.smallestSignificantScrollPx) { + this.blurredSinceLastMajorScroll = false; + return; + } + + if (!this.blurredSinceLastMajorScroll) { + this.cardGrid && this.cardGrid.unfocusInputs(); + this.blurredSinceLastMajorScroll = true; + } + if (this.moreMightExist()) { this.more(); } diff --git a/src/app/meta-campaign/meta-campaign.component.ts b/src/app/meta-campaign/meta-campaign.component.ts index b01b3d843..9f7f190bc 100644 --- a/src/app/meta-campaign/meta-campaign.component.ts +++ b/src/app/meta-campaign/meta-campaign.component.ts @@ -11,8 +11,10 @@ import { PLATFORM_ID, StateKey, TransferState, + ViewChild, } from '@angular/core'; import { ActivatedRoute, Router, NavigationEnd, NavigationStart } from '@angular/router'; +import { BiggiveCampaignCardFilterGrid } from '@biggive/components-angular'; import {SESSION_STORAGE, StorageService} from 'ngx-webstorage-service'; import {skip, Subscription} from 'rxjs'; @@ -46,6 +48,8 @@ const endPipeToken = 'timeLeftToEndPipe'; ], }) export class MetaCampaignComponent implements AfterViewChecked, OnDestroy, OnInit { + @ViewChild(BiggiveCampaignCardFilterGrid) cardGrid: BiggiveCampaignCardFilterGrid; + // Campaign ID may be passed instead @Input({ required: false }) private campaignSlug: string; // Passed only on the fund-filtered view of this page. @@ -63,6 +67,7 @@ export class MetaCampaignComponent implements AfterViewChecked, OnDestroy, OnIni public title: string; // Includes fund info if applicable. private autoScrollTimer: number | undefined; // State update setTimeout reference, for client side scroll to previous position. + private blurredSinceLastMajorScroll = false; private campaignId: string; private offset = 0; private routeChangeListener: Subscription; @@ -203,6 +208,7 @@ export class MetaCampaignComponent implements AfterViewChecked, OnDestroy, OnIni onScroll() { if (this.scroller.getScrollPosition()[1] < this.smallestSignificantScrollPx) { + this.blurredSinceLastMajorScroll = false; // On return with internal app nav, automatic position seems to be [0,59] // or so as of Nov '22. So we want only larger scrolls to be picked up as // donor intervention and to turn off auto-scroll + trigger loading of @@ -210,6 +216,11 @@ export class MetaCampaignComponent implements AfterViewChecked, OnDestroy, OnIni return; } + if (!this.blurredSinceLastMajorScroll) { + this.cardGrid && this.cardGrid.unfocusInputs(); + this.blurredSinceLastMajorScroll = true; + } + this.shouldAutoScroll = false; if (this.moreMightExist()) { From d45c3f328b0cfae9e8c590cd82bdd1e037171c32 Mon Sep 17 00:00:00 2001 From: Noel Light-Hilary Date: Wed, 27 Nov 2024 15:37:45 +0000 Subject: [PATCH 2/5] Update src/app/explore/explore.component.ts Co-authored-by: Barney Laurance --- src/app/explore/explore.component.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/explore/explore.component.ts b/src/app/explore/explore.component.ts index 32f723650..01aa4890b 100644 --- a/src/app/explore/explore.component.ts +++ b/src/app/explore/explore.component.ts @@ -32,7 +32,7 @@ export class ExploreComponent implements OnDestroy, OnInit { private offset = 0; private routeParamSubscription: Subscription; private searchServiceSubscription: Subscription; - private smallestSignificantScrollPx = 250; + private readonly smallestSignificantScrollPx = 250; beneficiaryOptions: string[] = []; categoryOptions: string[] = []; From 3e1303bfe99d96d9187cadbf8b989300dacc4e89 Mon Sep 17 00:00:00 2001 From: Noel Light-Hilary Date: Wed, 27 Nov 2024 15:37:58 +0000 Subject: [PATCH 3/5] Update src/app/explore/explore.component.ts Co-authored-by: Barney Laurance --- src/app/explore/explore.component.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/app/explore/explore.component.ts b/src/app/explore/explore.component.ts index 01aa4890b..c6e902ede 100644 --- a/src/app/explore/explore.component.ts +++ b/src/app/explore/explore.component.ts @@ -130,7 +130,8 @@ export class ExploreComponent implements OnDestroy, OnInit { } onScroll() { - if (this.scroller.getScrollPosition()[1] < this.smallestSignificantScrollPx) { + const scrollPositionY = this.scroller.getScrollPosition()[1]; + if (scrollPositionY < this.smallestSignificantScrollPx) { this.blurredSinceLastMajorScroll = false; return; } From 7ec20f25cc7f49fb376f4f523e60d40e975ff918 Mon Sep 17 00:00:00 2001 From: Noel Light-Hilary Date: Wed, 27 Nov 2024 15:39:13 +0000 Subject: [PATCH 4/5] Name `scrollPositionY` in other places we use it too --- src/app/meta-campaign/meta-campaign.component.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/app/meta-campaign/meta-campaign.component.ts b/src/app/meta-campaign/meta-campaign.component.ts index 9f7f190bc..71db1a6c7 100644 --- a/src/app/meta-campaign/meta-campaign.component.ts +++ b/src/app/meta-campaign/meta-campaign.component.ts @@ -207,7 +207,8 @@ export class MetaCampaignComponent implements AfterViewChecked, OnDestroy, OnIni } onScroll() { - if (this.scroller.getScrollPosition()[1] < this.smallestSignificantScrollPx) { + const scrollPositionY = this.scroller.getScrollPosition()[1]; + if (scrollPositionY < this.smallestSignificantScrollPx) { this.blurredSinceLastMajorScroll = false; // On return with internal app nav, automatic position seems to be [0,59] // or so as of Nov '22. So we want only larger scrolls to be picked up as @@ -407,7 +408,8 @@ export class MetaCampaignComponent implements AfterViewChecked, OnDestroy, OnIni private listenForRouteChanges() { this.routeChangeListener = this.router.events.subscribe(event => { if (event instanceof NavigationStart) { - this.navigationService.saveLastScrollY(this.scroller.getScrollPosition()[1]); + const scrollPositionY = this.scroller.getScrollPosition()[1]; + this.navigationService.saveLastScrollY(scrollPositionY); if (isPlatformBrowser(this.platformId) && this.autoScrollTimer) { window.clearTimeout(this.autoScrollTimer); From 848618c58e72d2273e13c2e47fc1e33ab91ea87d Mon Sep 17 00:00:00 2001 From: Noel Light-Hilary Date: Wed, 27 Nov 2024 15:43:40 +0000 Subject: [PATCH 5/5] =?UTF-8?q?DON-1092=20=E2=80=93=20Explain=20`blurredSi?= =?UTF-8?q?nceLastMajorScroll`=20resets?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/explore/explore.component.ts | 1 + src/app/meta-campaign/meta-campaign.component.ts | 2 ++ 2 files changed, 3 insertions(+) diff --git a/src/app/explore/explore.component.ts b/src/app/explore/explore.component.ts index c6e902ede..a5d0fc762 100644 --- a/src/app/explore/explore.component.ts +++ b/src/app/explore/explore.component.ts @@ -132,6 +132,7 @@ export class ExploreComponent implements OnDestroy, OnInit { onScroll() { const scrollPositionY = this.scroller.getScrollPosition()[1]; if (scrollPositionY < this.smallestSignificantScrollPx) { + // If we're now near the top, reset any previous input blurring as it might be helpful to blur again. this.blurredSinceLastMajorScroll = false; return; } diff --git a/src/app/meta-campaign/meta-campaign.component.ts b/src/app/meta-campaign/meta-campaign.component.ts index 71db1a6c7..3562fce1f 100644 --- a/src/app/meta-campaign/meta-campaign.component.ts +++ b/src/app/meta-campaign/meta-campaign.component.ts @@ -209,7 +209,9 @@ export class MetaCampaignComponent implements AfterViewChecked, OnDestroy, OnIni onScroll() { const scrollPositionY = this.scroller.getScrollPosition()[1]; if (scrollPositionY < this.smallestSignificantScrollPx) { + // If we're now near the top, reset any previous input blurring as it might be helpful to blur again. this.blurredSinceLastMajorScroll = false; + // On return with internal app nav, automatic position seems to be [0,59] // or so as of Nov '22. So we want only larger scrolls to be picked up as // donor intervention and to turn off auto-scroll + trigger loading of