feat(stalker): add account info dialog for Stalker portals

Xtream playlists have had an account-info dialog for a while; Stalker
portals stored the same facts (login, expiry, tariff, status captured at
import) as dead weight in the database and showed them nowhere.

Add StalkerAccountInfoComponent mirroring the Xtream dialog's visual
language: status pill, days-left/tariff/MAC hero stats, account and
portal panels. Data is cached-first — the import-time snapshot renders
instantly with a "Saved data" badge, then StalkerAccountInfoService
refreshes it: full /stalker_portal/ installations re-run
handshake+get_profile, portal.php panels are queried best-effort via
account_info/get_main_info. A failed refresh keeps the cached snapshot;
no data at all shows a retry-able error state.

Entry points are unified behind shared portal-account predicates
(isXtreamAccountPlaylist / isStalkerAccountPlaylist in shared/interfaces)
so both portal types get the same set: header playlist switcher (bottom
section + new per-row ⋮ Account info item), dashboard source card ⋮ menu,
and the command palette (now visible on stalker routes with its own
description). The header service picks the dialog by playlist type; the
per-row path works for non-active playlists and skips the session-scoped
stream counts.

Also adds the missing top-level LOADING/RETRY i18n keys the Xtream dialog
already referenced (they rendered as raw keys), a get_main_info handler
in the stalker mock server, and STALKER.ACCOUNT_INFO translations for all
19 locales.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
4grayandClaude Opus 5 committed 2026-08-02 09:16:00 +02:00
1 parent e86e988e72
commit 582785ee8e
52 files changed
+2394 -68

No files matched your search

+2
View File
@@ -25,6 +25,7 @@ export * from './lib/playback-position.interface';
export * from './lib/playlist-auto-update.interface';
export * from './lib/playlist-backup.interface';
export * from './lib/playlist-meta.type';
export * from './lib/portal-account-playlist.utils';
export * from './lib/preload-performance-marker.interface';
export * from './lib/playlist-recently-viewed.interface';
export * from './lib/playlist-recently-viewed.utils';
@@ -44,6 +45,7 @@ export * from './lib/stream-format.enum';
export * from './lib/catalog-title-match.interface';
export * from './lib/theme.enum';
export * from './lib/season-marker.util';
export * from './lib/stalker-account-info-dialog-data.interface';
export * from './lib/title-normalization.util';
export * from './lib/tmdb.interface';
export * from './lib/vod-source.interface';
@@ -0,0 +1,40 @@
import { PlaylistMeta } from './playlist-meta.type';
/**
* A playlist backed by an Xtream Codes account — the only kind the Xtream
* account-info dialog can query (`player_api.php` needs all three fields).
*/
export function isXtreamAccountPlaylist(
playlist: PlaylistMeta
): playlist is PlaylistMeta & {
serverUrl: string;
username: string;
password: string;
} {
return Boolean(
playlist.serverUrl && playlist.username && playlist.password
);
}
/**
* A playlist backed by a Stalker/Ministra portal. Portal URL + MAC address
* are what every Stalker request is keyed on, so together they identify an
* account the Stalker account-info dialog can describe.
*/
export function isStalkerAccountPlaylist(
playlist: PlaylistMeta
): playlist is PlaylistMeta & {
portalUrl: string;
macAddress: string;
} {
return Boolean(playlist.portalUrl && playlist.macAddress);
}
/**
* Any playlist for which an account-info dialog exists.
*/
export function isPortalAccountPlaylist(playlist: PlaylistMeta): boolean {
return (
isXtreamAccountPlaylist(playlist) || isStalkerAccountPlaylist(playlist)
);
}
@@ -0,0 +1,11 @@
import { PlaylistMeta } from './playlist-meta.type';
/**
* Dialog input for the Stalker account-info dialog. The meta row carries the
* portal URL, MAC address, and device identity needed for a fresh portal
* query; the cached `stalkerAccountInfo` snapshot lives only in the full
* playlist payload, so the dialog loads it by id.
*/
export interface StalkerAccountInfoDialogData {
playlist: PlaylistMeta;
}