From fb293ea23ddc01774d54ea1929b4141367527c37 Mon Sep 17 00:00:00 2001 From: 4gray Date: Thu, 1 Oct 2026 07:04:33 +0200 Subject: [PATCH] fix(ui): one provider icon per playlist row, imperative Korean remove label A restored Stalker or Xtream playlist can also carry a URL, and the row's independent checks then showed the M3U URL icon next to the provider icon. The row now switches on resolvePlaylistSourceIconKey(), the precedence every other surface uses, so each source shows exactly one icon. HOME.PLAYLISTS.REMOVE now names the confirm button and the row's delete tooltip; in Korean it read "the playlist has been removed". It now says "remove playlist", like every other locale. Co-Authored-By: Claude Opus 5.5 --- apps/web/src/assets/i18n/ko.json | 2 +- .../playlist-item.component.html | 111 +++++++++--------- .../playlist-item.component.spec.ts | 36 ++++++ .../playlist-item/playlist-item.component.ts | 6 + 4 files changed, 98 insertions(+), 57 deletions(-) diff --git a/apps/web/src/assets/i18n/ko.json b/apps/web/src/assets/i18n/ko.json index 9b4f72484..a6450e937 100644 --- a/apps/web/src/assets/i18n/ko.json +++ b/apps/web/src/assets/i18n/ko.json @@ -65,7 +65,7 @@ "CHANNELS": "채널", "ADDED": "추가되었습니다", "SHOW_DETAILS": "재생 목록 세부 정보 표시", - "REMOVE": "재생 목록이 제거되었습니다", + "REMOVE": "재생 목록 제거", "SEARCH_PLAYLISTS": "제목으로 재생목록 검색", "INFO_DIALOG": { "PLAYLIST_DETAILS": "재생 목록 세부 사항", diff --git a/libs/playlist/shared/ui/src/lib/recent-playlists/playlist-item/playlist-item.component.html b/libs/playlist/shared/ui/src/lib/recent-playlists/playlist-item/playlist-item.component.html index bc7df3ab5..2b30109bd 100644 --- a/libs/playlist/shared/ui/src/lib/recent-playlists/playlist-item/playlist-item.component.html +++ b/libs/playlist/shared/ui/src/lib/recent-playlists/playlist-item/playlist-item.component.html @@ -17,69 +17,68 @@ [enabled]="!isBusy()" /> } - @if (item.url) { -
+ + @switch (sourceIconKey) { + @case ('stalker') { {{ sourceIcons['m3u-url'] }}{{ sourceIcons.stalker }} - @if (item.autoRefresh) { + } + @case ('xtream') { +
autorenew{{ sourceIcons.xtream }} - } -
- } - @if (!item.url && !item.serverUrl && !item.macAddress) { -
- {{ sourceIcons['m3u-local'] }} - @if (item.autoRefresh) { - autorenew - } -
- } - @if (item.serverUrl) { -
- {{ sourceIcons.xtream }} - @if (!runtime.supportsSourceHealth) { - - } -
- } - @if (item.macAddress) { - {{ sourceIcons.stalker }} + @if (!runtime.supportsSourceHealth) { + + } +
+ } + @default { +
+ @if (sourceIconKey === 'm3u-url') { + {{ sourceIcons['m3u-url'] }} + } @else { + {{ sourceIcons['m3u-local'] }} + } + @if (item.autoRefresh) { + autorenew + } +
+ } }
diff --git a/libs/playlist/shared/ui/src/lib/recent-playlists/playlist-item/playlist-item.component.spec.ts b/libs/playlist/shared/ui/src/lib/recent-playlists/playlist-item/playlist-item.component.spec.ts index f56c4b44f..2ed168c99 100644 --- a/libs/playlist/shared/ui/src/lib/recent-playlists/playlist-item/playlist-item.component.spec.ts +++ b/libs/playlist/shared/ui/src/lib/recent-playlists/playlist-item/playlist-item.component.spec.ts @@ -221,4 +221,40 @@ describe('PlaylistItemComponent', () => { ).toContain('42%'); expect(nativeElement.querySelector('.cancel-btn')).not.toBeNull(); }); + + it.each([ + [ + { macAddress: '00:1A:79:00:00:01', url: 'http://portal.test' }, + 'cast', + ], + [ + { serverUrl: 'http://xtream.test', url: 'http://xtream.test' }, + 'cloud', + ], + [{ url: 'http://list.test/playlist.m3u' }, 'link'], + [{}, 'description'], + ])( + 'shows one provider icon for %o, with the shared precedence', + (source, icon) => { + fixture.destroy(); + fixture = TestBed.createComponent(PlaylistItemComponent); + fixture.componentInstance.item = { + title: 'Source', + _id: 'source', + count: 10, + importDate: Date.now().toString(), + autoRefresh: false, + ...source, + }; + fixture.detectChanges(); + + const icons = Array.from( + (fixture.nativeElement as HTMLElement).querySelectorAll( + '.upload-type-icon' + ), + (element) => element.textContent?.trim() + ); + expect(icons).toEqual([icon]); + } + ); }); diff --git a/libs/playlist/shared/ui/src/lib/recent-playlists/playlist-item/playlist-item.component.ts b/libs/playlist/shared/ui/src/lib/recent-playlists/playlist-item/playlist-item.component.ts index a7fbd73f3..77a13aef4 100644 --- a/libs/playlist/shared/ui/src/lib/recent-playlists/playlist-item/playlist-item.component.ts +++ b/libs/playlist/shared/ui/src/lib/recent-playlists/playlist-item/playlist-item.component.ts @@ -1,6 +1,8 @@ import { Injector } from '@angular/core'; import { SourceHealthService } from '@iptvnator/portal/shared/data-access'; import { + PlaylistSourceIconKey, + resolvePlaylistSourceIconKey, SOURCE_TYPE_ICONS, sourceHealthType, } from '@iptvnator/shared/interfaces'; @@ -72,6 +74,10 @@ export class PlaylistItemComponent implements OnInit { private readonly portalStatusService = inject(PortalStatusService); readonly runtime = inject(RuntimeCapabilitiesService); readonly sourceIcons = SOURCE_TYPE_ICONS; + + get sourceIconKey(): PlaylistSourceIconKey { + return resolvePlaylistSourceIconKey(this.item); + } private readonly translate = inject(TranslateService); private readonly languageTick = toSignal( this.translate.onLangChange.pipe(startWith(null)),