mirror of
https://github.com/4gray/iptvnator.git
synced 2026-10-11 02:46:16 -08:00
Merge master, dedupe the kept copy, and retire superseded switches
Master had moved ten commits ahead. Two conflicts, both resolved without losing either side: the `XTREAM_PROBE_URL` handler this PR extracted into `events/stream-probe.ts` stays extracted (master added performance capture nearby but never touched that handler), and the mock-server scenario table takes the union of master's `performance` row and this branch's `multisrc` pair. Two findings fixed alongside it. Pinning the copy the route is already on makes discovery return that very row, so prepending the current source listed one stream twice — a phantom copy in the grouping and a chip that counted it. And handing the "playing" badge back to the route row left an in-flight switch valid, so a slow resolution could arrive afterwards and replace the playback the user had just started with Play, Resume or Restart. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
commit
9f0a8b4f19
385 files changed
+58306
-2264
No files matched your search
@@ -19,6 +19,7 @@ export * from './lib/ipc-commands';
|
||||
export * from './lib/language.enum';
|
||||
export * from './lib/m3u-favorite-channel.interface';
|
||||
export * from './lib/parsed-playlist.interface';
|
||||
export * from './lib/performance-phase.interface';
|
||||
export * from './lib/playback-position.interface';
|
||||
export * from './lib/playlist-auto-update.interface';
|
||||
export * from './lib/playlist-backup.interface';
|
||||
@@ -54,6 +55,7 @@ export * from './lib/xtream-response.interface';
|
||||
export * from './lib/xtream-portal.utils';
|
||||
export * from './lib/xtream-restore-state.util';
|
||||
export * from './lib/xtream-recently-added.utils';
|
||||
export * from './lib/xtream-performance-marker.interface';
|
||||
export * from './lib/xtream-serie-details.interface';
|
||||
export * from './lib/xtream-serie-item.interface';
|
||||
export * from './lib/xtream-vod-details.interface';
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
export const PERFORMANCE_PHASE_BOUNDARY = {
|
||||
END: 'end',
|
||||
START: 'start',
|
||||
} as const;
|
||||
|
||||
export type PerformancePhaseBoundary =
|
||||
(typeof PERFORMANCE_PHASE_BOUNDARY)[keyof typeof PERFORMANCE_PHASE_BOUNDARY];
|
||||
|
||||
export const M3U_IMPORT_PERFORMANCE_PHASE_EVENT_CHANNEL =
|
||||
'IPTVNATOR_M3U_IMPORT_PERFORMANCE_PHASE_EVENT';
|
||||
|
||||
export const M3U_IMPORT_PERFORMANCE_PHASE = {
|
||||
DATA_ACQUIRE: 'data.acquire',
|
||||
NORMALIZE: 'normalize',
|
||||
PARSE_M3U: 'parse.m3u',
|
||||
} as const;
|
||||
|
||||
export type M3uImportPerformancePhase =
|
||||
(typeof M3U_IMPORT_PERFORMANCE_PHASE)[keyof typeof M3U_IMPORT_PERFORMANCE_PHASE];
|
||||
|
||||
export const APP_PLAYLIST_UPSERT_PERFORMANCE_PHASE = {
|
||||
SERIALIZE_PLAYLIST: 'serialize.playlist',
|
||||
SQLITE_WRITE: 'sqlite.write',
|
||||
} as const;
|
||||
|
||||
export type AppPlaylistUpsertPerformancePhase =
|
||||
(typeof APP_PLAYLIST_UPSERT_PERFORMANCE_PHASE)[keyof typeof APP_PLAYLIST_UPSERT_PERFORMANCE_PHASE];
|
||||
|
||||
export const APP_PLAYLIST_GET_PERFORMANCE_PHASE = {
|
||||
DESERIALIZE_PLAYLIST: 'deserialize.playlist',
|
||||
SQLITE_READ: 'sqlite.read',
|
||||
} as const;
|
||||
|
||||
export type AppPlaylistGetPerformancePhase =
|
||||
(typeof APP_PLAYLIST_GET_PERFORMANCE_PHASE)[keyof typeof APP_PLAYLIST_GET_PERFORMANCE_PHASE];
|
||||
|
||||
export type AppPlaylistPerformancePhase =
|
||||
AppPlaylistGetPerformancePhase | AppPlaylistUpsertPerformancePhase;
|
||||
|
||||
export const XTREAM_DATABASE_PERFORMANCE_PHASE = {
|
||||
NORMALIZE_CATEGORIES: 'normalize.categories',
|
||||
NORMALIZE_CONTENT: 'normalize.content',
|
||||
NORMALIZE_SEARCH_RANK: 'normalize.search-rank',
|
||||
SQLITE_CATEGORIES_READ: 'sqlite.categories.read',
|
||||
SQLITE_CATEGORIES_WRITE_TRANSACTIONS:
|
||||
'sqlite.categories.write-transactions',
|
||||
SQLITE_CONTENT_CATEGORY_MAP_READ: 'sqlite.content.category-map-read',
|
||||
SQLITE_CONTENT_READ: 'sqlite.content.read',
|
||||
SQLITE_CONTENT_WRITE_TRANSACTIONS: 'sqlite.content.write-transactions',
|
||||
SQLITE_PLAYLIST_DELETE_COLLECT_IDS: 'sqlite.playlist-delete.collect-ids',
|
||||
SQLITE_PLAYLIST_DELETE_WRITE_TRANSACTIONS:
|
||||
'sqlite.playlist-delete.write-transactions',
|
||||
SQLITE_SEARCH_QUERY: 'sqlite.search.query',
|
||||
SQLITE_XTREAM_CACHE_CLEAR_WRITE_TRANSACTIONS:
|
||||
'sqlite.xtream-cache-clear.write-transactions',
|
||||
SQLITE_XTREAM_DELETE_COLLECT_USER_DATA:
|
||||
'sqlite.xtream-delete.collect-user-data',
|
||||
SQLITE_XTREAM_DELETE_WRITE_TRANSACTIONS:
|
||||
'sqlite.xtream-delete.write-transactions',
|
||||
} as const;
|
||||
|
||||
export type XtreamDatabasePerformancePhase =
|
||||
(typeof XTREAM_DATABASE_PERFORMANCE_PHASE)[keyof typeof XTREAM_DATABASE_PERFORMANCE_PHASE];
|
||||
|
||||
export type DatabaseWorkerPerformancePhase =
|
||||
AppPlaylistPerformancePhase | XtreamDatabasePerformancePhase;
|
||||
|
||||
export interface PerformancePhaseMetadata {
|
||||
readonly byteCount?: number;
|
||||
readonly itemCount?: number;
|
||||
}
|
||||
|
||||
export interface PerformancePhaseEvent<TPhase extends string = string> {
|
||||
readonly boundary: PerformancePhaseBoundary;
|
||||
readonly durationMs: number | null;
|
||||
readonly epochMs: number;
|
||||
readonly metadata?: PerformancePhaseMetadata;
|
||||
readonly phase: TPhase;
|
||||
readonly requestId: string;
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
import { XtreamCodeActions } from './xtream-code-actions';
|
||||
|
||||
export const XTREAM_MAIN_PERFORMANCE_PHASE_EVENT_CHANNEL =
|
||||
'IPTVNATOR_XTREAM_MAIN_PERFORMANCE_PHASE_EVENT';
|
||||
|
||||
export const XTREAM_MAIN_PERFORMANCE_PHASE = {
|
||||
CANCEL_SESSION: 'xtream.cancel-session',
|
||||
JSON_TRANSFORM: 'xtream.json.transform',
|
||||
NETWORK_TOTAL: 'xtream.network.total',
|
||||
RESPONSE_READY: 'xtream.response.ready',
|
||||
} as const;
|
||||
|
||||
export type XtreamMainPerformancePhase =
|
||||
(typeof XTREAM_MAIN_PERFORMANCE_PHASE)[keyof typeof XTREAM_MAIN_PERFORMANCE_PHASE];
|
||||
|
||||
export const XTREAM_PRELOAD_PERFORMANCE_MARKER_CHANNEL =
|
||||
'IPTVNATOR_XTREAM_PERF_CAPTURE_MARKER';
|
||||
|
||||
export const XTREAM_PRELOAD_PERFORMANCE_SCHEMA_VERSION = 1 as const;
|
||||
|
||||
export const XTREAM_PRELOAD_PERFORMANCE_METHOD = {
|
||||
DB_CANCEL_OPERATION: 'dbCancelOperation',
|
||||
DB_DELETE_PLAYLIST: 'dbDeletePlaylist',
|
||||
DB_DELETE_XTREAM_CONTENT: 'dbDeleteXtreamContent',
|
||||
DB_GET_CATEGORIES: 'dbGetCategories',
|
||||
DB_GET_CONTENT: 'dbGetContent',
|
||||
DB_GLOBAL_SEARCH: 'dbGlobalSearch',
|
||||
DB_RESTORE_XTREAM_USER_DATA: 'dbRestoreXtreamUserData',
|
||||
DB_SAVE_CATEGORIES: 'dbSaveCategories',
|
||||
DB_SAVE_CONTENT: 'dbSaveContent',
|
||||
DB_SEARCH_CONTENT: 'dbSearchContent',
|
||||
XTREAM_CANCEL_SESSION: 'xtreamCancelSession',
|
||||
XTREAM_REQUEST: 'xtreamRequest',
|
||||
} as const;
|
||||
|
||||
export type XtreamPreloadPerformanceMethod =
|
||||
(typeof XTREAM_PRELOAD_PERFORMANCE_METHOD)[keyof typeof XTREAM_PRELOAD_PERFORMANCE_METHOD];
|
||||
|
||||
export type XtreamPreloadPerformanceBoundary = 'start' | 'end';
|
||||
export type XtreamPreloadPerformanceOutcome = 'success' | 'error' | null;
|
||||
export type XtreamPreloadPerformanceCategoryType = 'live' | 'movies' | 'series';
|
||||
export type XtreamPreloadPerformanceContentType = 'live' | 'movie' | 'series';
|
||||
|
||||
export interface XtreamPreloadPerformanceMarker {
|
||||
schemaVersion: typeof XTREAM_PRELOAD_PERFORMANCE_SCHEMA_VERSION;
|
||||
sourceEpochMs: number;
|
||||
ipcCallId: number;
|
||||
method: XtreamPreloadPerformanceMethod;
|
||||
boundary: XtreamPreloadPerformanceBoundary;
|
||||
outcome: XtreamPreloadPerformanceOutcome;
|
||||
playlistId: string | null;
|
||||
operationId: string | null;
|
||||
sessionId: string | null;
|
||||
action: XtreamCodeActions | null;
|
||||
categoryType: XtreamPreloadPerformanceCategoryType | null;
|
||||
contentType: XtreamPreloadPerformanceContentType | null;
|
||||
itemCount: number | null;
|
||||
}
|
||||
Reference in new issue
Block a user