mirror of
https://github.com/4gray/iptvnator.git
synced 2026-10-11 19:46:16 -08:00
* docs(playback): design recovery recommendations * docs(playback): plan recovery recommendations * refactor(playback): extract diagnostic utilities * feat(playback): define recovery recommendation contracts * feat(playback): rank recovery recommendations * feat(playback): track session recovery attempts * feat(playback): identify content recovery sessions * feat(ui): add ranked playback diagnostic panel * feat(playback): switch temporarily to recommended players * test(playback): cover temporary player recommendation * test(playback): verify recommendation capability guards * docs(playback): document recovery recommendations * fix(playback): keep recovery keys credential-free * fix(playback): remove derived tracking ownership * fix(playback): preserve distinct recovery fallbacks * fix(playback): reset resume for new sources * fix(playback): preserve desktop recovery guidance * docs(playback): clarify recovery policy exceptions * fix(playback): reject stale progress updates * fix(playback): keep protected recovery guidance neutral * test(playback): cover stale progress output * fix(playback): neutralize protected diagnostic copy * fix(playback): harden runtime guidance ownership * fix(playback): stabilize recovery application ownership * fix(ci): classify playback util coverage * fix(e2e): preserve playback fixture bytes
96 lines
3.0 KiB
TypeScript
96 lines
3.0 KiB
TypeScript
import type {
|
|
ExternalPlayerName,
|
|
} from '@iptvnator/shared/interfaces';
|
|
import type {
|
|
InlinePlaybackPlayer,
|
|
PlaybackDiagnostic,
|
|
} from './diagnostics/playback-diagnostics.model';
|
|
|
|
export const PlaybackRecommendationReason = {
|
|
RetryTransientFailure: 'retry-transient-failure',
|
|
RetryUnknownFailure: 'retry-unknown-failure',
|
|
AlternativeSourceAvailable: 'alternative-source-available',
|
|
DifferentEngineFamily: 'different-engine-family',
|
|
ExternalCodecOrContainerSupport: 'external-codec-or-container-support',
|
|
ExternalBrowserAccess: 'external-browser-access',
|
|
CompatibleDrmPath: 'compatible-drm-path',
|
|
} as const;
|
|
|
|
export type PlaybackRecommendationReason =
|
|
(typeof PlaybackRecommendationReason)[keyof typeof PlaybackRecommendationReason];
|
|
|
|
export type PlaybackRecommendationPriority = 'primary' | 'secondary';
|
|
|
|
export type PlaybackRecommendationTarget =
|
|
| InlinePlaybackPlayer
|
|
| ExternalPlayerName;
|
|
|
|
export const PlaybackSourceKind = {
|
|
Hls: 'hls',
|
|
MpegTs: 'mpegts',
|
|
Dash: 'dash',
|
|
Native: 'native',
|
|
Unknown: 'unknown',
|
|
} as const;
|
|
|
|
export type PlaybackSourceKind =
|
|
(typeof PlaybackSourceKind)[keyof typeof PlaybackSourceKind];
|
|
|
|
export const PlaybackEngineFamily = {
|
|
Vhs: 'vhs',
|
|
HlsJs: 'hls.js',
|
|
MpegTsJs: 'mpegts.js',
|
|
Shaka: 'shaka',
|
|
NativeMedia: 'native-media',
|
|
} as const;
|
|
|
|
export type PlaybackEngineFamily =
|
|
(typeof PlaybackEngineFamily)[keyof typeof PlaybackEngineFamily];
|
|
|
|
export type PlaybackTargetCapability =
|
|
| {
|
|
readonly kind: 'inline';
|
|
readonly target: InlinePlaybackPlayer;
|
|
readonly available: boolean;
|
|
readonly engineFamily: PlaybackEngineFamily | null;
|
|
}
|
|
| {
|
|
readonly kind: 'external';
|
|
readonly target: ExternalPlayerName;
|
|
readonly available: boolean;
|
|
};
|
|
|
|
export interface PlaybackRecommendationSourceContext {
|
|
readonly kind: PlaybackSourceKind;
|
|
readonly isLive: boolean;
|
|
readonly drm: 'none' | 'untransferable';
|
|
readonly externalTransferable: boolean;
|
|
}
|
|
|
|
export interface PlaybackRecommendationContext {
|
|
readonly diagnostic: PlaybackDiagnostic;
|
|
readonly activeTarget: PlaybackRecommendationTarget;
|
|
readonly attemptedTargets: ReadonlySet<PlaybackRecommendationTarget>;
|
|
readonly targetCapabilities: readonly PlaybackTargetCapability[];
|
|
readonly source: PlaybackRecommendationSourceContext;
|
|
readonly alternativeSourceCount: number;
|
|
}
|
|
|
|
export type PlaybackRecommendation =
|
|
| {
|
|
readonly action: 'retry';
|
|
readonly reason: PlaybackRecommendationReason;
|
|
readonly priority: PlaybackRecommendationPriority;
|
|
}
|
|
| {
|
|
readonly action: 'alternative-source';
|
|
readonly reason: PlaybackRecommendationReason;
|
|
readonly priority: PlaybackRecommendationPriority;
|
|
}
|
|
| {
|
|
readonly action: 'player';
|
|
readonly target: PlaybackRecommendationTarget;
|
|
readonly reason: PlaybackRecommendationReason;
|
|
readonly priority: PlaybackRecommendationPriority;
|
|
};
|