Bug fix: Backend now notifies frontend when a new playlist is creating. This should fix where accounts will sometimes only show fetching groups after a new account is added.

This commit is contained in:
SergeantPanda 2025-10-07 09:55:35 -05:00
parent 171bb004c4
commit da245c409a
3 changed files with 37 additions and 15 deletions

View file

@ -81,6 +81,13 @@ class M3UAccountViewSet(viewsets.ModelViewSet):
account_type = response.data.get("account_type")
account_id = response.data.get("id")
# Notify frontend that a new playlist was created
from core.utils import send_websocket_update
send_websocket_update('updates', 'update', {
'type': 'playlist_created',
'playlist_id': account_id
})
if account_type == M3UAccount.Types.XC:
refresh_m3u_groups(account_id)

View file

@ -36,7 +36,6 @@ export const WebsocketProvider = ({ children }) => {
const updateEPG = useEPGsStore((s) => s.updateEPG);
const updateEPGProgress = useEPGsStore((s) => s.updateEPGProgress);
const playlists = usePlaylistsStore((s) => s.playlists);
const updatePlaylist = usePlaylistsStore((s) => s.updatePlaylist);
// Calculate reconnection delay with exponential backoff
@ -247,10 +246,14 @@ export const WebsocketProvider = ({ children }) => {
// Update the playlist status whenever we receive a status update
// Not just when progress is 100% or status is pending_setup
if (parsedEvent.data.status && parsedEvent.data.account) {
// Check if playlists is an object with IDs as keys or an array
const playlist = Array.isArray(playlists)
? playlists.find((p) => p.id === parsedEvent.data.account)
: playlists[parsedEvent.data.account];
// Get fresh playlists from store to avoid stale state from React render cycle
const currentPlaylists = usePlaylistsStore.getState().playlists;
const isArray = Array.isArray(currentPlaylists);
const playlist = isArray
? currentPlaylists.find(
(p) => p.id === parsedEvent.data.account
)
: currentPlaylists[parsedEvent.data.account];
if (playlist) {
// When we receive a "success" status with 100% progress, this is a completed refresh
@ -279,13 +282,13 @@ export const WebsocketProvider = ({ children }) => {
fetchPlaylists(); // Refresh playlists to ensure UI is up-to-date
fetchChannelProfiles(); // Ensure channel profiles are updated
} else {
// Log when playlist can't be found for debugging purposes
console.warn(
`Received update for unknown playlist ID: ${parsedEvent.data.account}`,
Array.isArray(playlists)
? 'playlists is array'
: 'playlists is object',
Object.keys(playlists).length
// Playlist not in store yet - this happens when backend sends websocket
// updates immediately after creating the playlist, before the API response
// returns. The frontend will receive a 'playlist_created' event shortly
// which will trigger a fetchPlaylists() to sync the store.
console.log(
`Received update for playlist ID ${parsedEvent.data.account} not yet in store. ` +
`Waiting for playlist_created event to sync...`
);
}
}
@ -739,6 +742,14 @@ export const WebsocketProvider = ({ children }) => {
break;
case 'playlist_created':
// Backend signals that a new playlist has been created and we should refresh
console.log(
'Playlist created event received, refreshing playlists...'
);
fetchPlaylists();
break;
case 'bulk_channel_creation_progress': {
// Handle progress updates with persistent notifications like stream rehash
const data = parsedEvent.data;

View file

@ -23,7 +23,6 @@ import {
} from '@mantine/core';
import M3UGroupFilter from './M3UGroupFilter';
import useChannelsStore from '../../store/channels';
import usePlaylistsStore from '../../store/playlists';
import { notifications } from '@mantine/notifications';
import { isNotEmpty, useForm } from '@mantine/form';
import useEPGsStore from '../../store/epgs';
@ -40,7 +39,6 @@ const M3U = ({
const userAgents = useUserAgentsStore((s) => s.userAgents);
const fetchChannelGroups = useChannelsStore((s) => s.fetchChannelGroups);
const fetchPlaylists = usePlaylistsStore((s) => s.fetchPlaylists);
const fetchEPGs = useEPGsStore((s) => s.fetchEPGs);
const fetchCategories = useVODStore((s) => s.fetchCategories);
@ -171,8 +169,14 @@ const M3U = ({
return;
}
// Fetch the updated playlist details (this also updates the store via API)
const updatedPlaylist = await API.getPlaylist(newPlaylist.id);
await Promise.all([fetchChannelGroups(), fetchPlaylists(), fetchEPGs()]);
// Note: We don't call fetchPlaylists() here because API.addPlaylist()
// already added the playlist to the store. Calling fetchPlaylists() creates
// a race condition where the store is temporarily cleared/replaced while
// websocket updates for the new playlist's refresh task are arriving.
await Promise.all([fetchChannelGroups(), fetchEPGs()]);
// If this is an XC account with VOD enabled, also fetch VOD categories
if (values.account_type === 'XC' && values.enable_vod) {