From 97ff46afcdabb241110a7cbe751a1878eba7bf4d Mon Sep 17 00:00:00 2001 From: Vitaly Date: Fri, 17 Oct 2025 19:38:02 +0200 Subject: [PATCH] Drop jitsi --- .../apps/codebattle/assets/js/widgets/App.jsx | 34 +- .../assets/js/widgets/config/jitsiStatuses.js | 9 - .../js/widgets/pages/game/ChatWidget.jsx | 67 +-- .../js/widgets/pages/game/VideoConference.jsx | 57 --- .../pages/game/VideoConferenceButton.jsx | 50 --- .../game/VideoConferenceMediaControls.jsx | 53 --- .../assets/js/widgets/selectors/index.js | 408 +++++++++--------- .../assets/js/widgets/slices/gameUI.js | 10 - .../assets/js/widgets/utils/useJitsiRoom.js | 118 ----- .../codebattle/tournament/upcoming_runner.ex | 4 +- .../controllers/game_controller.ex | 6 - .../templates/game/show.html.heex | 5 - .../lib/codebattle_web/views/game_view.ex | 4 - services/app/config/config.exs | 4 - services/app/config/releases.exs | 4 - 15 files changed, 246 insertions(+), 587 deletions(-) delete mode 100644 services/app/apps/codebattle/assets/js/widgets/config/jitsiStatuses.js delete mode 100644 services/app/apps/codebattle/assets/js/widgets/pages/game/VideoConference.jsx delete mode 100644 services/app/apps/codebattle/assets/js/widgets/pages/game/VideoConferenceButton.jsx delete mode 100644 services/app/apps/codebattle/assets/js/widgets/pages/game/VideoConferenceMediaControls.jsx delete mode 100644 services/app/apps/codebattle/assets/js/widgets/utils/useJitsiRoom.js diff --git a/services/app/apps/codebattle/assets/js/widgets/App.jsx b/services/app/apps/codebattle/assets/js/widgets/App.jsx index bac9c9ea3..9fffe7ef5 100755 --- a/services/app/apps/codebattle/assets/js/widgets/App.jsx +++ b/services/app/apps/codebattle/assets/js/widgets/App.jsx @@ -1,10 +1,7 @@ import React, { Suspense } from 'react'; import NiceModal from '@ebay/nice-modal-react'; -import { - configureStore, - combineReducers, -} from '@reduxjs/toolkit'; +import { configureStore, combineReducers } from '@reduxjs/toolkit'; import { Provider } from 'react-redux'; import { persistStore, persistReducer, PERSIST } from 'redux-persist'; import { PersistGate } from 'redux-persist/integration/react'; @@ -29,7 +26,6 @@ const { gameUI: gameUIReducer, ...otherReducers } = reducers; const gameUIPersistWhitelist = [ 'audioMuted', 'videoMuted', - 'showVideoConferencePanel', 'editorMode', 'editorTheme', 'streamMode', @@ -55,14 +51,18 @@ const rollbarRedux = rollbarMiddleware(rollbar); const store = configureStore({ reducer: rootReducer, middleware: getDefaultMiddleware => getDefaultMiddleware({ - serializableCheck: { ignoredActions: ['ERROR', PERSIST] }, - }).concat(rollbarRedux), + serializableCheck: { ignoredActions: ['ERROR', PERSIST] }, + }).concat(rollbarRedux), }); const persistor = persistStore(store); -const OnlineContainer = React.lazy(() => import('./components/OnlineContainer')); -const InvitesContainer = React.lazy(() => import('./components/InvitesContainer')); +const OnlineContainer = React.lazy( + () => import('./components/OnlineContainer'), +); +const InvitesContainer = React.lazy( + () => import('./components/InvitesContainer'), +); const RoomWidget = React.lazy(() => import('./pages/RoomWidget')); const LobbyWidget = React.lazy(() => import('./pages/lobby')); const RatingList = React.lazy(() => import('./pages/rating')); @@ -71,7 +71,9 @@ const UserSettings = React.lazy(() => import('./pages/settings')); const UserProfile = React.lazy(() => import('./pages/profile')); const Registration = React.lazy(() => import('./pages/registration')); const Tournament = React.lazy(() => import('./pages/tournament')); -const TournamentAdmin = React.lazy(() => import('./pages/tournament/TournamentAdminWidget')); +const TournamentAdmin = React.lazy( + () => import('./pages/tournament/TournamentAdminWidget'), +); const Stream = React.lazy(() => import('./pages/stream/StreamWidget')); const EventWidget = React.lazy(() => import('./pages/event')); const TournamentPlayer = React.lazy(() => import('./pages/tournamentPlayer')); @@ -187,9 +189,7 @@ export const RegistrationPage = () => ( export const StairwayGamePage = () => ( - - {/* */} - + {/* */} ); @@ -198,9 +198,7 @@ export const TournamentPage = () => ( - + @@ -209,9 +207,7 @@ export const TournamentAdminPage = () => ( - + diff --git a/services/app/apps/codebattle/assets/js/widgets/config/jitsiStatuses.js b/services/app/apps/codebattle/assets/js/widgets/config/jitsiStatuses.js deleted file mode 100644 index d9d28893c..000000000 --- a/services/app/apps/codebattle/assets/js/widgets/config/jitsiStatuses.js +++ /dev/null @@ -1,9 +0,0 @@ -const statuses = { - loading: 'loading', - ready: 'ready', - joinedGameRoom: 'joinedGameRoom', - notSupported: 'notSupported', - noHaveApiKey: 'noHaveApiKey', -}; - -export default statuses; diff --git a/services/app/apps/codebattle/assets/js/widgets/pages/game/ChatWidget.jsx b/services/app/apps/codebattle/assets/js/widgets/pages/game/ChatWidget.jsx index 548cfa4a3..bb06355b9 100644 --- a/services/app/apps/codebattle/assets/js/widgets/pages/game/ChatWidget.jsx +++ b/services/app/apps/codebattle/assets/js/widgets/pages/game/ChatWidget.jsx @@ -28,7 +28,6 @@ import useChatRooms from '../../utils/useChatRooms'; import useMachineStateSelector from '../../utils/useMachineStateSelector'; import Notifications from './Notifications'; -import VideoConference from './VideoConference'; function ChatWidget() { const { mainService } = useContext(RoomContext); @@ -39,14 +38,22 @@ function ChatWidget() { const historyMessages = useSelector(selectors.chatHistoryMessagesSelector); const gameMode = useSelector(selectors.gameModeSelector); const useChat = useSelector(selectors.gameUseChatSelector); - const showVideoConferencePanel = useSelector(selectors.showVideoConferencePanelSelector); - const openedReplayer = useMachineStateSelector(mainService, openedReplayerSelector); - const isTestingRoom = useMachineStateSelector(mainService, inTestingRoomSelector); - const isRestricted = useMachineStateSelector(mainService, isRestrictedContentSelector); + const openedReplayer = useMachineStateSelector( + mainService, + openedReplayerSelector, + ); + const isTestingRoom = useMachineStateSelector( + mainService, + inTestingRoomSelector, + ); + const isRestricted = useMachineStateSelector( + mainService, + isRestrictedContentSelector, + ); // const isTournamentGame = (gameMode === GameRoomModes.tournament); - const isStandardGame = (gameMode === GameRoomModes.standard); + const isStandardGame = gameMode === GameRoomModes.standard; const showChatInput = !openedReplayer && !isTestingRoom && !isRestricted && useChat; // const showChatParticipants = !isTestingRoom && useChat && !isRestricted; @@ -73,11 +80,7 @@ function ChatWidget() { const filteredMessages = messages.filter(message => shouldShowMessage(message, activeRoom)); return ( - +
- {showVideoConferencePanel ? ( - - ) : ( - <> - - {openedReplayer - ? ( - - ) : ( - - )} - {showChatInput && } - - )} + <> + + {openedReplayer ? ( + + ) : ( + + )} + {showChatInput && ( + + )} +
diff --git a/services/app/apps/codebattle/assets/js/widgets/pages/game/VideoConference.jsx b/services/app/apps/codebattle/assets/js/widgets/pages/game/VideoConference.jsx deleted file mode 100644 index 5c7fb5b14..000000000 --- a/services/app/apps/codebattle/assets/js/widgets/pages/game/VideoConference.jsx +++ /dev/null @@ -1,57 +0,0 @@ -import React, { - memo, -} from 'react'; - -import cn from 'classnames'; - -import Loading from '@/components/Loading'; -import useJitsiRoom from '@/utils/useJitsiRoom'; - -import i18n from '../../../i18n'; -import statuses from '../../config/jitsiStatuses'; - -const mapStatusToDescription = { - [statuses.loading]: i18n.t('Setup Conference Room'), - [statuses.ready]: i18n.t('Conference Room Is Ready'), - [statuses.joinedGameRoom]: i18n.t('Conference Room Is Started'), - [statuses.notSupported]: i18n.t('Not Supported Browser'), - [statuses.noHaveApiKey]: i18n.t('No have jitsi api key'), -}; - -function ConferenceLoading({ status, hideLoader = false }) { - return ( -
- {!hideLoader && } - {mapStatusToDescription[status]} -
- ); -} - -function VideoConference() { - const { - ref, - status, - } = useJitsiRoom(); - - const loadingClassName = cn('w-100 h-100', { - 'd-flex justify-content-center align-items-center': status !== statuses.joinedGameRoom, - 'd-none invisible absolute': status === statuses.joinedGameRoom, - }); - const conferenceClassName = cn('w-100 h-100', { - 'd-none invisible absolute': status !== statuses.joinedGameRoom, - }); - - return ( - <> -
- -
-
- - ); -} - -export default memo(VideoConference); diff --git a/services/app/apps/codebattle/assets/js/widgets/pages/game/VideoConferenceButton.jsx b/services/app/apps/codebattle/assets/js/widgets/pages/game/VideoConferenceButton.jsx deleted file mode 100644 index 683f51f65..000000000 --- a/services/app/apps/codebattle/assets/js/widgets/pages/game/VideoConferenceButton.jsx +++ /dev/null @@ -1,50 +0,0 @@ -/* global JitsiMeetExternalAPI */ -import React from 'react'; - -import { useDispatch, useSelector } from 'react-redux'; - -import { actions } from '@/slices'; - -import i18n from '../../../i18n'; -import * as selectors from '../../selectors'; - -import VideoConferenceMediaControls from './VideoConferenceMediaControls'; - -function VideoConferenceButton() { - const dispatch = useDispatch(); - const showVideoConferencePanel = useSelector(selectors.showVideoConferencePanelSelector); - - const toggleVideoConference = () => { - dispatch(actions.toggleShowVideoConferencePanel()); - }; - - if (!JitsiMeetExternalAPI) { - return <>; - } - - return ( - <> - - {showVideoConferencePanel && ( - - )} - - ); -} - -export default VideoConferenceButton; diff --git a/services/app/apps/codebattle/assets/js/widgets/pages/game/VideoConferenceMediaControls.jsx b/services/app/apps/codebattle/assets/js/widgets/pages/game/VideoConferenceMediaControls.jsx deleted file mode 100644 index 4e810e920..000000000 --- a/services/app/apps/codebattle/assets/js/widgets/pages/game/VideoConferenceMediaControls.jsx +++ /dev/null @@ -1,53 +0,0 @@ -import React, { useEffect } from 'react'; - -import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import cn from 'classnames'; -import { useDispatch, useSelector } from 'react-redux'; - -import { actions } from '@/slices'; - -import * as selectors from '../../selectors'; - -function VideoConferenceMediaControls() { - const dispatch = useDispatch(); - - const { audioMuted, videoMuted } = useSelector(selectors.videoConferenceSettingsSelector); - const { audioAvailable, videoAvailable } = useSelector(selectors.videoConferenceMediaAvailableSelector); - - useEffect(() => () => { - dispatch(actions.setVideoAvailable(false)); - dispatch(actions.setAudioAvailable(false)); - }, [dispatch]); - - const audioMuteBtnClassName = cn('btn btn-secondary w-100 h-100 rounded-left', { - disabled: !audioAvailable, - }); - const videoMuteBtnClassName = cn('btn btn-secondary w-100 h-100 rounded-right', { - disabled: !videoAvailable, - }); - - return ( -
- - -
- ); -} - -export default VideoConferenceMediaControls; diff --git a/services/app/apps/codebattle/assets/js/widgets/selectors/index.js b/services/app/apps/codebattle/assets/js/widgets/selectors/index.js index 8de0234fd..64aa508f3 100644 --- a/services/app/apps/codebattle/assets/js/widgets/selectors/index.js +++ b/services/app/apps/codebattle/assets/js/widgets/selectors/index.js @@ -33,8 +33,8 @@ export const userByIdSelector = userId => state => state.user.users[userId]; export const userIsAdminSelector = userId => state => !!state.user.users[userId]?.isAdmin; export const subscriptionTypeSelector = state => (currentUserIsAdminSelector(state) - ? SubscriptionTypeCodes.admin - : SubscriptionTypeCodes.premium); + ? SubscriptionTypeCodes.admin + : SubscriptionTypeCodes.premium); export const isShowGuideSelector = state => !!state.gameUI.isShowGuide; @@ -114,15 +114,15 @@ export const editorDataSelector = (playerId, roomMachineState) => state => { } const text = roomMachineState && roomMachineState.matches({ replayer: replayerMachineStates.on }) - ? editorTextsHistory[playerId] - : editorTexts[makeEditorTextKey(playerId, meta.currentLangSlug)]; + ? editorTextsHistory[playerId] + : editorTexts[makeEditorTextKey(playerId, meta.currentLangSlug)]; const currentLangSlug = roomMachineState && roomMachineState.matches({ replayer: replayerMachineStates.on, }) - ? meta.historyCurrentLangSlug - : meta.currentLangSlug; + ? meta.historyCurrentLangSlug + : meta.currentLangSlug; return { ...meta, @@ -153,28 +153,28 @@ export const secondEditorSelector = (state, roomMachineState) => { }; export const leftEditorSelector = roomMachineState => createDraftSafeSelector( - state => state, - state => { - const currentUserId = currentUserIdSelector(state); - const player = get(gamePlayersSelector(state), currentUserId, false); - const editorSelector = !!player && player.type === userTypes.secondPlayer - ? secondEditorSelector - : firstEditorSelector; - return editorSelector(state, roomMachineState); - }, -); + state => state, + state => { + const currentUserId = currentUserIdSelector(state); + const player = get(gamePlayersSelector(state), currentUserId, false); + const editorSelector = !!player && player.type === userTypes.secondPlayer + ? secondEditorSelector + : firstEditorSelector; + return editorSelector(state, roomMachineState); + }, + ); export const rightEditorSelector = roomMachineState => createDraftSafeSelector( - state => state, - state => { - const currentUserId = currentUserIdSelector(state); - const player = get(gamePlayersSelector(state), currentUserId, false); - const editorSelector = !!player && player.type === userTypes.secondPlayer - ? firstEditorSelector - : secondEditorSelector; - return editorSelector(state, roomMachineState); - }, -); + state => state, + state => { + const currentUserId = currentUserIdSelector(state); + const player = get(gamePlayersSelector(state), currentUserId, false); + const editorSelector = !!player && player.type === userTypes.secondPlayer + ? firstEditorSelector + : secondEditorSelector; + return editorSelector(state, roomMachineState); + }, + ); export const currentPlayerTextByLangSelector = lang => state => { const userId = currentUserIdSelector(state); @@ -219,7 +219,7 @@ export const isTaskOwner = state => currentUserIdSelector(state) === state.build || currentUserIdSelector(state) === state.task?.creatorId; export const canEditTaskGenerator = state => (currentUserIdSelector(state) === state.builder.task.creatorId - && state.builder.task.state !== taskStateCodes.moderation) + && state.builder.task.state !== taskStateCodes.moderation) || (currentUserIsAdminSelector(state) && state.builder.task.state !== taskStateCodes.moderation); @@ -246,36 +246,36 @@ export const taskTextSolutionSelector = state => state.builder.textSolution[stat export const taskTextArgumentsGeneratorSelector = state => state.builder.textArgumentsGenerator[state.builder.generatorLang]; export const taskParamsSelector = (params = { normalize: true }) => createDraftSafeSelector( - state => state.builder.task, - state => state.builder.task.inputSignature, - state => state.builder.task.outputSignature, - state => state.builder.task.asserts, - state => state.builder.task.assertsExamples, - state => state.builder.generatorLang, - state => state.builder.textSolution, - state => state.builder.textArgumentsGenerator, - ( - task, - inputSignature, - outputSignature, - asserts, - assertsExamples, - generatorLang, - textSolution, - textArgumentsGenerator, - ) => ({ - ...task, - inputSignature: inputSignature.map(item => (params.normalize ? pick(item, ['argumentName', 'type']) : item)), - outputSignature: params.normalize - ? pick(outputSignature, ['type']) - : outputSignature, - asserts: asserts.map(item => (params.normalize ? pick(item, ['arguments', 'expected']) : item)), - assertsExamples: assertsExamples.map(item => (params.normalize ? pick(item, ['arguments', 'expected']) : item)), - generatorLang, - solution: textSolution[generatorLang], - argumentsGenerator: textArgumentsGenerator[generatorLang], - }), -); + state => state.builder.task, + state => state.builder.task.inputSignature, + state => state.builder.task.outputSignature, + state => state.builder.task.asserts, + state => state.builder.task.assertsExamples, + state => state.builder.generatorLang, + state => state.builder.textSolution, + state => state.builder.textArgumentsGenerator, + ( + task, + inputSignature, + outputSignature, + asserts, + assertsExamples, + generatorLang, + textSolution, + textArgumentsGenerator, + ) => ({ + ...task, + inputSignature: inputSignature.map(item => (params.normalize ? pick(item, ['argumentName', 'type']) : item)), + outputSignature: params.normalize + ? pick(outputSignature, ['type']) + : outputSignature, + asserts: asserts.map(item => (params.normalize ? pick(item, ['arguments', 'expected']) : item)), + assertsExamples: assertsExamples.map(item => (params.normalize ? pick(item, ['arguments', 'expected']) : item)), + generatorLang, + solution: textSolution[generatorLang], + argumentsGenerator: textArgumentsGenerator[generatorLang], + }), + ); export const taskParamsTemplatesStateSelector = state => state.builder.templates.state; @@ -294,9 +294,9 @@ export const editorLangsSelector = state => state.editor.langs; export const langInputSelector = state => state.editor.langInput; export const executionOutputSelector = (playerId, roomMachineState) => state => (roomMachineState - && roomMachineState.matches({ replayer: replayerMachineStates.on }) - ? state.executionOutput.historyResults[playerId] - : state.executionOutput.results[playerId]); + && roomMachineState.matches({ replayer: replayerMachineStates.on }) + ? state.executionOutput.historyResults[playerId] + : state.executionOutput.results[playerId]); export const firstExecutionOutputSelector = roomMachineState => state => { const playerId = firstPlayerSelector(state)?.id; @@ -313,8 +313,8 @@ export const leftExecutionOutputSelector = roomMachineState => state => { const player = get(gamePlayersSelector(state), currentUserId, false); const outputSelector = player.type === userTypes.secondPlayer - ? secondExecutionOutputSelector - : firstExecutionOutputSelector; + ? secondExecutionOutputSelector + : firstExecutionOutputSelector; return outputSelector(roomMachineState)(state); }; @@ -323,108 +323,108 @@ export const rightExecutionOutputSelector = roomMachineState => state => { const player = get(gamePlayersSelector(state), currentUserId, false); const outputSelector = !!player && player.type === userTypes.secondPlayer - ? firstExecutionOutputSelector - : secondExecutionOutputSelector; + ? firstExecutionOutputSelector + : secondExecutionOutputSelector; return outputSelector(roomMachineState)(state); }; export const singlePlayerExecutionOutputSelector = roomMachineState => state => { - const player = singleBattlePlayerSelector(state); + const player = singleBattlePlayerSelector(state); - return player - ? executionOutputSelector(player.id, roomMachineState)(state) - : {}; -}; + return player + ? executionOutputSelector(player.id, roomMachineState)(state) + : {}; + }; export const infoPanelExecutionOutputSelector = (viewMode, roomMachineState) => state => { - if (viewMode === BattleRoomViewModes.duel) { - return leftExecutionOutputSelector(roomMachineState)(state); - } + if (viewMode === BattleRoomViewModes.duel) { + return leftExecutionOutputSelector(roomMachineState)(state); + } - if (viewMode === BattleRoomViewModes.single) { - return singlePlayerExecutionOutputSelector(roomMachineState)(state); - } + if (viewMode === BattleRoomViewModes.single) { + return singlePlayerExecutionOutputSelector(roomMachineState)(state); + } - throw new Error('Invalid view mode for battle room'); -}; + throw new Error('Invalid view mode for battle room'); + }; export const editorsPanelOptionsSelector = (viewMode, roomMachineState) => state => { - const currentUserId = currentUserIdSelector(state); - const editorsMode = editorsModeSelector(state); - const theme = editorsThemeSelector(state); - - if (viewMode === BattleRoomViewModes.duel) { - const leftEditor = leftEditorSelector(roomMachineState)(state); - const rightEditor = rightEditorSelector(roomMachineState)(state); - const leftUserId = leftEditor?.userId; - const rightUserId = rightEditor?.userId; - - const leftUserType = currentUserId === leftUserId - ? editorUserTypes.currentUser - : editorUserTypes.player; - const rightUserType = leftUserType === editorUserTypes.currentUser - ? editorUserTypes.opponent - : editorUserTypes.player; - const leftEditorHeight = editorHeightSelector( - roomMachineState, - leftUserId, - )(state); - const rightEditorHeight = editorHeightSelector( - roomMachineState, - rightUserId, - )(state); - const rightOutput = rightExecutionOutputSelector(roomMachineState)(state); - - const leftEditorParams = { - id: leftUserId, - type: leftUserType, - editorState: leftEditor, - editorHeight: leftEditorHeight, - theme, - editorMode: editorsMode, - }; - const rightEditorParams = { - id: rightUserId, - type: rightUserType, - editorState: rightEditor, - editorHeight: rightEditorHeight, - theme, - editorMode: editorModes.default, - output: rightOutput, - }; - - return [leftEditorParams, rightEditorParams]; - } - - if (viewMode === BattleRoomViewModes.single) { - const player = singleBattlePlayerSelector(state); - - if (!player) return []; - - const { id: userId } = player; - const userType = currentUserId === userId - ? editorUserTypes.currentUser - : editorUserTypes.player; - const editorState = editorDataSelector(userId, roomMachineState)(state); - const editorHeight = editorHeightSelector( - roomMachineState, - userId, - )(state); - - const editorParams = { - id: userId, - type: userType, - editorState, - editorHeight, - theme, - editorMode: editorsMode, - }; - - return [editorParams]; - } - - throw new Error('Invalid view mode for battle room'); -}; + const currentUserId = currentUserIdSelector(state); + const editorsMode = editorsModeSelector(state); + const theme = editorsThemeSelector(state); + + if (viewMode === BattleRoomViewModes.duel) { + const leftEditor = leftEditorSelector(roomMachineState)(state); + const rightEditor = rightEditorSelector(roomMachineState)(state); + const leftUserId = leftEditor?.userId; + const rightUserId = rightEditor?.userId; + + const leftUserType = currentUserId === leftUserId + ? editorUserTypes.currentUser + : editorUserTypes.player; + const rightUserType = leftUserType === editorUserTypes.currentUser + ? editorUserTypes.opponent + : editorUserTypes.player; + const leftEditorHeight = editorHeightSelector( + roomMachineState, + leftUserId, + )(state); + const rightEditorHeight = editorHeightSelector( + roomMachineState, + rightUserId, + )(state); + const rightOutput = rightExecutionOutputSelector(roomMachineState)(state); + + const leftEditorParams = { + id: leftUserId, + type: leftUserType, + editorState: leftEditor, + editorHeight: leftEditorHeight, + theme, + editorMode: editorsMode, + }; + const rightEditorParams = { + id: rightUserId, + type: rightUserType, + editorState: rightEditor, + editorHeight: rightEditorHeight, + theme, + editorMode: editorModes.default, + output: rightOutput, + }; + + return [leftEditorParams, rightEditorParams]; + } + + if (viewMode === BattleRoomViewModes.single) { + const player = singleBattlePlayerSelector(state); + + if (!player) return []; + + const { id: userId } = player; + const userType = currentUserId === userId + ? editorUserTypes.currentUser + : editorUserTypes.player; + const editorState = editorDataSelector(userId, roomMachineState)(state); + const editorHeight = editorHeightSelector( + roomMachineState, + userId, + )(state); + + const editorParams = { + id: userId, + type: userType, + editorState, + editorHeight, + theme, + editorMode: editorsMode, + }; + + return [editorParams]; + } + + throw new Error('Invalid view mode for battle room'); + }; export const userRankingSelector = userId => state => (state.tournament.ranking?.entries || []).find(({ id }) => id === userId); export const tournamentIdSelector = state => state.tournament.id; @@ -468,26 +468,6 @@ export const currentChatUserSelector = state => { export const taskDescriptionLanguageSelector = state => state.gameUI.taskDescriptionLanguage; -export const videoConferenceMediaAvailableSelector = createDraftSafeSelector( - state => state.gameUI.audioAvailable, - state => state.gameUI.videoAvailable, - (audioAvailable, videoAvailable) => ({ - audioAvailable, - videoAvailable, - }), -); - -export const videoConferenceSettingsSelector = createDraftSafeSelector( - state => state.gameUI.audioMuted, - state => state.gameUI.videoMuted, - (audioMuted, videoMuted) => ({ - audioMuted, - videoMuted, - }), -); - -export const showVideoConferencePanelSelector = state => state.gameUI.showVideoConferencePanel; - export const playbookStatusSelector = state => state.playbook.state; export const playbookInitRecordsSelector = state => state.playbook.initRecords; @@ -585,47 +565,47 @@ export const participantDataSelector = state => { // Map event stages to the format needed by the dashboard const stages = event?.stages.map(eventStage => { - const userStage = userEvent?.stages.find( - stage => stage.slug === eventStage.slug, - ); - - // Determine status based on event stage status and user participation - const isStageAvailableForUser = !!( - eventStage.status === 'active' - && ['pending', 'started', null].includes(userStage?.status) - ); - const isUserPassedStage = userStage?.entranceResult === 'passed'; - const gamesCount = userStage?.gamesCount ? userStage.gamesCount : '-'; - const zeroWinsCount = gamesCount === '-' ? '-' : '0'; - const winsCount = userStage?.winsCount - ? userStage.winsCount - : zeroWinsCount; - - return { - status: eventStage.status, - userStatus: userStage?.status, - tournamentId: userStage?.tournamentId, - name: eventStage.name, - dates: eventStage.dates, - isStageAvailableForUser, - isUserPassedStage, - slug: eventStage.slug, - placeInTotalRank: userStage?.placeInTotalRank - ? userStage.placeInTotalRank - : '-', - placeInCategoryRank: userStage?.placeInCategoryRank - ? userStage.placeInCategoryRank - : '-', - gamesCount, - winsCount, - timeSpent: userStage?.timeSpentInSeconds - ? moment.utc(userStage.timeSpentInSeconds * 1000).format('HH:mm:ss') - : '-', - actionButtonText: eventStage.actionButtonText, - confirmationText: eventStage.confirmationText, - type: eventStage.type, - }; - }) || []; + const userStage = userEvent?.stages.find( + stage => stage.slug === eventStage.slug, + ); + + // Determine status based on event stage status and user participation + const isStageAvailableForUser = !!( + eventStage.status === 'active' + && ['pending', 'started', null].includes(userStage?.status) + ); + const isUserPassedStage = userStage?.entranceResult === 'passed'; + const gamesCount = userStage?.gamesCount ? userStage.gamesCount : '-'; + const zeroWinsCount = gamesCount === '-' ? '-' : '0'; + const winsCount = userStage?.winsCount + ? userStage.winsCount + : zeroWinsCount; + + return { + status: eventStage.status, + userStatus: userStage?.status, + tournamentId: userStage?.tournamentId, + name: eventStage.name, + dates: eventStage.dates, + isStageAvailableForUser, + isUserPassedStage, + slug: eventStage.slug, + placeInTotalRank: userStage?.placeInTotalRank + ? userStage.placeInTotalRank + : '-', + placeInCategoryRank: userStage?.placeInCategoryRank + ? userStage.placeInCategoryRank + : '-', + gamesCount, + winsCount, + timeSpent: userStage?.timeSpentInSeconds + ? moment.utc(userStage.timeSpentInSeconds * 1000).format('HH:mm:ss') + : '-', + actionButtonText: eventStage.actionButtonText, + confirmationText: eventStage.confirmationText, + type: eventStage.type, + }; + }) || []; return { stages, diff --git a/services/app/apps/codebattle/assets/js/widgets/slices/gameUI.js b/services/app/apps/codebattle/assets/js/widgets/slices/gameUI.js index 5cbc6ad11..56f0b57ab 100644 --- a/services/app/apps/codebattle/assets/js/widgets/slices/gameUI.js +++ b/services/app/apps/codebattle/assets/js/widgets/slices/gameUI.js @@ -14,7 +14,6 @@ const initialState = { taskDescriptionLanguage: taskDescriptionLanguages.default, showToastActionsAfterGame: false, isShowGuide: false, - showVideoConferencePanel: false, videoMuted: false, audioMuted: false, audioAvailable: false, @@ -51,15 +50,6 @@ const gameUI = createSlice({ toggleStreamMode: state => { state.streamMode = !state.streamMode; }, - toggleShowVideoConferencePanel: state => { - state.showVideoConferencePanel = !state.showVideoConferencePanel; - }, - setAudioMuted: (state, { payload }) => { - state.audioMuted = payload; - }, - setVideoMuted: (state, { payload }) => { - state.videoMuted = payload; - }, setInMainDraw: (state, { payload }) => { state.inMainDraw = payload; }, diff --git a/services/app/apps/codebattle/assets/js/widgets/utils/useJitsiRoom.js b/services/app/apps/codebattle/assets/js/widgets/utils/useJitsiRoom.js deleted file mode 100644 index 5ecbb3aac..000000000 --- a/services/app/apps/codebattle/assets/js/widgets/utils/useJitsiRoom.js +++ /dev/null @@ -1,118 +0,0 @@ -/* global JitsiMeetExternalAPI */ -import { - useEffect, useMemo, useRef, useState, -} from 'react'; - -import Gon from 'gon'; -import { useDispatch, useSelector } from 'react-redux'; - -import { actions } from '@/slices'; - -import statuses from '../config/jitsiStatuses'; -import * as selectors from '../selectors'; - -const apiKey = Gon.getAsset('jitsi_api_key'); - -const useJitsiRoom = () => { - const dispatch = useDispatch(); - - const ref = useRef(); - const [api, setApi] = useState(null); - const [status, setStatus] = useState(statuses.loading); - const userId = useSelector(selectors.currentUserIdSelector); - const gameId = useSelector(selectors.gameIdSelector); - const { name } = useSelector(selectors.userByIdSelector(userId)); - - const { - audioMuted, - videoMuted, - } = useSelector(selectors.videoConferenceSettingsSelector); - - const roomName = gameId ? `${apiKey}/codebattle_game_${gameId}` : `${apiKey}/codebattle_testing`; - - useEffect(() => { - if (!JitsiMeetExternalAPI) { - dispatch(actions.toggleShowVideoConferencePanel()); - } - - if (!apiKey) { - setStatus(statuses.noHaveApiKey); - } - }, [dispatch]); - - useEffect(() => { - if (status === statuses.loading && JitsiMeetExternalAPI && apiKey) { - const newApi = new JitsiMeetExternalAPI('8x8.vc', { - roomName, - parentNode: ref.current, - userInfo: { - displayName: name, - }, - configOverwrite: { - startWithAudioMuted: audioMuted, - startWithVideoMuted: videoMuted, - prejoinPageEnabled: false, - hideConferenceSubject: true, - // hideConferenceTimer: true, - toolbarButtons: [ - 'settings', - ], - }, - }); - - newApi.addListener('browserSupport', payload => { - if (payload.supported) { - setStatus(statuses.ready); - } else { - setStatus(statuses.notSupported); - } - }); - - newApi.addListener('videoConferenceJoined', () => { - newApi.getAvailableDevices().then(devices => { - const { audioInput, videoInput } = devices; - - const audioAvailable = audioInput.some(item => !!item.deviceId); - const videoAvailable = videoInput.some(item => !!item.deviceId); - - dispatch(actions.setAudioAvailable(audioAvailable)); - dispatch(actions.setVideoAvailable(videoAvailable)); - }); - - setStatus(statuses.joinedGameRoom); - }); - - setApi(newApi); - } - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [status]); - - useEffect(() => { - if (api) { - api.isAudioMuted().then(muted => { - if (muted !== audioMuted) { - api.executeCommand('toggleAudio'); - } - }); - } - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [audioMuted]); - - useEffect(() => { - if (api) { - api.isVideoMuted().then(muted => { - if (muted !== videoMuted) { - api.executeCommand('toggleVideo'); - } - }); - } - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [videoMuted]); - - return useMemo(() => ({ - ref, - status, - }), [status]); -}; - -export default useJitsiRoom; diff --git a/services/app/apps/codebattle/lib/codebattle/tournament/upcoming_runner.ex b/services/app/apps/codebattle/lib/codebattle/tournament/upcoming_runner.ex index ad1d69e76..f378b7c54 100644 --- a/services/app/apps/codebattle/lib/codebattle/tournament/upcoming_runner.ex +++ b/services/app/apps/codebattle/lib/codebattle/tournament/upcoming_runner.ex @@ -9,9 +9,9 @@ defmodule Codebattle.Tournament.UpcomingRunner do require Logger @tournament_run_upcoming Application.compile_env(:codebattle, :tournament_run_upcoming) - @worker_timeout to_timeout(second: 3) + @worker_timeout to_timeout(second: 15) - @upcoming_time_before_live_mins 7 + @upcoming_time_before_live_mins 10 @spec start_link([]) :: GenServer.on_start() def start_link(_) do diff --git a/services/app/apps/codebattle/lib/codebattle_web/controllers/game_controller.ex b/services/app/apps/codebattle/lib/codebattle_web/controllers/game_controller.ex index 46f467f77..9fb9e92ed 100644 --- a/services/app/apps/codebattle/lib/codebattle_web/controllers/game_controller.ex +++ b/services/app/apps/codebattle/lib/codebattle_web/controllers/game_controller.ex @@ -73,7 +73,6 @@ defmodule CodebattleWeb.GameController do conn = put_gon(conn, - jitsi_api_key: jitsi_api_key(), reports: maybe_get_reports(conn.assigns.current_user, game.id), game: game_params, game_id: game.id, @@ -106,7 +105,6 @@ defmodule CodebattleWeb.GameController do conn |> put_gon( - jitsi_api_key: jitsi_api_key(), is_record: true, game_id: game.id, game: game_params, @@ -162,10 +160,6 @@ defmodule CodebattleWeb.GameController do end end - defp jitsi_api_key do - Application.get_env(:codebattle, :jitsi_api_key) - end - defp put_game_meta_tags(conn, game) do put_meta_tags(conn, %{ description: game_meta_description(game), diff --git a/services/app/apps/codebattle/lib/codebattle_web/templates/game/show.html.heex b/services/app/apps/codebattle/lib/codebattle_web/templates/game/show.html.heex index 8faa7d978..250dffbb3 100644 --- a/services/app/apps/codebattle/lib/codebattle_web/templates/game/show.html.heex +++ b/services/app/apps/codebattle/lib/codebattle_web/templates/game/show.html.heex @@ -1,8 +1,3 @@ -<%= if load_jitsi?(@user, get_first_player(@game), get_second_player(@game)) do %> - -<% end %> -
<%= if Application.get_env(:codebattle, :html_debug_mode) do %> diff --git a/services/app/apps/codebattle/lib/codebattle_web/views/game_view.ex b/services/app/apps/codebattle/lib/codebattle_web/views/game_view.ex index 783961a20..88450b813 100644 --- a/services/app/apps/codebattle/lib/codebattle_web/views/game_view.ex +++ b/services/app/apps/codebattle/lib/codebattle_web/views/game_view.ex @@ -23,10 +23,6 @@ defmodule CodebattleWeb.GameView do end) end - def load_jitsi?(user, player1, player2) do - Codebattle.User.admin?(user) || player1.id == user.id || player2.id == user.id - end - def csrf_token do Plug.CSRFProtection.get_csrf_token() end diff --git a/services/app/config/config.exs b/services/app/config/config.exs index fbd7950f5..8437d00f5 100644 --- a/services/app/config/config.exs +++ b/services/app/config/config.exs @@ -85,10 +85,6 @@ config :codebattle, fake_html_to_image: false config :codebattle, free_users_redirect_url: "/" config :codebattle, freeze_time: false config :codebattle, html_debug_mode: true - -config :codebattle, - jitsi_api_key: System.get_env("JITSI_API_KEY", "") - config :codebattle, load_dot_env_file: true config :codebattle, store_playbook_async: true config :codebattle, tasks_provider: Codebattle.Game.TasksQueuesServer diff --git a/services/app/config/releases.exs b/services/app/config/releases.exs index 504c8ec92..dbee2370c 100644 --- a/services/app/config/releases.exs +++ b/services/app/config/releases.exs @@ -118,10 +118,6 @@ config :codebattle, config :codebattle, free_users_redirect_url: System.get_env("CODEBATTLE_FREE_USERS_REDIRECT_URL") config :codebattle, host: codebattle_host - -config :codebattle, - jitsi_api_key: System.get_env("JITSI_API_KEY", "") - config :codebattle, k8s_namespace: System.get_env("KUBERNETES_NAMESPACE", "default") config :codebattle, tournament_rematch_timeout_ms: tournament_rematch_timeout_ms