From 44de6aad06f914b548b2aaa3fa49e8aa4dc52f44 Mon Sep 17 00:00:00 2001 From: 4gray Date: Sun, 2 Aug 2026 12:23:02 +0200 Subject: [PATCH] fix(dashboard): make expiry-badge labels depend on the language signal MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit sourceCards previously relied on getPlaylistProvider's indirect language read; the translate.instant() labels now read languageTick explicitly (mirroring trendingCards). Also shift the minute tick by one so the interval's first 0 differs from initialValue — the signal equality check was swallowing the first heartbeat, delaying it to two minutes. Co-Authored-By: Claude Fable 5 --- .../workspace-dashboard-rails.component.ts | 21 ++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/libs/workspace/dashboard/feature/src/lib/rails/workspace-dashboard-rails.component.ts b/libs/workspace/dashboard/feature/src/lib/rails/workspace-dashboard-rails.component.ts index 074d9dcf8..810728126 100644 --- a/libs/workspace/dashboard/feature/src/lib/rails/workspace-dashboard-rails.component.ts +++ b/libs/workspace/dashboard/feature/src/lib/rails/workspace-dashboard-rails.component.ts @@ -8,7 +8,7 @@ import { untracked, } from '@angular/core'; import { toObservable, toSignal } from '@angular/core/rxjs-interop'; -import { interval, of, startWith, switchMap } from 'rxjs'; +import { interval, map, of, startWith, switchMap } from 'rxjs'; import { EpgService } from '@iptvnator/epg/data-access'; import { type EpgProgram, @@ -345,14 +345,21 @@ export class WorkspaceDashboardRailsComponent { // Minute heartbeat for the expiry badges: resolveSourceExpiryBadge reads // the wall clock, so without a reactive tick a dashboard left open would - // never cross a day-countdown or expiration boundary. + // never cross a day-countdown or expiration boundary. interval() emits + // 0 first — shifted by one so it differs from initialValue, otherwise + // the signal's equality check would swallow the first tick. private readonly sourceExpiryTick = toSignal( - interval(SOURCE_EXPIRY_TICK_MS).pipe(startWith(0)), + interval(SOURCE_EXPIRY_TICK_MS).pipe(map((tick) => tick + 1)), { initialValue: 0 } ); - readonly sourceCards = computed(() => - this.data.recentPlaylists().map((playlist) => ({ + readonly sourceCards = computed(() => { + // Explicit language dependency for the translate.instant() calls + // below (title fallback, expiry-badge labels). getPlaylistProvider + // also reads the data service's language tick, but the labels must + // not rely on that indirection surviving refactors. + this.languageTick(); + return this.data.recentPlaylists().map((playlist) => ({ id: playlist._id, title: playlist.title || @@ -370,8 +377,8 @@ export class WorkspaceDashboardRailsComponent { this.playlistRefreshAction.canRefresh(playlist) ), expiryBadge: this.buildSourceExpiryBadge(playlist._id), - })) - ); + })); + }); constructor() { // Re-entering the dashboard should pick up any DB-backed recent/favorite