feat: add multiplayer feature flag (#6888)
* updated feature flag to type * added feature flag dependency for pointer sharing and editor listing features
This commit is contained in:
parent
49909d24b8
commit
f65ef8ddf3
|
|
@ -1,6 +1,7 @@
|
|||
type FeatureFlag = {
|
||||
COMMENT: boolean;
|
||||
JS_EDITOR: boolean;
|
||||
MULTIPLAYER: boolean;
|
||||
LINTING: boolean;
|
||||
SNIPPET: boolean;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import React, { memo, useCallback } from "react";
|
||||
import store from "store";
|
||||
import store, { useSelector } from "store";
|
||||
import WidgetFactory from "utils/WidgetFactory";
|
||||
import { RenderModes } from "constants/WidgetConstants";
|
||||
import { ContainerWidgetProps } from "widgets/ContainerWidget";
|
||||
|
|
@ -17,6 +17,7 @@ import {
|
|||
APP_COLLAB_EVENTS,
|
||||
NAMESPACE_COLLAB_PAGE_EDIT,
|
||||
} from "constants/AppCollabConstants";
|
||||
import { isMultiplayerEnabledForUser as isMultiplayerEnabledForUserSelector } from "selectors/appCollabSelectors";
|
||||
|
||||
interface CanvasProps {
|
||||
dsl: ContainerWidgetProps<WidgetProps>;
|
||||
|
|
@ -46,12 +47,16 @@ const shareMousePointer = (e: any, pageId: string) => {
|
|||
// TODO(abhinav): get the render mode from context
|
||||
const Canvas = memo((props: CanvasProps) => {
|
||||
const { pageId } = props;
|
||||
const isMultiplayerEnabledForUser = useSelector(
|
||||
isMultiplayerEnabledForUserSelector,
|
||||
);
|
||||
const delayedShareMousePointer = useCallback(
|
||||
throttle((e) => shareMousePointer(e, pageId), 50, {
|
||||
trailing: false,
|
||||
}),
|
||||
[shareMousePointer, pageId],
|
||||
);
|
||||
|
||||
try {
|
||||
return (
|
||||
<>
|
||||
|
|
@ -62,16 +67,19 @@ const Canvas = memo((props: CanvasProps) => {
|
|||
id="art-board"
|
||||
onMouseMove={(e) => {
|
||||
e.persist();
|
||||
if (!isMultiplayerEnabledForUser) return;
|
||||
delayedShareMousePointer(e);
|
||||
}}
|
||||
width={props.dsl.rightColumn}
|
||||
>
|
||||
{props.dsl.widgetId &&
|
||||
WidgetFactory.createWidget(props.dsl, RenderModes.CANVAS)}
|
||||
<CanvasMultiPointerArena
|
||||
pageEditSocket={pageEditSocket}
|
||||
pageId={pageId}
|
||||
/>
|
||||
{isMultiplayerEnabledForUser && (
|
||||
<CanvasMultiPointerArena
|
||||
pageEditSocket={pageEditSocket}
|
||||
pageId={pageId}
|
||||
/>
|
||||
)}
|
||||
</ArtBoard>
|
||||
</>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -57,6 +57,7 @@ import { useLocation } from "react-router";
|
|||
import { setIsGitSyncModalOpen } from "actions/gitSyncActions";
|
||||
import RealtimeAppEditors from "./RealtimeAppEditors";
|
||||
import { EditorSaveIndicator } from "./EditorSaveIndicator";
|
||||
import { isMultiplayerEnabledForUser as isMultiplayerEnabledForUserSelector } from "selectors/appCollabSelectors";
|
||||
|
||||
const HeaderWrapper = styled(StyledHeader)`
|
||||
width: 100%;
|
||||
|
|
@ -227,6 +228,10 @@ export function EditorHeader(props: EditorHeaderProps) {
|
|||
dispatch(setIsGitSyncModalOpen(true));
|
||||
}, [dispatch, setIsGitSyncModalOpen]);
|
||||
|
||||
const isMultiplayerEnabledForUser = useSelector(
|
||||
isMultiplayerEnabledForUserSelector,
|
||||
);
|
||||
|
||||
return (
|
||||
<ThemeProvider theme={props.darkTheme}>
|
||||
<HeaderWrapper>
|
||||
|
|
@ -276,7 +281,9 @@ export function EditorHeader(props: EditorHeaderProps) {
|
|||
</HeaderSection>
|
||||
<HeaderSection>
|
||||
<EditorSaveIndicator />
|
||||
<RealtimeAppEditors applicationId={applicationId} />
|
||||
{isMultiplayerEnabledForUser && (
|
||||
<RealtimeAppEditors applicationId={applicationId} />
|
||||
)}
|
||||
<Boxed step={OnboardingStep.FINISH}>
|
||||
<FormDialogComponent
|
||||
Form={AppInviteUsersForm}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,14 @@
|
|||
import { io } from "socket.io-client";
|
||||
import { eventChannel } from "redux-saga";
|
||||
import { fork, take, call, cancel, put, delay } from "redux-saga/effects";
|
||||
import {
|
||||
fork,
|
||||
take,
|
||||
call,
|
||||
cancel,
|
||||
put,
|
||||
delay,
|
||||
select,
|
||||
} from "redux-saga/effects";
|
||||
import {
|
||||
ReduxActionTypes,
|
||||
ReduxSagaChannels,
|
||||
|
|
@ -17,6 +25,8 @@ import {
|
|||
} from "actions/websocketActions";
|
||||
|
||||
import handleSocketEvent from "./handleSocketEvent";
|
||||
import { isMultiplayerEnabledForUser } from "selectors/appCollabSelectors";
|
||||
import { areCommentsEnabledForUserAndApp } from "selectors/commentsSelectors";
|
||||
|
||||
function connect() {
|
||||
const socket = io();
|
||||
|
|
@ -85,6 +95,10 @@ function* handleIO(socket: any) {
|
|||
|
||||
function* flow() {
|
||||
while (true) {
|
||||
yield take([
|
||||
ReduxActionTypes.FETCH_FEATURE_FLAGS_SUCCESS,
|
||||
ReduxActionTypes.RETRY_WEBSOCKET_CONNECTION, // for manually triggering reconnection
|
||||
]);
|
||||
try {
|
||||
/**
|
||||
* Incase the socket is disconnected due to network latencies
|
||||
|
|
@ -93,13 +107,17 @@ function* flow() {
|
|||
* We only need to retry incase the socket connection isn't made
|
||||
* in the first attempt itself
|
||||
*/
|
||||
const socket = yield call(connect);
|
||||
const task = yield fork(handleIO, socket);
|
||||
yield put(setIsWebsocketConnected(true));
|
||||
yield take([ReduxActionTypes.LOGOUT_USER_INIT]);
|
||||
yield take();
|
||||
yield cancel(task);
|
||||
socket.disconnect();
|
||||
const commentsEnabled = yield select(areCommentsEnabledForUserAndApp);
|
||||
const multiplayerEnabled = yield select(isMultiplayerEnabledForUser);
|
||||
if (commentsEnabled || multiplayerEnabled) {
|
||||
const socket = yield call(connect);
|
||||
const task = yield fork(handleIO, socket);
|
||||
yield put(setIsWebsocketConnected(true));
|
||||
yield take([ReduxActionTypes.LOGOUT_USER_INIT]);
|
||||
yield take();
|
||||
yield cancel(task);
|
||||
socket.disconnect();
|
||||
}
|
||||
} catch (e) {
|
||||
// this has to be non blocking
|
||||
yield fork(function*() {
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import { createSelector } from "reselect";
|
|||
import { AppState } from "reducers";
|
||||
import { AppCollabReducerState } from "reducers/uiReducers/appCollabReducer";
|
||||
import { getCurrentUser } from "./usersSelectors";
|
||||
import getFeatureFlags from "../utils/featureFlags";
|
||||
|
||||
export const getAppCollabState = (state: AppState) => state.ui.appCollab;
|
||||
|
||||
|
|
@ -11,3 +12,5 @@ export const getRealtimeAppEditors = createSelector(
|
|||
(appCollab: AppCollabReducerState, currentUser) =>
|
||||
appCollab.editors.filter((el) => el.email !== currentUser?.email),
|
||||
);
|
||||
|
||||
export const isMultiplayerEnabledForUser = () => getFeatureFlags().MULTIPLAYER;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user