mirror of
https://github.com/4gray/iptvnator.git
synced 2026-10-11 19:46:16 -08:00
feat(xtream): Xtream playlist refresh workflow
a dedicated refresh button and workflow for Xtream in the recent playlists UI. Show a refresh icon only when the playlist has a serverUrl. For Xtream playlists, prompt the user with a confirmation dialog, delete locally cached categories and streams, show a toast that the refresh started, and navigate to the playlist to trigger re-import. Keep existing refresh IPC logic for non-Xtream (M3U/local) playlists. Also add English translations for the Xtream refresh tooltip and dialog messages, and surface errors via snackbar on failure. This enables safe re-importing of remote Xtream playlists while preserving favorites and recent items.
This commit is contained in:
1 parent
0a934d2ac6
commit
461e2e2e7e
8 files changed
+160
-60
No files matched your search
@@ -3,7 +3,6 @@ import {
|
||||
AfterViewInit,
|
||||
Component,
|
||||
effect,
|
||||
ElementRef,
|
||||
inject,
|
||||
Inject,
|
||||
Optional,
|
||||
@@ -55,7 +54,7 @@ interface SearchResultsData {
|
||||
styleUrls: ['./search-results.component.scss'],
|
||||
})
|
||||
export class SearchResultsComponent implements AfterViewInit {
|
||||
@ViewChild('searchInput') searchInput!: ElementRef;
|
||||
@ViewChild(SearchFormComponent) searchFormComponent!: SearchFormComponent;
|
||||
readonly xtreamStore = inject(XtreamStore);
|
||||
readonly router = inject(Router);
|
||||
readonly activatedRoute = inject(ActivatedRoute);
|
||||
@@ -105,7 +104,7 @@ export class SearchResultsComponent implements AfterViewInit {
|
||||
ngAfterViewInit() {
|
||||
this.xtreamStore.setSelectedContentType(undefined);
|
||||
setTimeout(() => {
|
||||
this.searchInput.nativeElement.focus();
|
||||
this.searchFormComponent?.focusSearchInput();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -568,51 +568,57 @@ export const XtreamStore = signalStore(
|
||||
try {
|
||||
console.log('Starting content initialization...');
|
||||
|
||||
console.log('Fetching live categories...');
|
||||
await lastValueFrom(
|
||||
fetchCategories(
|
||||
XtreamCodeActions.GetLiveCategories,
|
||||
'liveCategories',
|
||||
'live'
|
||||
)
|
||||
);
|
||||
await lastValueFrom(
|
||||
fetchCategories(
|
||||
XtreamCodeActions.GetVodCategories,
|
||||
'vodCategories',
|
||||
'movies'
|
||||
)
|
||||
);
|
||||
await lastValueFrom(
|
||||
fetchCategories(
|
||||
XtreamCodeActions.GetSeriesCategories,
|
||||
'serialCategories',
|
||||
'series'
|
||||
)
|
||||
);
|
||||
// Fetch all categories in parallel
|
||||
console.log('Fetching categories...');
|
||||
await Promise.all([
|
||||
lastValueFrom(
|
||||
fetchCategories(
|
||||
XtreamCodeActions.GetLiveCategories,
|
||||
'liveCategories',
|
||||
'live'
|
||||
)
|
||||
),
|
||||
lastValueFrom(
|
||||
fetchCategories(
|
||||
XtreamCodeActions.GetVodCategories,
|
||||
'vodCategories',
|
||||
'movies'
|
||||
)
|
||||
),
|
||||
lastValueFrom(
|
||||
fetchCategories(
|
||||
XtreamCodeActions.GetSeriesCategories,
|
||||
'serialCategories',
|
||||
'series'
|
||||
)
|
||||
),
|
||||
]);
|
||||
|
||||
// Fetch all content in parallel
|
||||
console.log('Fetching content...');
|
||||
await lastValueFrom(
|
||||
fetchStreams(
|
||||
XtreamCodeActions.GetLiveStreams,
|
||||
'liveStreams',
|
||||
'live'
|
||||
)
|
||||
);
|
||||
await lastValueFrom(
|
||||
fetchStreams(
|
||||
XtreamCodeActions.GetVodStreams,
|
||||
'vodStreams',
|
||||
'movie'
|
||||
)
|
||||
);
|
||||
await lastValueFrom(
|
||||
fetchStreams(
|
||||
XtreamCodeActions.GetSeries,
|
||||
'serialStreams',
|
||||
'series'
|
||||
)
|
||||
);
|
||||
await Promise.all([
|
||||
lastValueFrom(
|
||||
fetchStreams(
|
||||
XtreamCodeActions.GetLiveStreams,
|
||||
'liveStreams',
|
||||
'live'
|
||||
)
|
||||
),
|
||||
lastValueFrom(
|
||||
fetchStreams(
|
||||
XtreamCodeActions.GetVodStreams,
|
||||
'vodStreams',
|
||||
'movie'
|
||||
)
|
||||
),
|
||||
lastValueFrom(
|
||||
fetchStreams(
|
||||
XtreamCodeActions.GetSeries,
|
||||
'serialStreams',
|
||||
'series'
|
||||
)
|
||||
),
|
||||
]);
|
||||
console.log('Content initialization completed');
|
||||
} catch (error) {
|
||||
console.error(
|
||||
@@ -627,7 +633,7 @@ export const XtreamStore = signalStore(
|
||||
const checkPortalStatus = rxMethod<void>(
|
||||
pipe(
|
||||
combineLatestWith(oldStore.select(selectActivePlaylist)),
|
||||
switchMap(([_, playlist]) => {
|
||||
switchMap(([, playlist]) => {
|
||||
if (!playlist) return EMPTY;
|
||||
|
||||
return from(
|
||||
|
||||
@@ -54,6 +54,13 @@
|
||||
},
|
||||
"UPDATED": "Updated",
|
||||
"REFRESH": "Refresh playlist",
|
||||
"REFRESH_XTREAM": "Refresh Xtream playlist from remote",
|
||||
"REFRESH_XTREAM_DIALOG": {
|
||||
"TITLE": "Refresh Xtream Playlist",
|
||||
"MESSAGE": "This will delete locally cached categories and streams and re-import everything from the remote server. Your favorites and recently viewed items will be preserved. Are you sure you want to continue?",
|
||||
"STARTED": "Refresh started. Navigating to playlist...",
|
||||
"ERROR": "Failed to refresh playlist. Please try again."
|
||||
},
|
||||
"GLOBAL_FAVORITES": "Global favorites",
|
||||
"GLOBAL_FAVORITES_DESCRIPTION": "Auto-generated playlist with aggregated favorites from all playlists",
|
||||
"MY_PLAYLISTS": "My playlists",
|
||||
|
||||
Reference in new issue
Block a user