mirror of
https://github.com/4gray/iptvnator.git
synced 2026-10-14 21:26:15 -08:00
refactor: enhance live stream layout with loading state and caching
- Added `XtreamCachedContentScope` type to manage content loading states. - Updated live stream layout to show a loading skeleton when content is being fetched. - Introduced styles for loading content in the live stream layout. - Enhanced unit tests to cover loading states and caching behavior. - Modified `XtreamWorkspaceRouteSession` to handle cached content loading and state management. - Improved handling of optional connection values in playlist data. - Updated workspace context panel to reflect import states and loading conditions. Entire-Checkpoint: c2cea9c530e6
This commit is contained in:
1 parent
a6e886116c
commit
cbedb22698
15 files changed
+1211
-120
No files matched your search
+29
-6
@@ -31,6 +31,7 @@ describe('WorkspaceContextPanelComponent', () => {
|
||||
const xtreamSelectedTypeContentState =
|
||||
signal<XtreamContentLoadState>('loading');
|
||||
const xtreamImportPhase = signal<string | null>('loading-live');
|
||||
const xtreamIsImporting = signal(true);
|
||||
const xtreamIsLoadingCategories = signal(false);
|
||||
|
||||
const xtreamStore = {
|
||||
@@ -44,6 +45,7 @@ describe('WorkspaceContextPanelComponent', () => {
|
||||
selectedTypeCountsReady: computed(
|
||||
() => xtreamSelectedTypeContentState() === 'ready'
|
||||
),
|
||||
isImporting: xtreamIsImporting,
|
||||
currentImportPhase: xtreamImportPhase,
|
||||
isLoadingCategories: xtreamIsLoadingCategories,
|
||||
setSelectedItem: jest.fn(),
|
||||
@@ -75,6 +77,7 @@ describe('WorkspaceContextPanelComponent', () => {
|
||||
xtreamSelectedCategoryId.set(null);
|
||||
xtreamSelectedTypeContentState.set('loading');
|
||||
xtreamImportPhase.set('loading-live');
|
||||
xtreamIsImporting.set(true);
|
||||
xtreamIsLoadingCategories.set(false);
|
||||
xtreamStore.setSelectedItem.mockClear();
|
||||
xtreamStore.setSelectedCategory.mockClear();
|
||||
@@ -137,9 +140,9 @@ describe('WorkspaceContextPanelComponent', () => {
|
||||
const status = fixture.nativeElement.querySelector(
|
||||
'.context-inline-status'
|
||||
) as HTMLElement | null;
|
||||
const manageButton = fixture.nativeElement.querySelector(
|
||||
'.context-header__action'
|
||||
) as HTMLButtonElement | null;
|
||||
const manageButton = Array.from(
|
||||
fixture.nativeElement.querySelectorAll('.context-header__action')
|
||||
).at(-1) as HTMLButtonElement | undefined;
|
||||
|
||||
expect(countPlaceholders).toHaveLength(2);
|
||||
expect(categoryButtons.every((button) => button.disabled)).toBe(true);
|
||||
@@ -156,6 +159,26 @@ describe('WorkspaceContextPanelComponent', () => {
|
||||
expect(router.navigate).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('keeps local xtream loading states quiet when no import is running', () => {
|
||||
fixture.componentRef.setInput('section', 'vod');
|
||||
xtreamIsImporting.set(false);
|
||||
fixture.detectChanges();
|
||||
|
||||
const countPlaceholders = fixture.nativeElement.querySelectorAll(
|
||||
'.item-count--loading'
|
||||
);
|
||||
const categoryButtons = Array.from(
|
||||
fixture.nativeElement.querySelectorAll('.category-item')
|
||||
) as HTMLButtonElement[];
|
||||
const status = fixture.nativeElement.querySelector(
|
||||
'.context-inline-status'
|
||||
) as HTMLElement | null;
|
||||
|
||||
expect(countPlaceholders).toHaveLength(2);
|
||||
expect(categoryButtons.every((button) => button.disabled)).toBe(true);
|
||||
expect(status).toBeNull();
|
||||
});
|
||||
|
||||
it('shows real counts and enables navigation once the selected xtream type is ready', () => {
|
||||
fixture.componentRef.setInput('section', 'vod');
|
||||
xtreamSelectedTypeContentState.set('ready');
|
||||
@@ -174,9 +197,9 @@ describe('WorkspaceContextPanelComponent', () => {
|
||||
const categoryButtons = Array.from(
|
||||
fixture.nativeElement.querySelectorAll('.category-item')
|
||||
) as HTMLButtonElement[];
|
||||
const manageButton = fixture.nativeElement.querySelector(
|
||||
'.context-header__action'
|
||||
) as HTMLButtonElement | null;
|
||||
const manageButton = Array.from(
|
||||
fixture.nativeElement.querySelectorAll('.context-header__action')
|
||||
).at(-1) as HTMLButtonElement | undefined;
|
||||
|
||||
expect(countTexts).toEqual(['3', '0']);
|
||||
expect(categoryButtons.every((button) => !button.disabled)).toBe(true);
|
||||
|
||||
+2
@@ -81,6 +81,7 @@ export class WorkspaceContextPanelComponent {
|
||||
this.xtreamStore.selectedTypeContentReady;
|
||||
readonly xtreamSelectedTypeCountsReady =
|
||||
this.xtreamStore.selectedTypeCountsReady;
|
||||
readonly isXtreamImporting = this.xtreamStore.isImporting;
|
||||
readonly xtreamImportPhase = this.xtreamStore.currentImportPhase;
|
||||
readonly isXtreamCategoryLoading = computed(
|
||||
() =>
|
||||
@@ -106,6 +107,7 @@ export class WorkspaceContextPanelComponent {
|
||||
if (
|
||||
!this.isXtreamCategories() ||
|
||||
this.isXtreamCategoryLoading() ||
|
||||
!this.isXtreamImporting() ||
|
||||
this.xtreamSelectedTypeContentState() !== 'loading'
|
||||
) {
|
||||
return '';
|
||||
|
||||
Reference in new issue
Block a user