Refactor and fix websocket connection behavior
This commit is contained in:
parent
05ec4e5fbe
commit
129a5819d9
10 changed files with 109 additions and 52 deletions
9
flow-typed/livestream.js
vendored
9
flow-typed/livestream.js
vendored
|
@ -18,7 +18,7 @@ declare type LivestreamReplayItem = {
|
||||||
uploadedAt: string, // Date?
|
uploadedAt: string, // Date?
|
||||||
},
|
},
|
||||||
id: string,
|
id: string,
|
||||||
}
|
};
|
||||||
declare type LivestreamReplayData = Array<LivestreamReplayItem>;
|
declare type LivestreamReplayData = Array<LivestreamReplayItem>;
|
||||||
|
|
||||||
declare type LivestreamState = {
|
declare type LivestreamState = {
|
||||||
|
@ -29,7 +29,8 @@ declare type LivestreamState = {
|
||||||
activeLivestreamsLastFetchedDate: number,
|
activeLivestreamsLastFetchedDate: number,
|
||||||
activeLivestreamsLastFetchedOptions: {},
|
activeLivestreamsLastFetchedOptions: {},
|
||||||
activeLivestreamInitialized: boolean,
|
activeLivestreamInitialized: boolean,
|
||||||
}
|
socketConnectionById: { [id: string]: { connected: ?boolean, sub_category: ?string } },
|
||||||
|
};
|
||||||
|
|
||||||
declare type LivestreamInfo = {
|
declare type LivestreamInfo = {
|
||||||
[/* creatorId */ string]: {
|
[/* creatorId */ string]: {
|
||||||
|
@ -38,5 +39,5 @@ declare type LivestreamInfo = {
|
||||||
creatorId: string,
|
creatorId: string,
|
||||||
claimId: string,
|
claimId: string,
|
||||||
claimUri: string,
|
claimUri: string,
|
||||||
}
|
},
|
||||||
}
|
};
|
||||||
|
|
|
@ -19,11 +19,11 @@ import {
|
||||||
} from 'redux/selectors/content';
|
} from 'redux/selectors/content';
|
||||||
import { selectClientSetting } from 'redux/selectors/settings';
|
import { selectClientSetting } from 'redux/selectors/settings';
|
||||||
import { selectCostInfoForUri } from 'lbryinc';
|
import { selectCostInfoForUri } from 'lbryinc';
|
||||||
import { doUriInitiatePlay, doSetPlayingUri } from 'redux/actions/content';
|
import { doUriInitiatePlay, doSetPlayingUri, doClearPlayingUri } from 'redux/actions/content';
|
||||||
import { doFetchRecommendedContent } from 'redux/actions/search';
|
import { doFetchRecommendedContent } from 'redux/actions/search';
|
||||||
import { withRouter } from 'react-router';
|
import { withRouter } from 'react-router';
|
||||||
import { selectAppDrawerOpen } from 'redux/selectors/app';
|
import { selectAppDrawerOpen } from 'redux/selectors/app';
|
||||||
import { selectIsActiveLivestreamForUri, selectCommentSocketConnected } from 'redux/selectors/livestream';
|
import { selectIsActiveLivestreamForUri, selectSocketConnectionForId } from 'redux/selectors/livestream';
|
||||||
import { doCommentSocketConnect, doCommentSocketDisconnect } from 'redux/actions/websocket';
|
import { doCommentSocketConnect, doCommentSocketDisconnect } from 'redux/actions/websocket';
|
||||||
import { isStreamPlaceholderClaim, getVideoClaimAspectRatio } from 'util/claim';
|
import { isStreamPlaceholderClaim, getVideoClaimAspectRatio } from 'util/claim';
|
||||||
import FileRenderFloating from './view';
|
import FileRenderFloating from './view';
|
||||||
|
@ -57,7 +57,7 @@ const select = (state, props) => {
|
||||||
collectionId,
|
collectionId,
|
||||||
isCurrentClaimLive: selectIsActiveLivestreamForUri(state, uri),
|
isCurrentClaimLive: selectIsActiveLivestreamForUri(state, uri),
|
||||||
videoAspectRatio: getVideoClaimAspectRatio(claim),
|
videoAspectRatio: getVideoClaimAspectRatio(claim),
|
||||||
socketConnected: selectCommentSocketConnected(state),
|
socketConnection: selectSocketConnectionForId(state, claimId),
|
||||||
isLivestreamClaim: isStreamPlaceholderClaim(claim),
|
isLivestreamClaim: isStreamPlaceholderClaim(claim),
|
||||||
geoRestriction: selectGeoRestrictionForUri(state, uri),
|
geoRestriction: selectGeoRestrictionForUri(state, uri),
|
||||||
appDrawerOpen: selectAppDrawerOpen(state),
|
appDrawerOpen: selectAppDrawerOpen(state),
|
||||||
|
@ -70,6 +70,7 @@ const perform = {
|
||||||
doSetPlayingUri,
|
doSetPlayingUri,
|
||||||
doCommentSocketConnect,
|
doCommentSocketConnect,
|
||||||
doCommentSocketDisconnect,
|
doCommentSocketDisconnect,
|
||||||
|
doClearPlayingUri,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default withRouter(connect(select, perform)(FileRenderFloating));
|
export default withRouter(connect(select, perform)(FileRenderFloating));
|
||||||
|
|
|
@ -71,12 +71,13 @@ type Props = {
|
||||||
doSetPlayingUri: ({ uri?: ?string }) => void,
|
doSetPlayingUri: ({ uri?: ?string }) => void,
|
||||||
isCurrentClaimLive?: boolean,
|
isCurrentClaimLive?: boolean,
|
||||||
videoAspectRatio: number,
|
videoAspectRatio: number,
|
||||||
socketConnected: boolean,
|
socketConnection: { connected: ?boolean },
|
||||||
isLivestreamClaim: boolean,
|
isLivestreamClaim: boolean,
|
||||||
geoRestriction: ?GeoRestriction,
|
geoRestriction: ?GeoRestriction,
|
||||||
appDrawerOpen: boolean,
|
appDrawerOpen: boolean,
|
||||||
doCommentSocketConnect: (string, string, string) => void,
|
doCommentSocketConnect: (string, string, string) => void,
|
||||||
doCommentSocketDisconnect: (string, string) => void,
|
doCommentSocketDisconnect: (string, string) => void,
|
||||||
|
doClearPlayingUri: () => void,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function FileRenderFloating(props: Props) {
|
export default function FileRenderFloating(props: Props) {
|
||||||
|
@ -97,7 +98,7 @@ export default function FileRenderFloating(props: Props) {
|
||||||
claimWasPurchased,
|
claimWasPurchased,
|
||||||
nextListUri,
|
nextListUri,
|
||||||
previousListUri,
|
previousListUri,
|
||||||
socketConnected,
|
socketConnection,
|
||||||
isLivestreamClaim,
|
isLivestreamClaim,
|
||||||
doFetchRecommendedContent,
|
doFetchRecommendedContent,
|
||||||
doUriInitiatePlay,
|
doUriInitiatePlay,
|
||||||
|
@ -108,6 +109,7 @@ export default function FileRenderFloating(props: Props) {
|
||||||
appDrawerOpen,
|
appDrawerOpen,
|
||||||
doCommentSocketConnect,
|
doCommentSocketConnect,
|
||||||
doCommentSocketDisconnect,
|
doCommentSocketDisconnect,
|
||||||
|
doClearPlayingUri,
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
const isMobile = useIsMobile();
|
const isMobile = useIsMobile();
|
||||||
|
@ -235,14 +237,25 @@ export default function FileRenderFloating(props: Props) {
|
||||||
|
|
||||||
// Only connect if not yet connected, so for example clicked on an embed instead of accessing
|
// Only connect if not yet connected, so for example clicked on an embed instead of accessing
|
||||||
// from the Livestream page
|
// from the Livestream page
|
||||||
if (!socketConnected) doCommentSocketConnect(uri, channelName, claimId);
|
if (!socketConnection?.connected) {
|
||||||
|
doCommentSocketConnect(uri, channelName, claimId);
|
||||||
|
}
|
||||||
|
|
||||||
// This will be used to disconnect for every case, since this is the main player component
|
// This will be used to disconnect for every case, since this is the main player component
|
||||||
return () => doCommentSocketDisconnect(claimId, channelName);
|
return () => {
|
||||||
|
if (socketConnection?.connected) {
|
||||||
// only listen to socketConnected on initial mount
|
doCommentSocketDisconnect(claimId, channelName);
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
}
|
||||||
}, [channelUrl, claimId, doCommentSocketConnect, doCommentSocketDisconnect, isCurrentClaimLive, uri]);
|
};
|
||||||
|
}, [
|
||||||
|
channelUrl,
|
||||||
|
claimId,
|
||||||
|
doCommentSocketConnect,
|
||||||
|
doCommentSocketDisconnect,
|
||||||
|
isCurrentClaimLive,
|
||||||
|
socketConnection,
|
||||||
|
uri,
|
||||||
|
]);
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
if (playingPrimaryUri || playingUrl || noPlayerHeight) {
|
if (playingPrimaryUri || playingUrl || noPlayerHeight) {
|
||||||
|
@ -310,6 +323,12 @@ export default function FileRenderFloating(props: Props) {
|
||||||
};
|
};
|
||||||
}, [playingUrl]);
|
}, [playingUrl]);
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
if (!primaryUri && !floatingPlayerEnabled && playingUrl && !playingUriSource) {
|
||||||
|
doClearPlayingUri();
|
||||||
|
}
|
||||||
|
}, [doClearPlayingUri, floatingPlayerEnabled, playingUriSource, playingUrl, primaryUri]);
|
||||||
|
|
||||||
if (
|
if (
|
||||||
geoRestriction ||
|
geoRestriction ||
|
||||||
!isPlayable ||
|
!isPlayable ||
|
||||||
|
|
|
@ -427,7 +427,7 @@ export const COMMENT_FETCH_SETTINGS_COMPLETED = 'COMMENT_FETCH_SETTINGS_COMPLETE
|
||||||
export const COMMENT_FETCH_BLOCKED_WORDS_STARTED = 'COMMENT_FETCH_BLOCKED_WORDS_STARTED';
|
export const COMMENT_FETCH_BLOCKED_WORDS_STARTED = 'COMMENT_FETCH_BLOCKED_WORDS_STARTED';
|
||||||
export const COMMENT_FETCH_BLOCKED_WORDS_FAILED = 'COMMENT_FETCH_BLOCKED_WORDS_FAILED';
|
export const COMMENT_FETCH_BLOCKED_WORDS_FAILED = 'COMMENT_FETCH_BLOCKED_WORDS_FAILED';
|
||||||
export const COMMENT_FETCH_BLOCKED_WORDS_COMPLETED = 'COMMENT_FETCH_BLOCKED_WORDS_COMPLETED';
|
export const COMMENT_FETCH_BLOCKED_WORDS_COMPLETED = 'COMMENT_FETCH_BLOCKED_WORDS_COMPLETED';
|
||||||
export const COMMENT_SOCKET_CONNECTED = 'COMMENT_SOCKET_CONNECTED';
|
export const SOCKET_CONNECTED_BY_ID = 'SOCKET_CONNECTED_BY_ID';
|
||||||
export const COMMENT_RECEIVED = 'COMMENT_RECEIVED';
|
export const COMMENT_RECEIVED = 'COMMENT_RECEIVED';
|
||||||
export const COMMENT_SUPER_CHAT_LIST_STARTED = 'COMMENT_SUPER_CHAT_LIST_STARTED';
|
export const COMMENT_SUPER_CHAT_LIST_STARTED = 'COMMENT_SUPER_CHAT_LIST_STARTED';
|
||||||
export const COMMENT_SUPER_CHAT_LIST_COMPLETED = 'COMMENT_SUPER_CHAT_LIST_COMPLETED';
|
export const COMMENT_SUPER_CHAT_LIST_COMPLETED = 'COMMENT_SUPER_CHAT_LIST_COMPLETED';
|
||||||
|
|
|
@ -4,13 +4,14 @@ import { doSetPrimaryUri } from 'redux/actions/content';
|
||||||
import { doUserSetReferrer } from 'redux/actions/user';
|
import { doUserSetReferrer } from 'redux/actions/user';
|
||||||
import { selectUserVerifiedEmail } from 'redux/selectors/user';
|
import { selectUserVerifiedEmail } from 'redux/selectors/user';
|
||||||
import { DISABLE_COMMENTS_TAG } from 'constants/tags';
|
import { DISABLE_COMMENTS_TAG } from 'constants/tags';
|
||||||
import { doCommentSocketConnect } from 'redux/actions/websocket';
|
import { doCommentSocketConnect, doCommentSocketDisconnect } from 'redux/actions/websocket';
|
||||||
import { getChannelIdFromClaim } from 'util/claim';
|
import { getChannelIdFromClaim } from 'util/claim';
|
||||||
import {
|
import {
|
||||||
selectActiveLivestreamForChannel,
|
selectActiveLivestreamForChannel,
|
||||||
selectActiveLivestreamInitialized,
|
selectActiveLivestreamInitialized,
|
||||||
selectCommentSocketConnected,
|
selectSocketConnectionForId,
|
||||||
} from 'redux/selectors/livestream';
|
} from 'redux/selectors/livestream';
|
||||||
|
import { selectIsUriCurrentlyPlaying } from 'redux/selectors/content';
|
||||||
import { doFetchChannelLiveStatus } from 'redux/actions/livestream';
|
import { doFetchChannelLiveStatus } from 'redux/actions/livestream';
|
||||||
import LivestreamPage from './view';
|
import LivestreamPage from './view';
|
||||||
|
|
||||||
|
@ -18,7 +19,7 @@ const select = (state, props) => {
|
||||||
const { uri } = props;
|
const { uri } = props;
|
||||||
|
|
||||||
const claim = selectClaimForUri(state, uri);
|
const claim = selectClaimForUri(state, uri);
|
||||||
const { canonical_url } = claim || {};
|
const { claim_id: claimId, canonical_url } = claim || {};
|
||||||
const channelClaimId = getChannelIdFromClaim(claim);
|
const channelClaimId = getChannelIdFromClaim(claim);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
@ -28,7 +29,8 @@ const select = (state, props) => {
|
||||||
chatDisabled: makeSelectTagInClaimOrChannelForUri(uri, DISABLE_COMMENTS_TAG)(state),
|
chatDisabled: makeSelectTagInClaimOrChannelForUri(uri, DISABLE_COMMENTS_TAG)(state),
|
||||||
activeLivestreamForChannel: selectActiveLivestreamForChannel(state, channelClaimId),
|
activeLivestreamForChannel: selectActiveLivestreamForChannel(state, channelClaimId),
|
||||||
activeLivestreamInitialized: selectActiveLivestreamInitialized(state),
|
activeLivestreamInitialized: selectActiveLivestreamInitialized(state),
|
||||||
socketConnected: selectCommentSocketConnected(state),
|
socketConnection: selectSocketConnectionForId(state, claimId),
|
||||||
|
isStreamPlaying: selectIsUriCurrentlyPlaying(state, uri),
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -36,6 +38,7 @@ const perform = {
|
||||||
doSetPrimaryUri,
|
doSetPrimaryUri,
|
||||||
doUserSetReferrer,
|
doUserSetReferrer,
|
||||||
doCommentSocketConnect,
|
doCommentSocketConnect,
|
||||||
|
doCommentSocketDisconnect,
|
||||||
doFetchChannelLiveStatus,
|
doFetchChannelLiveStatus,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -20,9 +20,11 @@ type Props = {
|
||||||
claim: StreamClaim,
|
claim: StreamClaim,
|
||||||
isAuthenticated: boolean,
|
isAuthenticated: boolean,
|
||||||
uri: string,
|
uri: string,
|
||||||
socketConnected: boolean,
|
socketConnection: { connected: ?boolean },
|
||||||
|
isStreamPlaying: boolean,
|
||||||
doSetPrimaryUri: (uri: ?string) => void,
|
doSetPrimaryUri: (uri: ?string) => void,
|
||||||
doCommentSocketConnect: (string, string, string) => void,
|
doCommentSocketConnect: (uri: string, channelName: string, claimId: string) => void,
|
||||||
|
doCommentSocketDisconnect: (claimId: string, channelName: string) => void,
|
||||||
doFetchChannelLiveStatus: (string) => void,
|
doFetchChannelLiveStatus: (string) => void,
|
||||||
doUserSetReferrer: (string) => void,
|
doUserSetReferrer: (string) => void,
|
||||||
};
|
};
|
||||||
|
@ -38,15 +40,19 @@ export default function LivestreamPage(props: Props) {
|
||||||
claim,
|
claim,
|
||||||
isAuthenticated,
|
isAuthenticated,
|
||||||
uri,
|
uri,
|
||||||
socketConnected,
|
socketConnection,
|
||||||
|
isStreamPlaying,
|
||||||
doSetPrimaryUri,
|
doSetPrimaryUri,
|
||||||
doCommentSocketConnect,
|
doCommentSocketConnect,
|
||||||
|
doCommentSocketDisconnect,
|
||||||
doFetchChannelLiveStatus,
|
doFetchChannelLiveStatus,
|
||||||
doUserSetReferrer,
|
doUserSetReferrer,
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
const isMobile = useIsMobile();
|
const isMobile = useIsMobile();
|
||||||
|
|
||||||
|
const streamPlayingRef = React.useRef();
|
||||||
|
|
||||||
const [activeStreamUri, setActiveStreamUri] = React.useState(false);
|
const [activeStreamUri, setActiveStreamUri] = React.useState(false);
|
||||||
const [showLivestream, setShowLivestream] = React.useState(false);
|
const [showLivestream, setShowLivestream] = React.useState(false);
|
||||||
const [showScheduledInfo, setShowScheduledInfo] = React.useState(false);
|
const [showScheduledInfo, setShowScheduledInfo] = React.useState(false);
|
||||||
|
@ -73,18 +79,33 @@ export default function LivestreamPage(props: Props) {
|
||||||
// On livestream page, only connect, fileRenderFloating will handle disconnect.
|
// On livestream page, only connect, fileRenderFloating will handle disconnect.
|
||||||
// (either by leaving page with floating player off, or by closing the player)
|
// (either by leaving page with floating player off, or by closing the player)
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
if (!claim || socketConnected) return;
|
|
||||||
|
|
||||||
const { claim_id: claimId, signing_channel: channelClaim } = claim;
|
const { claim_id: claimId, signing_channel: channelClaim } = claim;
|
||||||
const channelName = channelClaim && formatLbryChannelName(channelUrl);
|
const channelName = channelClaim && formatLbryChannelName(channelUrl);
|
||||||
|
|
||||||
if (claimId && channelName) {
|
if (claimId && channelName && !socketConnection?.connected) {
|
||||||
doCommentSocketConnect(uri, channelName, claimId);
|
doCommentSocketConnect(uri, channelName, claimId);
|
||||||
}
|
}
|
||||||
|
// willAutoplay mount only
|
||||||
// only listen to socketConnected on initial mount
|
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [channelUrl, claim, doCommentSocketConnect, uri]);
|
}, [channelUrl, claim, doCommentSocketConnect, doCommentSocketDisconnect, socketConnection, uri]);
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
// use for unmount case without triggering render
|
||||||
|
streamPlayingRef.current = isStreamPlaying;
|
||||||
|
}, [isStreamPlaying]);
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
return () => {
|
||||||
|
if (!streamPlayingRef.current) {
|
||||||
|
const { claim_id: claimId, signing_channel: channelClaim } = claim;
|
||||||
|
const channelName = channelClaim && formatLbryChannelName(channelUrl);
|
||||||
|
|
||||||
|
if (claimId && channelName) doCommentSocketDisconnect(claimId, channelName);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
// only on unmount -> leave page
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
}, []);
|
||||||
|
|
||||||
const claimReleaseStartingSoonStatic = () =>
|
const claimReleaseStartingSoonStatic = () =>
|
||||||
releaseTime.isBetween(moment(), moment().add(LIVESTREAM_STARTS_SOON_BUFFER, 'minutes'));
|
releaseTime.isBetween(moment(), moment().add(LIVESTREAM_STARTS_SOON_BUFFER, 'minutes'));
|
||||||
|
|
|
@ -154,31 +154,30 @@ export const doCommentSocketConnect = (uri, channelName, claimId, subCategory) =
|
||||||
dispatch(doFetchChannelLiveStatus(channel_id));
|
dispatch(doFetchChannelLiveStatus(channel_id));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
'comment'
|
`${subCategory || COMMENT_WS_SUBCATEGORIES.VIEWER} comment`
|
||||||
);
|
);
|
||||||
|
|
||||||
dispatch(doSetSocketConnected(true));
|
dispatch(doSetSocketConnection(true, claimId, subCategory || COMMENT_WS_SUBCATEGORIES.VIEWER));
|
||||||
};
|
};
|
||||||
|
|
||||||
export const doCommentSocketDisconnect = (claimId, channelName) => (dispatch) => {
|
export const doCommentSocketDisconnect = (claimId, channelName, subCategory) => (dispatch) => {
|
||||||
const url = getCommentSocketUrl(claimId, channelName);
|
const url =
|
||||||
|
subCategory === COMMENT_WS_SUBCATEGORIES.COMMENTER
|
||||||
|
? getCommentSocketUrlForCommenter(claimId, channelName)
|
||||||
|
: getCommentSocketUrl(claimId, channelName);
|
||||||
|
|
||||||
dispatch(doSocketDisconnect(url));
|
dispatch(doSocketDisconnect(url));
|
||||||
dispatch(doSetSocketConnected(false));
|
dispatch(doSetSocketConnection(false, claimId, subCategory));
|
||||||
};
|
};
|
||||||
|
|
||||||
export const doCommentSocketConnectAsCommenter = (uri, channelName, claimId) => (dispatch) => {
|
export const doCommentSocketConnectAsCommenter = (uri, channelName, claimId) => (dispatch) =>
|
||||||
dispatch(doCommentSocketConnect(uri, channelName, claimId, COMMENT_WS_SUBCATEGORIES.COMMENTER));
|
dispatch(doCommentSocketConnect(uri, channelName, claimId, COMMENT_WS_SUBCATEGORIES.COMMENTER));
|
||||||
};
|
|
||||||
|
|
||||||
export const doCommentSocketDisconnectAsCommenter = (claimId, channelName) => (dispatch) => {
|
export const doCommentSocketDisconnectAsCommenter = (claimId, channelName) => (dispatch) =>
|
||||||
const url = getCommentSocketUrlForCommenter(claimId, channelName);
|
dispatch(doCommentSocketDisconnect(claimId, channelName, COMMENT_WS_SUBCATEGORIES.COMMENTER));
|
||||||
|
|
||||||
dispatch(doSocketDisconnect(url));
|
export const doSetSocketConnection = (connected, id, subCategory) => (dispatch) =>
|
||||||
};
|
|
||||||
|
|
||||||
export const doSetSocketConnected = (connected) => (dispatch) =>
|
|
||||||
dispatch({
|
dispatch({
|
||||||
type: ACTIONS.COMMENT_SOCKET_CONNECTED,
|
type: ACTIONS.SOCKET_CONNECTED_BY_ID,
|
||||||
data: { connected },
|
data: { connected, sub_category: subCategory, id },
|
||||||
});
|
});
|
||||||
|
|
|
@ -11,7 +11,7 @@ const defaultState: LivestreamState = {
|
||||||
activeLivestreamsLastFetchedDate: 0,
|
activeLivestreamsLastFetchedDate: 0,
|
||||||
activeLivestreamsLastFetchedOptions: {},
|
activeLivestreamsLastFetchedOptions: {},
|
||||||
activeLivestreamInitialized: false,
|
activeLivestreamInitialized: false,
|
||||||
commentSocketConnected: false,
|
socketConnectionById: {},
|
||||||
};
|
};
|
||||||
|
|
||||||
function updateViewersById(activeLivestreams, originalState) {
|
function updateViewersById(activeLivestreams, originalState) {
|
||||||
|
@ -90,10 +90,14 @@ export default handleActions(
|
||||||
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 };
|
||||||
},
|
},
|
||||||
[ACTIONS.COMMENT_SOCKET_CONNECTED]: (state: CommentsState, action: any) => ({
|
[ACTIONS.SOCKET_CONNECTED_BY_ID]: (state: LivestreamState, action: any) => {
|
||||||
...state,
|
const { connected, sub_category, id: claimId } = action.data;
|
||||||
commentSocketConnected: action.data.connected,
|
|
||||||
}),
|
const socketConnectionById = Object.assign({}, state.socketConnectionById);
|
||||||
|
socketConnectionById[claimId] = { connected, sub_category };
|
||||||
|
|
||||||
|
return { ...state, socketConnectionById };
|
||||||
|
},
|
||||||
},
|
},
|
||||||
defaultState
|
defaultState
|
||||||
);
|
);
|
||||||
|
|
|
@ -30,8 +30,11 @@ export const selectListShuffle = (state: State) => selectState(state).shuffleLis
|
||||||
export const makeSelectIsPlaying = (uri: string) =>
|
export const makeSelectIsPlaying = (uri: string) =>
|
||||||
createSelector(selectPrimaryUri, (primaryUri) => primaryUri === uri);
|
createSelector(selectPrimaryUri, (primaryUri) => primaryUri === uri);
|
||||||
|
|
||||||
export const makeSelectIsUriCurrentlyPlaying = (uri: string) =>
|
export const selectIsUriCurrentlyPlaying = createSelector(
|
||||||
createSelector(selectPlayingUri, (playingUri) => playingUri.uri === uri);
|
(state, uri) => uri,
|
||||||
|
selectPlayingUri,
|
||||||
|
(uri, playingUri) => Boolean(playingUri.uri === uri)
|
||||||
|
);
|
||||||
|
|
||||||
export const makeSelectIsPlayerFloating = (location: UrlLocation) =>
|
export const makeSelectIsPlayerFloating = (location: UrlLocation) =>
|
||||||
createSelector(selectPrimaryUri, selectPlayingUri, (primaryUri, playingUri) => {
|
createSelector(selectPrimaryUri, selectPlayingUri, (primaryUri, playingUri) => {
|
||||||
|
|
|
@ -12,7 +12,13 @@ export const selectViewersById = (state: State) => selectState(state).viewersByI
|
||||||
export const selectActiveLivestreams = (state: State) => selectState(state).activeLivestreams;
|
export const selectActiveLivestreams = (state: State) => selectState(state).activeLivestreams;
|
||||||
export const selectFetchingActiveLivestreams = (state: State) => selectState(state).fetchingActiveLivestreams;
|
export const selectFetchingActiveLivestreams = (state: State) => selectState(state).fetchingActiveLivestreams;
|
||||||
export const selectActiveLivestreamInitialized = (state: State) => selectState(state).activeLivestreamInitialized;
|
export const selectActiveLivestreamInitialized = (state: State) => selectState(state).activeLivestreamInitialized;
|
||||||
export const selectCommentSocketConnected = (state: State) => selectState(state).commentSocketConnected;
|
export const selectSocketConnectionById = (state: State) => selectState(state).socketConnectionById;
|
||||||
|
|
||||||
|
export const selectSocketConnectionForId = createSelector(
|
||||||
|
(state, claimId) => claimId,
|
||||||
|
selectSocketConnectionById,
|
||||||
|
(claimId, byId) => claimId && byId[claimId]
|
||||||
|
);
|
||||||
|
|
||||||
// select non-pending claims without sources for given channel
|
// select non-pending claims without sources for given channel
|
||||||
export const makeSelectLivestreamsForChannelId = (channelId: string) =>
|
export const makeSelectLivestreamsForChannelId = (channelId: string) =>
|
||||||
|
|
Loading…
Reference in a new issue