diff --git a/libs/playlist/shared/ui/src/lib/playlist-switcher/playlist-switcher-panel.component.spec.ts b/libs/playlist/shared/ui/src/lib/playlist-switcher/playlist-switcher-panel.component.spec.ts index d001c9838..736c7775a 100644 --- a/libs/playlist/shared/ui/src/lib/playlist-switcher/playlist-switcher-panel.component.spec.ts +++ b/libs/playlist/shared/ui/src/lib/playlist-switcher/playlist-switcher-panel.component.spec.ts @@ -194,6 +194,19 @@ describe('PlaylistSwitcherPanelComponent', () => { expect(closed).toHaveBeenCalled(); }); + it('scrolls a new search back to its first match at the top', () => { + const list = (fixture.nativeElement as HTMLElement).querySelector( + '.switcher__list' + ) as HTMLElement; + list.scrollTop = 120; + type('a'); + expect(list.scrollTop).toBe(0); + + list.scrollTop = 120; + component.setType('xtream'); + expect(list.scrollTop).toBe(0); + }); + it('moves through options whose IDs a selector would misread', () => { const restored = { ...ALPHA, _id: 'odd:id.one', title: 'Aardvark' }; playlists.set([restored, BRAVO]); diff --git a/libs/playlist/shared/ui/src/lib/playlist-switcher/playlist-switcher-panel.component.ts b/libs/playlist/shared/ui/src/lib/playlist-switcher/playlist-switcher-panel.component.ts index f67f620de..4e41812c4 100644 --- a/libs/playlist/shared/ui/src/lib/playlist-switcher/playlist-switcher-panel.component.ts +++ b/libs/playlist/shared/ui/src/lib/playlist-switcher/playlist-switcher-panel.component.ts @@ -205,11 +205,21 @@ export class PlaylistSwitcherPanelComponent { setQuery(value: string): void { this.query.set(value); + this.scrollToTop(); } setType(type: SourcesTypeFilter): void { this.type.set(type); writeSwitcherType(type); + this.scrollToTop(); + } + + /** + * A new search or type highlights the first match, at the top of the + * list: a list scrolled down for the previous one would hide it. + */ + private scrollToTop(): void { + this.list().nativeElement.scrollTop = 0; } onSearchKeydown(event: KeyboardEvent): void { diff --git a/libs/portal/shared/data-access/src/lib/source-status.service.spec.ts b/libs/portal/shared/data-access/src/lib/source-status.service.spec.ts index 085319db3..213295db4 100644 --- a/libs/portal/shared/data-access/src/lib/source-status.service.spec.ts +++ b/libs/portal/shared/data-access/src/lib/source-status.service.spec.ts @@ -178,6 +178,20 @@ describe('SourceStatusService', () => { expect(service.statusOf(m3u)?.pending).toBe(true); }); + it('says why an inconclusive check is inconclusive', () => { + snapshots.set('m', { + state: 'unavailable', + reason: 'paused', + confirmedInactive: false, + checkedAt: 700, + }); + expect(create(true).statusOf(m3u)).toEqual({ + reachability: 'unknown', + reason: 'paused', + checkedAt: 700, + }); + }); + it('reports an unchecked source as unknown', () => { expect(create(true).statusOf(m3u)).toEqual({ reachability: 'unknown', diff --git a/libs/portal/shared/data-access/src/lib/source-status.service.ts b/libs/portal/shared/data-access/src/lib/source-status.service.ts index b6039757d..a71cfd38d 100644 --- a/libs/portal/shared/data-access/src/lib/source-status.service.ts +++ b/libs/portal/shared/data-access/src/lib/source-status.service.ts @@ -116,7 +116,14 @@ export class SourceStatusService { reason: kept.reason, }; } - return { reachability }; + // An inconclusive check still says why ("Connection checks paused"). + return reachability === 'checking' || !live + ? { reachability } + : { + reachability, + reason: live.reason, + checkedAt: live.checkedAt || undefined, + }; } /** A passive check: cached results count; the signal cancels it. */