maintenance
This commit is contained in:
164
src/store/action/channels-publishing.ts
Normal file
164
src/store/action/channels-publishing.ts
Normal file
@@ -0,0 +1,164 @@
|
||||
/**
|
||||
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
|
||||
*/
|
||||
import {createAsyncThunk, createSelector, createSlice, PayloadAction} from '@reduxjs/toolkit';
|
||||
import {Channel} from '@phenixrts/sdk';
|
||||
import channelService from '../../services/channel.service';
|
||||
import {RootState} from '../index';
|
||||
|
||||
// Publishing state interface
|
||||
export interface ChannelPublishingState {
|
||||
channelId: string;
|
||||
isOnline: boolean;
|
||||
publisherCount: number;
|
||||
streamCount: number;
|
||||
lastUpdated: string;
|
||||
}
|
||||
|
||||
export interface ChannelsPublishingState {
|
||||
publishingState: ChannelPublishingState[];
|
||||
isLoading: boolean;
|
||||
error: string | null;
|
||||
lastFetched: string | null;
|
||||
}
|
||||
|
||||
const initialState: ChannelsPublishingState = {
|
||||
publishingState: [],
|
||||
isLoading: false,
|
||||
error: null,
|
||||
lastFetched: null
|
||||
};
|
||||
|
||||
// Selectors
|
||||
export const channelsPublishingSelector = (state: RootState): ChannelsPublishingState =>
|
||||
state.channelsPublishing;
|
||||
|
||||
export const selectChannelsPublishingState = createSelector(
|
||||
[channelsPublishingSelector],
|
||||
(channelsPublishing: ChannelsPublishingState) => channelsPublishing.publishingState
|
||||
);
|
||||
|
||||
export const selectChannelsPublishingLoading = createSelector(
|
||||
[channelsPublishingSelector],
|
||||
(channelsPublishing: ChannelsPublishingState) => channelsPublishing.isLoading
|
||||
);
|
||||
|
||||
export const selectChannelPublishingState = createSelector(
|
||||
[selectChannelsPublishingState, (_: RootState, channelId: string) => channelId],
|
||||
(publishingStates: ChannelPublishingState[], channelId: string) =>
|
||||
publishingStates.find(state => state.channelId === channelId)
|
||||
);
|
||||
|
||||
// Async thunks
|
||||
export const fetchChannelsPublishingState = createAsyncThunk(
|
||||
'channelsPublishing/fetchChannelsPublishingState',
|
||||
async (channels: Channel[], {rejectWithValue}) => {
|
||||
try {
|
||||
const publishingStates = await Promise.all(
|
||||
channels.map(async (channel): Promise<ChannelPublishingState> => {
|
||||
try {
|
||||
const publisherCount = await channelService.getPublisherCount(channel.channelId);
|
||||
return {
|
||||
channelId: channel.channelId,
|
||||
isOnline: publisherCount > 0,
|
||||
publisherCount,
|
||||
streamCount: publisherCount, // Assuming 1:1 for now
|
||||
lastUpdated: new Date().toISOString()
|
||||
};
|
||||
} catch (error) {
|
||||
// If we can't get publisher count, assume offline
|
||||
return {
|
||||
channelId: channel.channelId,
|
||||
isOnline: false,
|
||||
publisherCount: 0,
|
||||
streamCount: 0,
|
||||
lastUpdated: new Date().toISOString()
|
||||
};
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
return publishingStates;
|
||||
} catch (error) {
|
||||
return rejectWithValue(error instanceof Error ? error.message : 'Failed to fetch publishing state');
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
export const updateChannelPublishingState = createAsyncThunk(
|
||||
'channelsPublishing/updateChannelPublishingState',
|
||||
async (channelId: string, {rejectWithValue}) => {
|
||||
try {
|
||||
const publisherCount = await channelService.getPublisherCount(channelId);
|
||||
return {
|
||||
channelId,
|
||||
isOnline: publisherCount > 0,
|
||||
publisherCount,
|
||||
streamCount: publisherCount,
|
||||
lastUpdated: new Date().toISOString()
|
||||
} as ChannelPublishingState;
|
||||
} catch (error) {
|
||||
return rejectWithValue(error instanceof Error ? error.message : 'Failed to update publishing state');
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
// Slice
|
||||
const channelsPublishingSlice = createSlice({
|
||||
name: 'channelsPublishing',
|
||||
initialState,
|
||||
reducers: {
|
||||
clearPublishingState: (state) => {
|
||||
state.publishingState = [];
|
||||
state.error = null;
|
||||
},
|
||||
setPublishingError: (state, action: PayloadAction<string | null>) => {
|
||||
state.error = action.payload;
|
||||
},
|
||||
updateChannelState: (state, action: PayloadAction<ChannelPublishingState>) => {
|
||||
const index = state.publishingState.findIndex(
|
||||
item => item.channelId === action.payload.channelId
|
||||
);
|
||||
|
||||
if (index >= 0) {
|
||||
state.publishingState[index] = action.payload;
|
||||
} else {
|
||||
state.publishingState.push(action.payload);
|
||||
}
|
||||
}
|
||||
},
|
||||
extraReducers: (builder) => {
|
||||
builder
|
||||
.addCase(fetchChannelsPublishingState.pending, (state) => {
|
||||
state.isLoading = true;
|
||||
state.error = null;
|
||||
})
|
||||
.addCase(fetchChannelsPublishingState.fulfilled, (state, action) => {
|
||||
state.isLoading = false;
|
||||
state.publishingState = action.payload;
|
||||
state.lastFetched = new Date().toISOString();
|
||||
state.error = null;
|
||||
})
|
||||
.addCase(fetchChannelsPublishingState.rejected, (state, action) => {
|
||||
state.isLoading = false;
|
||||
state.error = action.payload as string;
|
||||
})
|
||||
.addCase(updateChannelPublishingState.fulfilled, (state, action) => {
|
||||
const index = state.publishingState.findIndex(
|
||||
item => item.channelId === action.payload.channelId
|
||||
);
|
||||
|
||||
if (index >= 0) {
|
||||
state.publishingState[index] = action.payload;
|
||||
} else {
|
||||
state.publishingState.push(action.payload);
|
||||
}
|
||||
})
|
||||
.addCase(updateChannelPublishingState.rejected, (state, action) => {
|
||||
state.error = action.payload as string;
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
export const {clearPublishingState, setPublishingError, updateChannelState} = channelsPublishingSlice.actions;
|
||||
export default channelsPublishingSlice.reducer;
|
||||
Reference in New Issue
Block a user