Add a better solution for 304 browser bug + update naming conventions to better articulate what's happening (#603)
This commit is contained in:
parent
1eaa172a1b
commit
bc38466abf
7 changed files with 53 additions and 41 deletions
|
@ -13,7 +13,7 @@ import { makeSelectChannelIsMuted } from 'redux/selectors/blocked';
|
||||||
import { withRouter } from 'react-router';
|
import { withRouter } from 'react-router';
|
||||||
import { selectUserVerifiedEmail } from 'redux/selectors/user';
|
import { selectUserVerifiedEmail } from 'redux/selectors/user';
|
||||||
import { selectClientSetting, selectShowMatureContent } from 'redux/selectors/settings';
|
import { selectClientSetting, selectShowMatureContent } from 'redux/selectors/settings';
|
||||||
import { doFetchActiveLivestream } from 'redux/actions/livestream';
|
import { doFetchChannelLiveStatus } from 'redux/actions/livestream';
|
||||||
import { selectActiveLivestreamForChannel, selectActiveLivestreamInitialized } from 'redux/selectors/livestream';
|
import { selectActiveLivestreamForChannel, selectActiveLivestreamInitialized } from 'redux/selectors/livestream';
|
||||||
import { getChannelIdFromClaim } from 'util/claim';
|
import { getChannelIdFromClaim } from 'util/claim';
|
||||||
import ChannelContent from './view';
|
import ChannelContent from './view';
|
||||||
|
@ -42,7 +42,7 @@ const select = (state, props) => {
|
||||||
|
|
||||||
const perform = (dispatch) => ({
|
const perform = (dispatch) => ({
|
||||||
doResolveUris: (uris, returnCachedUris) => dispatch(doResolveUris(uris, returnCachedUris)),
|
doResolveUris: (uris, returnCachedUris) => dispatch(doResolveUris(uris, returnCachedUris)),
|
||||||
doFetchActiveLivestream: (channelID) => dispatch(doFetchActiveLivestream(channelID)),
|
doFetchChannelLiveStatus: (channelID) => dispatch(doFetchChannelLiveStatus(channelID)),
|
||||||
});
|
});
|
||||||
|
|
||||||
export default withRouter(connect(select, perform)(ChannelContent));
|
export default withRouter(connect(select, perform)(ChannelContent));
|
||||||
|
|
|
@ -37,7 +37,7 @@ type Props = {
|
||||||
doResolveUris: (Array<string>, boolean) => void,
|
doResolveUris: (Array<string>, boolean) => void,
|
||||||
claimType: string,
|
claimType: string,
|
||||||
empty?: string,
|
empty?: string,
|
||||||
doFetchActiveLivestream: (string) => void,
|
doFetchChannelLiveStatus: (string) => void,
|
||||||
activeLivestreamForChannel: any,
|
activeLivestreamForChannel: any,
|
||||||
activeLivestreamInitialized: boolean,
|
activeLivestreamInitialized: boolean,
|
||||||
};
|
};
|
||||||
|
@ -59,7 +59,7 @@ function ChannelContent(props: Props) {
|
||||||
doResolveUris,
|
doResolveUris,
|
||||||
claimType,
|
claimType,
|
||||||
empty,
|
empty,
|
||||||
doFetchActiveLivestream,
|
doFetchChannelLiveStatus,
|
||||||
activeLivestreamForChannel,
|
activeLivestreamForChannel,
|
||||||
activeLivestreamInitialized,
|
activeLivestreamInitialized,
|
||||||
} = props;
|
} = props;
|
||||||
|
@ -126,10 +126,10 @@ function ChannelContent(props: Props) {
|
||||||
|
|
||||||
// Find out current channels status + active live claim.
|
// Find out current channels status + active live claim.
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
doFetchActiveLivestream(claimId);
|
doFetchChannelLiveStatus(claimId);
|
||||||
const intervalId = setInterval(() => doFetchActiveLivestream(claimId), 30000);
|
const intervalId = setInterval(() => doFetchChannelLiveStatus(claimId), 30000);
|
||||||
return () => clearInterval(intervalId);
|
return () => clearInterval(intervalId);
|
||||||
}, [claimId, doFetchActiveLivestream]);
|
}, [claimId, doFetchChannelLiveStatus]);
|
||||||
|
|
||||||
const showScheduledLiveStreams = claimType !== 'collection'; // ie. not on the playlist page.
|
const showScheduledLiveStreams = claimType !== 'collection'; // ie. not on the playlist page.
|
||||||
|
|
||||||
|
|
|
@ -477,9 +477,8 @@ export const FETCH_ACTIVE_LIVESTREAMS_FAILED = 'FETCH_ACTIVE_LIVESTREAMS_FAILED'
|
||||||
export const FETCH_ACTIVE_LIVESTREAMS_SKIPPED = 'FETCH_ACTIVE_LIVESTREAMS_SKIPPED';
|
export const FETCH_ACTIVE_LIVESTREAMS_SKIPPED = 'FETCH_ACTIVE_LIVESTREAMS_SKIPPED';
|
||||||
export const FETCH_ACTIVE_LIVESTREAMS_COMPLETED = 'FETCH_ACTIVE_LIVESTREAMS_COMPLETED';
|
export const FETCH_ACTIVE_LIVESTREAMS_COMPLETED = 'FETCH_ACTIVE_LIVESTREAMS_COMPLETED';
|
||||||
|
|
||||||
export const FETCH_ACTIVE_LIVESTREAM_FAILED = 'FETCH_ACTIVE_LIVESTREAMS_FAILED';
|
export const ADD_CHANNEL_TO_ACTIVE_LIVESTREAMS = 'ADD_CHANNEL_TO_ACTIVE_LIVESTREAMS';
|
||||||
export const FETCH_ACTIVE_LIVESTREAM_COMPLETED = 'FETCH_ACTIVE_LIVESTREAM_COMPLETED';
|
export const REMOVE_CHANNEL_FROM_ACTIVE_LIVESTREAMS = 'REMOVE_CHANNEL_FROM_ACTIVE_LIVESTREAMS';
|
||||||
export const FETCH_ACTIVE_LIVESTREAM_FINISHED = 'FETCH_ACTIVE_LIVESTREAM_FINISHED';
|
|
||||||
|
|
||||||
// Blacklist
|
// Blacklist
|
||||||
export const FETCH_BLACK_LISTED_CONTENT_STARTED = 'FETCH_BLACK_LISTED_CONTENT_STARTED';
|
export const FETCH_BLACK_LISTED_CONTENT_STARTED = 'FETCH_BLACK_LISTED_CONTENT_STARTED';
|
||||||
|
|
|
@ -7,7 +7,7 @@ import { DISABLE_COMMENTS_TAG } from 'constants/tags';
|
||||||
import { doCommentSocketConnect, doCommentSocketDisconnect } from 'redux/actions/websocket';
|
import { doCommentSocketConnect, doCommentSocketDisconnect } from 'redux/actions/websocket';
|
||||||
import { getChannelIdFromClaim } from 'util/claim';
|
import { getChannelIdFromClaim } from 'util/claim';
|
||||||
import { selectActiveLivestreamForChannel, selectActiveLivestreamInitialized } from 'redux/selectors/livestream';
|
import { selectActiveLivestreamForChannel, selectActiveLivestreamInitialized } from 'redux/selectors/livestream';
|
||||||
import { doFetchActiveLivestream } from 'redux/actions/livestream';
|
import { doFetchChannelLiveStatus } from 'redux/actions/livestream';
|
||||||
import LivestreamPage from './view';
|
import LivestreamPage from './view';
|
||||||
|
|
||||||
const select = (state, props) => {
|
const select = (state, props) => {
|
||||||
|
@ -26,7 +26,7 @@ const perform = {
|
||||||
doUserSetReferrer,
|
doUserSetReferrer,
|
||||||
doCommentSocketConnect,
|
doCommentSocketConnect,
|
||||||
doCommentSocketDisconnect,
|
doCommentSocketDisconnect,
|
||||||
doFetchActiveLivestream,
|
doFetchChannelLiveStatus,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default connect(select, perform)(LivestreamPage);
|
export default connect(select, perform)(LivestreamPage);
|
||||||
|
|
|
@ -19,7 +19,7 @@ type Props = {
|
||||||
chatDisabled: boolean,
|
chatDisabled: boolean,
|
||||||
doCommentSocketConnect: (string, string) => void,
|
doCommentSocketConnect: (string, string) => void,
|
||||||
doCommentSocketDisconnect: (string) => void,
|
doCommentSocketDisconnect: (string) => void,
|
||||||
doFetchActiveLivestream: (string) => void,
|
doFetchChannelLiveStatus: (string) => void,
|
||||||
activeLivestreamForChannel: any,
|
activeLivestreamForChannel: any,
|
||||||
activeLivestreamInitialized: boolean,
|
activeLivestreamInitialized: boolean,
|
||||||
};
|
};
|
||||||
|
@ -35,7 +35,7 @@ export default function LivestreamPage(props: Props) {
|
||||||
chatDisabled,
|
chatDisabled,
|
||||||
doCommentSocketConnect,
|
doCommentSocketConnect,
|
||||||
doCommentSocketDisconnect,
|
doCommentSocketDisconnect,
|
||||||
doFetchActiveLivestream,
|
doFetchChannelLiveStatus,
|
||||||
activeLivestreamForChannel,
|
activeLivestreamForChannel,
|
||||||
activeLivestreamInitialized,
|
activeLivestreamInitialized,
|
||||||
} = props;
|
} = props;
|
||||||
|
@ -67,10 +67,10 @@ export default function LivestreamPage(props: Props) {
|
||||||
|
|
||||||
// Find out current channels status + active live claim.
|
// Find out current channels status + active live claim.
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
doFetchActiveLivestream(livestreamChannelId);
|
doFetchChannelLiveStatus(livestreamChannelId);
|
||||||
const intervalId = setInterval(() => doFetchActiveLivestream(livestreamChannelId), 30000);
|
const intervalId = setInterval(() => doFetchChannelLiveStatus(livestreamChannelId), 30000);
|
||||||
return () => clearInterval(intervalId);
|
return () => clearInterval(intervalId);
|
||||||
}, [livestreamChannelId, doFetchActiveLivestream]);
|
}, [livestreamChannelId, doFetchChannelLiveStatus]);
|
||||||
|
|
||||||
const [activeStreamUri, setActiveStreamUri] = React.useState(false);
|
const [activeStreamUri, setActiveStreamUri] = React.useState(false);
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,16 @@ import { doClaimSearch } from 'redux/actions/claims';
|
||||||
import { LIVESTREAM_LIVE_API, LIVESTREAM_STARTS_SOON_BUFFER } from 'constants/livestream';
|
import { LIVESTREAM_LIVE_API, LIVESTREAM_STARTS_SOON_BUFFER } from 'constants/livestream';
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
|
|
||||||
|
const LiveStatus = Object.freeze({
|
||||||
|
LIVE: 'LIVE',
|
||||||
|
NOT_LIVE: 'NOT_LIVE',
|
||||||
|
UNKNOWN: 'UNKNOWN',
|
||||||
|
});
|
||||||
|
|
||||||
|
type LiveStatusType = $Keys<typeof LiveStatus>;
|
||||||
|
|
||||||
|
type LiveChannelStatus = { channelStatus: LiveStatusType, channelData?: LivestreamInfo };
|
||||||
|
|
||||||
export const doFetchNoSourceClaims = (channelId: string) => async (dispatch: Dispatch, getState: GetState) => {
|
export const doFetchNoSourceClaims = (channelId: string) => async (dispatch: Dispatch, getState: GetState) => {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: ACTIONS.FETCH_NO_SOURCE_CLAIMS_STARTED,
|
type: ACTIONS.FETCH_NO_SOURCE_CLAIMS_STARTED,
|
||||||
|
@ -48,23 +58,22 @@ const transformLivestreamData = (data: Array<any>): LivestreamInfo => {
|
||||||
}, {});
|
}, {});
|
||||||
};
|
};
|
||||||
|
|
||||||
const fetchLiveChannels = async () => {
|
const fetchLiveChannels = async (): Promise<LivestreamInfo> => {
|
||||||
const response = await fetch(LIVESTREAM_LIVE_API);
|
const response = await fetch(LIVESTREAM_LIVE_API);
|
||||||
const json = await response.json();
|
const json = await response.json();
|
||||||
if (!json.data) throw new Error();
|
if (!json.data) throw new Error();
|
||||||
return transformLivestreamData(json.data);
|
return transformLivestreamData(json.data);
|
||||||
};
|
};
|
||||||
|
|
||||||
const fetchLiveChannel = async (channelId: string) => {
|
const fetchLiveChannel = async (channelId: string): Promise<LiveChannelStatus> => {
|
||||||
const response = await fetch(`${LIVESTREAM_LIVE_API}/${channelId}`);
|
|
||||||
let json;
|
|
||||||
try {
|
try {
|
||||||
json = await response.json();
|
const response = await fetch(`${LIVESTREAM_LIVE_API}/${channelId}`);
|
||||||
|
const json = await response.json();
|
||||||
|
if (json.data?.live === false) return { channelStatus: LiveStatus.NOT_LIVE };
|
||||||
|
return { channelStatus: LiveStatus.LIVE, channelData: transformLivestreamData([json.data]) };
|
||||||
} catch {
|
} catch {
|
||||||
throw new Error('Error handling live API response');
|
return { channelStatus: LiveStatus.UNKNOWN };
|
||||||
}
|
}
|
||||||
if (!(json.data && json.data.live)) throw new Error();
|
|
||||||
return transformLivestreamData([json.data]);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const filterUpcomingLiveStreamClaims = (upcomingClaims) => {
|
const filterUpcomingLiveStreamClaims = (upcomingClaims) => {
|
||||||
|
@ -164,25 +173,29 @@ const findActiveStreams = async (channelIDs: Array<string>, orderBy: Array<strin
|
||||||
return determineLiveClaim(allClaims, liveChannels);
|
return determineLiveClaim(allClaims, liveChannels);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const doFetchActiveLivestream = (channelId: string) => {
|
export const doFetchChannelLiveStatus = (channelId: string) => {
|
||||||
return async (dispatch: Dispatch) => {
|
return async (dispatch: Dispatch) => {
|
||||||
try {
|
try {
|
||||||
const liveChannel = await fetchLiveChannel(channelId);
|
const { channelStatus, channelData } = await fetchLiveChannel(channelId);
|
||||||
const currentlyLiveClaims = await findActiveStreams([channelId], ['release_time'], liveChannel, dispatch);
|
|
||||||
|
if (channelStatus === LiveStatus.NOT_LIVE) {
|
||||||
|
dispatch({ type: ACTIONS.REMOVE_CHANNEL_FROM_ACTIVE_LIVESTREAMS, data: { channelId } });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (channelStatus === LiveStatus.UNKNOWN) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const currentlyLiveClaims = await findActiveStreams([channelId], ['release_time'], channelData, dispatch);
|
||||||
const liveClaim = currentlyLiveClaims[channelId];
|
const liveClaim = currentlyLiveClaims[channelId];
|
||||||
|
|
||||||
liveChannel[channelId].claimId = liveClaim.stream.claim_id;
|
if (channelData && liveClaim) {
|
||||||
liveChannel[channelId].claimUri = liveClaim.stream.canonical_url;
|
channelData[channelId].claimId = liveClaim.stream.claim_id;
|
||||||
|
channelData[channelId].claimUri = liveClaim.stream.canonical_url;
|
||||||
dispatch({
|
dispatch({ type: ACTIONS.ADD_CHANNEL_TO_ACTIVE_LIVESTREAMS, data: { ...channelData } });
|
||||||
type: ACTIONS.FETCH_ACTIVE_LIVESTREAM_COMPLETED,
|
}
|
||||||
data: {
|
|
||||||
...liveChannel,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
if (err.message === 'Error handling live API response') return;
|
dispatch({ type: ACTIONS.REMOVE_CHANNEL_FROM_ACTIVE_LIVESTREAMS, data: { channelId } });
|
||||||
dispatch({ type: ACTIONS.FETCH_ACTIVE_LIVESTREAM_FAILED, data: { channelId } });
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -58,11 +58,11 @@ export default handleActions(
|
||||||
activeLivestreamsLastFetchedOptions,
|
activeLivestreamsLastFetchedOptions,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
[ACTIONS.FETCH_ACTIVE_LIVESTREAM_COMPLETED]: (state: LivestreamState, action: any) => {
|
[ACTIONS.ADD_CHANNEL_TO_ACTIVE_LIVESTREAMS]: (state: LivestreamState, action: any) => {
|
||||||
const activeLivestreams = Object.assign({}, state.activeLivestreams || {}, action.data);
|
const activeLivestreams = Object.assign({}, state.activeLivestreams || {}, action.data);
|
||||||
return { ...state, activeLivestreams, activeLivestreamInitialized: true };
|
return { ...state, activeLivestreams, activeLivestreamInitialized: true };
|
||||||
},
|
},
|
||||||
[ACTIONS.FETCH_ACTIVE_LIVESTREAM_FAILED]: (state: LivestreamState, action: any) => {
|
[ACTIONS.REMOVE_CHANNEL_FROM_ACTIVE_LIVESTREAMS]: (state: LivestreamState, action: any) => {
|
||||||
const activeLivestreams = state.activeLivestreams;
|
const activeLivestreams = state.activeLivestreams;
|
||||||
if (activeLivestreams) delete activeLivestreams[action.data.channelId];
|
if (activeLivestreams) delete activeLivestreams[action.data.channelId];
|
||||||
return { ...state, activeLivestreams: Object.assign({}, activeLivestreams), activeLivestreamInitialized: true };
|
return { ...state, activeLivestreams: Object.assign({}, activeLivestreams), activeLivestreamInitialized: true };
|
||||||
|
|
Loading…
Reference in a new issue