Commit a4e226a0 authored by liujiaxin's avatar liujiaxin

feat:添加检测用户是否开启音视频权限功能

parent 788c9a76
......@@ -115,7 +115,13 @@
"pack:win": "npm run electron:build && electron-builder --win"
},
"eslintConfig": {
"extends": "react-app"
"extends": "react-app",
"rules": {
"jsx-a11y/href-no-hash": "off",
"no-throw-literal": "off",
"react-hooks/rules-of-hooks": "off",
"react-hooks/exhaustive-deps": "off"
}
},
"browserslist": {
"production": [
......
import React, { useEffect, useRef, useState } from 'react';
import React from 'react';
import './toast.scss';
import {useGlobalState, useRoomState} from '../containers/root-container';
import { isEmpty } from 'lodash';
import {roomStore} from "../stores/room";
import { useRoomState} from '../containers/root-container';
// import { isEmpty } from 'lodash';
// import {roomStore} from "../stores/room";
import EmojiEventsIcon from "@material-ui/icons/EmojiEvents";
import {eventBus} from "../stores/EventBus";
import Link from "@material-ui/core/Link";
......@@ -35,7 +35,7 @@ export default function AddStarsButton({type, uid}: AddStarsButtonProps) {
const me = useRoomState().me;
const style = useStyles();
const addStar = async () => {
if (me.role != 'teacher') {
if (me.role !== 'teacher') {
return
}
eventBus.emit('showAddStartDialog', {uid})
......
import React, {useRef, useEffect, useMemo, useState} from 'react';
import Icon from './icon';
import React, {useEffect, useState} from 'react';
// import Icon from './icon';
import './video-player.scss';
import { AgoraElectronStream, StreamType, nativeRTCClient as nativeClient } from '../utils/agora-electron-client';
import { useRoomState } from '../containers/root-container';
import { platform } from '../utils/platform';
// import { AgoraElectronStream, StreamType, nativeRTCClient as nativeClient } from '../utils/agora-electron-client';
// import { useRoomState } from '../containers/root-container';
// import { platform } from '../utils/platform';
import {makeStyles} from "@material-ui/core/styles";
import { endPoint } from '../services/agora-end-points';
const contentMode = 0;
// const contentMode = 0;
const useStyles = makeStyles({
......@@ -45,7 +45,8 @@ const useStyles = makeStyles({
const CourseWareFrame: React.FC = () => {
const classes = useStyles();
// `${ENDPOINT}/airclass_ol?token=${this.userToken}`;
let src = endPoint.getCourseUrl();
const cw_src = endPoint.getCourseUrl();
const [src, setSrc] = useState<string>(cw_src);
let refDom: any = null;
const saveRef = (ref: any) => {refDom = ref};
useEffect(() => {
......@@ -60,15 +61,16 @@ const CourseWareFrame: React.FC = () => {
}
return () => {
src = 'about:blank'
setSrc('about:blank');
console.log('iframe to blank');
}
// eslint-disable-next-line
}, []);
return (
<div ref={saveRef} className={classes.style1}>
{/*<svg viewBox="0 0 0 0"></svg>*/}
<iframe id="cwFrame" src={src} className={classes.frm}></iframe>
<iframe title="courseware-player " id="cwFrame" src={src} className={classes.frm}></iframe>
</div>
)
}
......
......@@ -8,7 +8,7 @@ import {roomStore, windowMonitor} from '../../stores/room';
import {globalStore} from '../../stores/global';
import { useHistory } from 'react-router-dom';
import { RoomMessage } from '../../utils/agora-rtm-client';
import {getApiServerHost, goHome} from "../../services/agora-end-points";
import { goHome} from "../../services/agora-end-points";
interface RoomProps {
onConfirm: (type: string) => void
......
import React, {useEffect, useMemo, useRef, useState} from 'react';
import React, {useMemo} from 'react';
import { useRoomState} from '../containers/root-container';
import { isEmpty } from 'lodash';
import {roomStore} from "../stores/room";
// import { isEmpty } from 'lodash';
// import {roomStore} from "../stores/room";
import PanToolIcon from "@material-ui/icons/PanTool";
import './hands-up-icon.scss';
......@@ -22,11 +22,11 @@ export default function HandsUpIcon({id, streamID}: UserStarsProps) {
// }, [state.handsUpStudents]);
const isHandUp = useMemo(() => {
const hu = roomStore.state.handsUpStudents[streamID];
const hu = state.handsUpStudents[streamID];
console.log(streamID, hu)
return hu
}, [roomStore.state.handsUpStudents]);
// eslint-disable-next-line
}, [state]);
return (
......
......@@ -19,11 +19,10 @@ import { roomStore } from '../stores/room';
import { whiteboard } from '../stores/whiteboard';
import { globalStore } from '../stores/global';
import { platform } from '../utils/platform';
import AgoraWebClient, { SHARE_ID } from '../utils/agora-rtc-client';
import AgoraWebClient from '../utils/agora-rtc-client';
import "white-web-sdk/style/index.css";
import { ViewMode } from 'white-web-sdk';
const pathName = (path: string): string => {
const reg = /\/([^/]*)\//g;
reg.exec(path);
......@@ -183,6 +182,7 @@ const MediaBoard: React.FC<MediaBoardProps> = ({
const isHost = useMemo(() => {
return +roomStore.state.me.uid === +roomStore.state.course.linkId;
// eslint-disable-next-line
}, [roomStore.state.me.uid,
roomStore.state.course.linkId]);
......@@ -247,7 +247,7 @@ const MediaBoard: React.FC<MediaBoardProps> = ({
const showControl: boolean = useMemo(() => {
if (me.role === 'teacher') return true;
return false;
}, []);
}, [me.role]);
const items = [
{
......@@ -294,8 +294,10 @@ const items = [
if (['add', 'folder', 'upload'].indexOf(item.name) === -1) {
return item;
}
return null;
})
}, []);
// eslint-disable-next-line
}, [items]);
const drawable: string = useMemo(() => {
if (location.pathname.match('small-class')) {
......@@ -312,6 +314,7 @@ const items = [
}
}
return 'drawable';
// eslint-disable-next-line
}, [me.role, me.grantBoard, location]);
const [tool, setTool] = useState<string | any>(drawable === 'drawable' ? 'pencil' : '');
......@@ -372,6 +375,7 @@ const items = [
}).catch(console.warn);
}
// eslint-disable-next-line
}, []);
useEffect(() => {
......@@ -436,6 +440,7 @@ const items = [
})
}
*/
// eslint-disable-next-line
}, [rtmState.joined, me.boardId, course.boardId]);
const [uploadPhase, updateUploadPhase] = useState<string>('');
......@@ -443,6 +448,7 @@ const items = [
useEffect(() => {
console.log("[mediaboard] uploadPhase: ", uploadPhase, " convertPhase: ", convertPhase);
// eslint-disable-next-line
}, [uploadPhase, convertPhase]);
const UploadPanel = useCallback(() => {
......@@ -483,6 +489,7 @@ const items = [
}
}}
/>)
// eslint-disable-next-line
}, [tool, room]);
useEffect(() => {
......@@ -524,11 +531,12 @@ const items = [
room.setViewMode(ViewMode.Freedom);
}
}
// eslint-disable-next-line
}, [room, roomStore.state.course.lockBoard, roomStore.state.me.role]);
const globalState = useGlobalState();
const scale = whiteboardState.scale ? whiteboardState.scale : 1;
// const scale = whiteboardState.scale ? whiteboardState.scale : 1;
const UploadProgressView = useCallback(() => {
if (uploadPhase === 'uploading') {
......@@ -583,7 +591,7 @@ const items = [
items={toolItems}
currentTool={tool}
handleToolClick={handleToolClick} />
{tool === 'color_picker' && strokeColor && roomStore.state.me.role == 'teacher'?
{tool === 'color_picker' && strokeColor && roomStore.state.me.role === 'teacher'?
<SketchPicker
color={strokeColor}
onChangeComplete={onColorChanged} />
......
import React, { useRef, useEffect, useMemo } from 'react';
import Icon from './icon';
// import Icon from './icon';
import './member-holder.scss';
import { AgoraElectronStream, StreamType, nativeRTCClient as nativeClient } from '../utils/agora-electron-client';
import { nativeRTCClient as nativeClient } from '../utils/agora-electron-client';
import { useRoomState } from '../containers/root-container';
import { platform } from '../utils/platform';
import AccountCircle from '@material-ui/icons/AccountCircle';
import Link from '@material-ui/core/Link';
import PanToolIcon from '@material-ui/icons/PanTool';
import {roomStore} from "../stores/room";
// import PanToolIcon from '@material-ui/icons/PanTool';
// import {roomStore} from "../stores/room";
import UserStars from "./user-stars";
import {eventBus} from "../stores/EventBus";
// import {eventBus} from "../stores/EventBus";
import AddStarsButton, { StarsButtonType } from './add-stars-btn';
import HandsUpIcon from "./hands-up-icon";
const contentMode = 0;
// const contentMode = 0;
interface MemberHolderProps {
id?: string
......@@ -45,10 +45,11 @@ const MemberHolder: React.FC<MemberHolderProps> = ({
const loadVideo = useRef<boolean>(false);
const loadAudio = useRef<boolean>(false);
const lockPlay = useRef<boolean>(false);
// const lockPlay = useRef<boolean>(false);
const AgoraRtcEngine = useMemo(() => {
return nativeClient.rtcEngine;
// eslint-disable-next-line
}, [nativeClient.rtcEngine]);
/*
useEffect(() => {
......@@ -206,12 +207,13 @@ const MemberHolder: React.FC<MemberHolderProps> = ({
}
}
}, [stream, video, AgoraRtcEngine]);
/*
const onAudioClick = (evt: any) => {
if (handleClick && id) {
handleClick('audio', streamID, id);
}
}
*/
const onStageUp = (evt: any) => {
if (handleClick && id) {
......@@ -219,6 +221,7 @@ const MemberHolder: React.FC<MemberHolderProps> = ({
}
}
/*
const onVideoClick = (evt: any) => {
if (handleClick && id) {
handleClick('video', streamID, id);
......@@ -230,12 +233,14 @@ const MemberHolder: React.FC<MemberHolderProps> = ({
handleClose('close', streamID);
}
}
const addStar = (evt: any) => {
if (me.role != 'teacher') {
return
}
eventBus.emit('showAddStartDialog', {uid: id});
}
*/
const me = useRoomState().me;
return (
......
......@@ -13,8 +13,8 @@ import { isElectron, platform } from '../utils/platform';
import { useRoomState } from '../containers/root-container';
import { roomStore } from '../stores/room';
import { globalStore } from '../stores/global';
import VoiceOverOffIcon from '@material-ui/icons/VoiceOverOff';
import RecordVoiceOverIcon from '@material-ui/icons/RecordVoiceOver';
// import VoiceOverOffIcon from '@material-ui/icons/VoiceOverOff';
// import RecordVoiceOverIcon from '@material-ui/icons/RecordVoiceOver';
import RoomToolsBar from "./room-tools-bar";
interface NavProps {
delay: string
......@@ -123,6 +123,7 @@ export default function NavContainer() {
setTimer(null);
}
}
// eslint-disable-next-line
}, []);
const roomState = useRoomState();
......@@ -169,6 +170,7 @@ export default function NavContainer() {
nativeClient.off('audioquality', () => {});
}
}
// eslint-disable-next-line
}, []);
const courseState = roomState.course.courseState;
......@@ -184,6 +186,7 @@ export default function NavContainer() {
clearInterval(timer);
setTimer(null);
}
// eslint-disable-next-line
}, [courseState]);
const lock = useRef<boolean>(false);
......
import React from 'react';
import { makeStyles } from '@material-ui/core/styles';
import { useGlobalState } from '../containers/root-container';
const useStyles = makeStyles(theme => ({
progress: {
margin: theme.spacing(2),
color: '#44A2FC'
},
container: {
position: 'absolute',
top: '0px',
left: '0px',
height: '100%',
width: '100%',
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
backgroundColor:'rgba(0, 0, 0, 0.5)',
// opacity: 0.8,
zIndex: 10
},
textWrap:{
padding: 32,
}
}));
export const Permission: React.FC<{}> = () => {
const classes = useStyles();
return (
<div className={classes.container}>
<div>
<div className="custom-card">
<div className="flex-item cover">
<div className="preview-video">
<div className="permission-placeholder"></div>
</div>
</div>
<div className="flex-item card">
<div className={classes.textWrap}>
<h3>提示</h3>
<p>请先开启摄像头、麦克风权限,<b>否则将无法正常上课!!!</b></p>
<p><b>第一步</b>:按照如下方法,设置摄像头/麦克风权限为<b>“允许”</b>
点击浏览器地址旁边的小锁头,在弹出的窗口中,设置摄像头/麦克风权限为<b>“允许”</b></p>
<p><b>第二步</b>:设置完成后,根据提示,点击<b>“重新加载”</b></p>
</div>
</div>
</div>
</div>
</div>
);
}
export default function PermissionContainer () {
const state = useGlobalState();
const permission = state.permission;
return (
permission ? <Permission /> : null
)
}
import React, {useMemo, useState} from 'react';
import ChatPanel from './chat/panel';
import StudentList from './student-list';
import useChatText from '../hooks/use-chat-text';
import { VolumeOff, VolumeUp, ImportExport } from '@material-ui/icons';
import React, {useMemo} from 'react';
// import ChatPanel from './chat/panel';
// import StudentList from './student-list';
// import useChatText from '../hooks/use-chat-text';
// import { VolumeOff, VolumeUp, ImportExport } from '@material-ui/icons';
import {roomStore} from "../stores/room";
import {useRoomState} from "../containers/root-container";
import './room-tools-bar.scss';
......@@ -13,8 +13,8 @@ import ImportContacts from "@material-ui/icons/ImportContacts";
import SettingsApplicationsIcon from '@material-ui/icons/SettingsApplications';
import SettingsPowerIcon from '@material-ui/icons/SettingsPower';
import {TOOL_TYPE} from "../utils/types";
import EmojiEventsIcon from '@material-ui/icons/EmojiEvents';
import {eventBus} from "../stores/EventBus";
// import EmojiEventsIcon from '@material-ui/icons/EmojiEvents';
// import {eventBus} from "../stores/EventBus";
import AddStarsButton, {StarsButtonType} from './add-stars-btn';
type Props = {
......@@ -28,7 +28,7 @@ export default function RoomToolsBar (props: any) {
const roomState = useRoomState();
const changeTool = async () => {
console.log(roomStore.state.course.currentTool);
if (roomStore.state.course.currentTool == TOOL_TYPE.WHITEBOARD) {
if (roomStore.state.course.currentTool === TOOL_TYPE.WHITEBOARD) {
await roomStore.setCurrentTool(TOOL_TYPE.COURSE_WARE)
} else {
await roomStore.setCurrentTool(TOOL_TYPE.WHITEBOARD)
......@@ -38,6 +38,7 @@ export default function RoomToolsBar (props: any) {
return {
currentTool: roomStore.state.course.currentTool
}
// eslint-disable-next-line
}, [roomState]);
const {muteAudio} = useMemo(() => {
......@@ -56,15 +57,15 @@ export default function RoomToolsBar (props: any) {
// const allAddStar = async () => {
// eventBus.emit('showAddStartDialog', {uid: 0})
// }
const randomStageUp = async () => {
await roomStore.randomStageUp()
}
// const randomStageUp = async () => {
// await roomStore.randomStageUp()
// }
return (
<>
<div className={'room-tool-box'}>
{roomStore.state.me.role == 'teacher' ?
{roomStore.state.me.role === 'teacher' ?
<>
<AddStarsButton type={StarsButtonType.BIG} uid={0}></AddStarsButton>
{/*<div className="tool-btn" onClick={allAddStar}><EmojiEventsIcon/></div>*/}
......@@ -72,7 +73,7 @@ export default function RoomToolsBar (props: any) {
? <div className="tool-btn" onClick={allMuteOff}><RecordVoiceOverIcon/></div>
: <div onClick={allMuteOn} className="tool-btn"><VoiceOverOffIcon/></div>
}
{currentTool == TOOL_TYPE.WHITEBOARD
{currentTool === TOOL_TYPE.WHITEBOARD
? <div className="tool-btn" onClick={changeTool}><ImportContacts/></div>
: <div onClick={changeTool} className="tool-btn"><Category/></div>
}
......
......@@ -5,7 +5,6 @@ import Button from './custom-button';
import FormSelect from './form-select';
import SpeakerVolume from './volume/speaker';
import useSettingControl from '../hooks/use-setting-control';
import { usePlatform } from '../containers/platform-container';
const useStyles = makeStyles ({
......@@ -34,7 +33,7 @@ export default function (props: SettingProps) {
setCamera,
setMicrophone,
setSpeaker,
volume,
/*volume,*/
speakerVolume,
setSpeakerVolume,
save,
......@@ -77,7 +76,7 @@ export default function (props: SettingProps) {
</div>
<div className="position-content flex-direction-column">
<FormControl className={classes.formControl}>
<FormSelect
<FormSelect
Label={"Camera"}
value={camera}
onChange={changeCamera}
......@@ -85,7 +84,7 @@ export default function (props: SettingProps) {
/>
</FormControl>
<FormControl className={classes.formControl}>
<FormSelect
<FormSelect
Label={"Microphone"}
value={microphone}
onChange={changeMicrophone}
......@@ -94,7 +93,7 @@ export default function (props: SettingProps) {
<MicrophoneVolume />
</FormControl>
<FormControl className={classes.formControl}>
<FormSelect
<FormSelect
Label={"Speaker"}
value={speaker}
onChange={changeSpeaker}
......@@ -116,4 +115,4 @@ export default function (props: SettingProps) {
</div>
</div>
)
}
\ No newline at end of file
}
import React, { useEffect, useRef, useState } from 'react';
import './toast.scss';
import {useGlobalState} from '../containers/root-container';
import { isEmpty } from 'lodash';
// import { isEmpty } from 'lodash';
export interface SnackbarMessage {
message: string;
......@@ -30,6 +30,7 @@ export default function ConsecutiveSnackbars({
timerRef.current = null;
}, duration);
}
// eslint-disable-next-line
}, [messages]);
useEffect(() => {
......@@ -40,11 +41,12 @@ export default function ConsecutiveSnackbars({
})
setMessages([...queueRef.current]);
}
// eslint-disable-next-line
}, [globalState.toast]);
return (
<div className="notice-message-container">
{messages.map((message: any, idx: number) =>
{messages.map((message: any, idx: number) =>
<div key={`${idx}${message.key}`} className={"custom-toast"}>
<div className="toast-container">
<span className="text">{message.message}</span>
......
import React, { useEffect, useRef, useState } from 'react';
import React, { useEffect, useState } from 'react';
import './toast.scss';
import {useGlobalState} from '../containers/root-container';
import { isEmpty } from 'lodash';
// import {useGlobalState} from '../containers/root-container';
// import { isEmpty } from 'lodash';
import {roomStore} from "../stores/room";
......@@ -25,7 +25,8 @@ export default function UserStars({id, streamID}: UserStarsProps) {
}
}
// setStar()
}, [roomStore.state.userStars]);
// eslint-disable-next-line
}, [roomStore.state.userStars, streamID]);
......
import React, {useRef, useEffect, useMemo, useState} from 'react';
import React, {useRef, useEffect, useMemo} from 'react';
import Icon from './icon';
import './video-player.scss';
import { AgoraElectronStream, StreamType, nativeRTCClient as nativeClient } from '../utils/agora-electron-client';
......@@ -8,7 +8,7 @@ import ArrowDownwardIcon from '@material-ui/icons/ArrowDownward';
import {makeStyles} from '@material-ui/core/styles';
import {roomStore} from "../stores/room";
import BuildIcon from '@material-ui/icons/Build';
import {eventBus} from "../stores/EventBus";
// import {eventBus} from "../stores/EventBus";
// import StarIcon from '@material-ui/icons/Star';
// import EmojiEventsOutlinedIcon from '@material-ui/icons/EmojiEventsOutlined';
import UserStars from './user-stars';
......@@ -108,6 +108,7 @@ const VideoPlayer: React.FC<VideoPlayerProps> = ({
const AgoraRtcEngine = useMemo(() => {
return nativeClient.rtcEngine;
// eslint-disable-next-line
}, [nativeClient.rtcEngine]);
useEffect(() => {
......@@ -168,11 +169,13 @@ const VideoPlayer: React.FC<VideoPlayerProps> = ({
}
}
}
// eslint-disable-next-line
}, [domId, stream, AgoraRtcEngine]);
useEffect(() => {
if (platform === 'web') {
if (!stream || !domId || lockPlay.current && stream.isPlaying()) return;
if (!stream || !domId || (lockPlay.current && stream.isPlaying())) return;
lockPlay.current = true;
/*const playFn = () => {
if (reloadStreamTimer) {
......@@ -221,6 +224,7 @@ const VideoPlayer: React.FC<VideoPlayerProps> = ({
local && stream && stream.close();
}
}
// eslint-disable-next-line
}, [domId, stream]);
/*
......@@ -277,6 +281,7 @@ const VideoPlayer: React.FC<VideoPlayerProps> = ({
console.log("[agora-electron] muteLocalAudioStream(true); ", res);
}
}
// eslint-disable-next-line
}, [stream, audio, AgoraRtcEngine]);
useEffect(() => {
......@@ -319,6 +324,7 @@ const VideoPlayer: React.FC<VideoPlayerProps> = ({
console.log("[agora-electron] muteLocalVideoStream(true); ", res);
}
}
// eslint-disable-next-line
}, [stream, video, AgoraRtcEngine]);
const onAudioClick = (evt: any) => {
......@@ -350,16 +356,16 @@ const VideoPlayer: React.FC<VideoPlayerProps> = ({
handleClose('close', streamID);
}
}
const addStar = (evt: any) => {
if (me.role != 'teacher') {
return
}
eventBus.emit('showAddStartDialog', {uid: id});
}
const resumeStream = (evt: any) => {
stateError.current = false;
stream.resume()
}
// const addStar = (evt: any) => {
// if (me.role != 'teacher') {
// return
// }
// eventBus.emit('showAddStartDialog', {uid: id});
// }
// const resumeStream = (evt: any) => {
// stateError.current = false;
// stream.resume()
// }
const me = useRoomState().me;
const teacherId = useRoomState().course.teacherId;
......@@ -372,7 +378,7 @@ return (
{preview ? null :
account ?
<>
{ streamID > 0 && id != teacherId?
{ streamID > 0 && id !== teacherId?
<>
<UserStars id={id} streamID={streamID}></UserStars>
<div className="hands-wrapper">
......@@ -399,7 +405,7 @@ return (
<>
{id != roomStore.state.course.teacherId
{id !== roomStore.state.course.teacherId
?
<>
{/*<EmojiEventsOutlinedIcon onClick={addStar} className={style.emojiEvent}></EmojiEventsOutlinedIcon>*/}
......
import React, { useRef, useEffect, useState, useLayoutEffect } from 'react';
import React, { useRef, useEffect, useState } from 'react';
import VideoPlayer from './video-player';
// import Icon from './icon';
import {ExpandMore, ExpandLess} from '@material-ui/icons';
......@@ -7,8 +7,8 @@ import useStream from '../hooks/use-streams';
import { AgoraMediaStream } from '../utils/types';
import {STAGE_NUM} from "../utils/consts";
import MemberHolder from "./member-holder";
import { Dialog, Button, DialogContent, DialogActions, TextField, DialogContentText, DialogTitle } from '@material-ui/core';
import { roomStore } from '../stores/room';
// import { Dialog, Button, DialogContent, DialogActions, TextField, DialogContentText, DialogTitle } from '@material-ui/core';
// import { roomStore } from '../stores/room';
function VideoShowList() {
......
......@@ -32,6 +32,7 @@ export default function ContinuousSlider(props: SliderProps) {
useEffect(() => {
props.onChange(value);
// eslint-disable-next-line
}, [value]);
return (
......@@ -42,4 +43,4 @@ export default function ContinuousSlider(props: SliderProps) {
</div>
</div>
);
}
\ No newline at end of file
}
import React, { useRef } from 'react';
import React from 'react';
import Icon from '../icon';
import { roomStore } from '../../stores/room';
import { whiteboard } from '../../stores/whiteboard';
import moment from 'moment';
import { globalStore } from '../../stores/global';
import { getOSSUrl } from '../../utils/helper';
// import { roomStore } from '../../stores/room';
// import { whiteboard } from '../../stores/whiteboard';
// import moment from 'moment';
// import { globalStore } from '../../stores/global';
// import { getOSSUrl } from '../../utils/helper';
interface ControlItemProps {
name: string
onClick: (evt: any, name: string) => void
......@@ -58,8 +58,8 @@ export default function Control({
role,
notice,
}: ControlProps) {
const lock = useRef<boolean>(false);
// const lock = useRef<boolean>(false);
/*
const canStop = () => {
const timeMoment = moment(whiteboard.state.startTime).add(15, 'seconds');
if (+timeMoment >= +Date.now()) {
......@@ -70,8 +70,9 @@ export default function Control({
return false;
}
return true;
}
}*/
/*
const onRecordButtonClick = (evt: any, type: string) => {
handleRecording(evt, type)
.then(() => {}).catch(console.warn);
......@@ -124,7 +125,7 @@ export default function Control({
}
}
}
*/
return (
<div className="controls-container">
<div className="interactive">
......
import React from 'react';
import OSS from "ali-oss";
// import OSS from "ali-oss";
import uuidv4 from 'uuid/v4';
import { PPTProgressListener, UploadManager } from "../../../utils/upload-manager";
import { PptKind, Room } from "white-web-sdk";
import {ossConfig, ossClient, resolveFileInfo, getOssClient} from '../../../utils/helper';
import { Room } from "white-web-sdk";
import {ossConfig, resolveFileInfo, getOssClient} from '../../../utils/helper';
import { whiteboard } from '../../../stores/whiteboard';
export type UploadBtnProps = {
......@@ -18,6 +18,7 @@ export const UploadBtn: React.FC<UploadBtnProps> = ({
room, uuid, roomToken,
onProgress, onFailure
}) => {
/*
const uploadDynamic = async (event: any) => {
try {
const file = event.currentTarget.files[0];
......@@ -60,7 +61,7 @@ export const UploadBtn: React.FC<UploadBtnProps> = ({
console.warn(err)
}
}
*/
const uploadImage = async (event: any) => {
try {
const file = event.currentTarget.files[0];
......
import React, { useEffect } from 'react';
import Icon from '../components/icon';
import _, {isFunction} from 'lodash';
import _ from 'lodash';
import { useLocation } from 'react-router';
export interface IPlatformContext {
......@@ -43,7 +43,7 @@ export const PlatformContainer: React.FC<React.ComponentProps<any>> = ({ childre
const handleClick = (type: string) => {
if (!ipc) return;
switch (type) {
case 'minimum': {
ipc.send('minimum');
......@@ -124,4 +124,4 @@ export const PlatformContainer: React.FC<React.ComponentProps<any>> = ({ childre
{children}
</PlatformContext.Provider>
)
}
\ No newline at end of file
}
......@@ -6,7 +6,7 @@ import { useHistory, useLocation } from 'react-router-dom';
import { resolveMessage, resolvePeerMessage, resolveChannelAttrs, jsonParse } from '../utils/helper';
import GlobalStorage from '../utils/custom-storage';
import {endPoint, goHome} from "../services/agora-end-points";
import {Map as immuMap} from "immutable";
// import {Map as immuMap} from "immutable";
export type IRootProvider = {
globalState: GlobalState
......@@ -29,7 +29,7 @@ function useObserver<T>(store: IObserver<T>) {
return () => {
store.unsubscribe();
}
}, []);
}, [store]);
return state;
}
......@@ -114,7 +114,7 @@ export const RootProvider: React.FC<any> = ({children}) => {
}).catch(console.warn);
});
rtmClient.on("AttributesUpdated", (attributes: object) => {
if (Object.keys(attributes).length == 0) {
if (Object.keys(attributes).length === 0) {
globalStore.showToast({
type: 'rtmClient',
message: 'teacher close classroom'
......@@ -165,6 +165,7 @@ export const RootProvider: React.FC<any> = ({children}) => {
return () => {
rtmClient.removeAllListeners();
}
// eslint-disable-next-line
}, [roomStore.state.rtm.joined]);
const location = useLocation();
......@@ -199,7 +200,7 @@ export const RootProvider: React.FC<any> = ({children}) => {
window.whiteboard = whiteboardState;
//@ts-ignore
window.store = globalStore;
// eslint-disable-next-line
}, [value, location]);
return (
......
......@@ -42,7 +42,7 @@ export default function useChatText () {
setValue(evt.target.value.slice(0, 100));
}
const list = useMemo(() => {
if (!roomState.me.uid || !roomState.rtc.users.count() && !roomState.rtc.localStream) return [];
if (!roomState.me.uid || !roomState.rtc.users.count() /*&& !roomState.rtc.localStream*/) return [];
const my = roomState.users.get(roomState.me.uid);
const users = [];
if (my) {
......@@ -55,7 +55,7 @@ export default function useChatText () {
}
}
return users.filter((user: AgoraUser) => user.role === 'student');
}, [roomState.me.uid, roomState.rtc.users, roomState.users, roomState.rtc.localStream]);
}, [roomState.me.uid, roomState.rtc.users, roomState.users/*, roomState.rtc.localStream*/]);
return {
list,
......@@ -66,4 +66,4 @@ export default function useChatText () {
handleChange,
roomName
}
}
\ No newline at end of file
}
......@@ -15,19 +15,19 @@ export default function useSettingControl () {
const cameraList = useMemo(() => {
return devices
.filter((it: Device) =>
.filter((it: Device) =>
it.kind === 'videoinput');
}, [devices]);
const microphoneList = useMemo(() => {
return devices
.filter((it: Device) =>
.filter((it: Device) =>
it.kind === 'audioinput');
}, [devices]);
const speakerList = useMemo(() => {
return devices
.filter((it: Device) =>
.filter((it: Device) =>
it.kind === 'audiooutput');
}, [devices]);
......@@ -43,13 +43,13 @@ export default function useSettingControl () {
const [speakerVolume, setSpeakerVolume] = useState<number>(mediaDevice.speakerVolume);
const [volume, setVolume] = useState<number>(0);
let mounted = false;
const mounted = useRef<boolean>(false);
useEffect(() => {
const rtcClient: AgoraWebClient | AgoraElectronClient = roomStore.rtcClient;
if (!platform || !rtcClient) return;
if (platform === 'web' && !mounted) {
if (platform === 'web' && !mounted.current) {
const webClient = rtcClient as AgoraWebClient;
const onChange = async () => {
const devices: Device[] = await webClient.getDevices();
......@@ -62,13 +62,13 @@ export default function useSettingControl () {
window.addEventListener('devicechange', onChange);
onChange().then(() => {
}).catch(console.warn);
mounted = true;
mounted.current = true;
return () => {
window.removeEventListener('devicechange', onChange);
}
}
if (platform === 'electron' && !mounted) {
if (platform === 'electron' && !mounted.current) {
const nativeClient = rtcClient as AgoraElectronClient;
const onChange = async () => {
......@@ -100,7 +100,7 @@ export default function useSettingControl () {
nativeClient.on('videodevicestatechanged', onChange);
nativeClient.on('audiodevicestatechanged', onChange);
mounted = true;
mounted.current = true;
return () => {
nativeClient.off('videodevicestatechanged', onChange);
nativeClient.off('audiodevicestatechanged', onChange);
......@@ -199,7 +199,7 @@ export default function useSettingControl () {
console.log('startplayback off result', nativeClient.rtcEngine.stopAudioPlaybackDeviceTest());
}
}
}, [stream]);
}, [stream, platform]);
const PreviewPlayer = useCallback(() => {
if (!stream) return null;
......@@ -259,4 +259,4 @@ export default function useSettingControl () {
MicrophoneVolume,
save: handleSave,
}
}
\ No newline at end of file
}
import { useMemo } from 'react';
import { SHARE_ID } from '../utils/agora-rtc-client';
import _ from 'lodash';
// import _ from 'lodash';
import { roomStore } from '../stores/room';
import { useRoomState } from '../containers/root-container';
import {STAGE_NUM} from "../utils/consts";
// import {STAGE_NUM} from "../utils/consts";
type StreamValue ={
teacher: any
......@@ -132,7 +132,7 @@ export default function useStream () {
const studentsOrder = [...roomStore.state.studentsOrder] || [];
// exclude teacher and me
let studentIds = peerUsers.filter((it: number) => studentsOrder.includes(it) && `${it}` !== `${teacherUid}` && `${it}` !== `${me.uid}` && `${it}` !== `${SHARE_ID}`);
if (me.role != 'teacher') {
if (me.role !== 'teacher') {
studentIds = studentIds.add(+me.uid);
}
......@@ -150,11 +150,11 @@ export default function useStream () {
const sids: any = [];
let orderIdx = 0;
for (const ouid of studentsOrder) {
if (ouid == 0) {
if (ouid === 0) {
sids.push(0)
} else {
// find in peer
const uid = studentIds.find((it: number) => `${ouid}` == `${it}`);
const uid = studentIds.find((it: number) => `${ouid}` === `${it}`);
if (uid) {
sids.push(uid);
roomStore.releaseWaitStreamHandle(+uid);
......@@ -193,11 +193,11 @@ export default function useStream () {
// capture all remote streams
for (let studentId of /*studentIds*/sids) {
// console.log('*****************', studentId)
if (studentId == undefined) {
if (studentId === undefined) {
continue
}
if (studentId == 0) {
if (studentId === 0) {
const _tmpStream = {
account: '空闲',
streamID: studentId,
......@@ -220,7 +220,7 @@ export default function useStream () {
continue
}
if (me.role === 'student' && +me.uid == studentId) {
if (me.role === 'student' && +me.uid === studentId) {
if (myAttr && roomState.rtc.localStream) {
// console.log('use local stream')
const _tmpStream = {
......@@ -267,14 +267,14 @@ export default function useStream () {
}
userAttrs.forEach((v, k) => {
if (!sids.includes(+v.uid)) {
if (`${v.uid}` != `${teacherUid}`) {
if (`${v.uid}` !== `${teacherUid}`) {
const s: any = {
streamID: +v.uid,
account: v.account,
video: v.video,
audio: v.audio, // roomState.course.muteAudio ? 0 : v.audio,
}
if (`${me.uid}` == `${v.uid}`) {
if (`${me.uid}` === `${v.uid}`) {
s.local = true;
}
studentStreams.push(s)
......@@ -283,6 +283,7 @@ export default function useStream () {
})
// console.log('studentStreams', studentStreams);
return studentStreams;
// eslint-disable-next-line
}, [
// course,
me.uid,
......@@ -415,6 +416,7 @@ export default function useStream () {
}
}
return null;
// eslint-disable-next-line
}, [
course,
me.uid,
......@@ -458,7 +460,7 @@ export default function useStream () {
if (audio) {
await roomStore.mute(targetUid, 'audio');
} else {
if (me.role == 'student' && roomStore.state.course.muteAudio) {
if (me.role === 'student' && roomStore.state.course.muteAudio) {
return
}
await roomStore.unmute(targetUid, 'audio');
......
......@@ -299,6 +299,27 @@
background-repeat: no-repeat;
opacity: 0.9;
}
.permission-placeholder{
border-top-left-radius: 8px;
border-bottom-left-radius: 8px;
display: flex;
flex: 1 1;
position: absolute;
height: 100%;
width: 100%;
}
.permission-placeholder::before {
content: ' ';
background-image: url(./assets/WechatIMG77.png);
background-position: center;
background-repeat: no-repeat;
//opacity: 0.9;
flex: 1 1;
background-color: #DBE2E5;
justify-content: center;
box-sizing: border-box;
background-size: contain;
}
.media-board.panel {
pointer-events: none;
......
......@@ -5,7 +5,7 @@ import RoomDialog from '../../components/dialog/room';
import { AgoraStream } from '../../utils/types';
import './room.scss';
import NativeSharedWindow from '../../components/native-shared-window';
import { roomStore } from '../../stores/room';
import {roomStore, RTC_STATUS} from '../../stores/room';
import { useRoomState } from '../../containers/root-container';
import { globalStore } from '../../stores/global';
import { platform } from '../../utils/platform';
......@@ -17,7 +17,6 @@ import {
Dialog,
DialogActions,
DialogContent,
DialogContentText,
DialogTitle,
TextField
} from "@material-ui/core";
......@@ -47,19 +46,25 @@ function StarDialog(props: StarDialogProps) {
setTitle(valueProp);
}
}, [valueProp, open]);
const handleChange = (evt: any) => {
console.log('dialog handleChange ');
const val = evt.target.value.match(NUMBER)[0];
if (val) {
setValue(+val);
let val = evt.target.value.match(NUMBER)[0];
val = +val
console.log('dialog handleChange ', val);
if (!val || isNaN(val)) {
setValue(0);
} else {
val = Math.abs(val)
setValue(val);
}
};
const handleEntering = () => {
// console.log('dialog handleEntering ');
onClose(uid, value);
setValue(0)
};
// const handleEntering = () => {
// // console.log('dialog handleEntering ');
// onClose(uid, value);
// setValue(0)
// };
const handleCancel = () => {
console.log('dialog handleCancel ');
......@@ -91,7 +96,7 @@ function StarDialog(props: StarDialogProps) {
margin="dense"
id="starNumber"
label="奖励值"
type="number"
type="text"
value={value || ''}
onChange={handleChange}
fullWidth
......@@ -221,7 +226,7 @@ export function RoomPage({ children }: any) {
.finally(() => {
lock.current = false;
});
}, []);
}, [history]);
/*
......@@ -294,7 +299,7 @@ export function RoomPage({ children }: any) {
const course = roomStore.state.course;
const classroom = Boolean(location.pathname.match(/classroom/));
const isBigClass = Boolean(location.pathname.match(/big-class/));
const isSmallClass = Boolean(location.pathname.match(/small-class/));
// const isSmallClass = Boolean(location.pathname.match(/small-class/));
const prevRoute = useRef<string>(location.pathname);
useEffect(() => {
......@@ -442,6 +447,7 @@ export function RoomPage({ children }: any) {
publishLock.current = false;
}
}
// eslint-disable-next-line
}, [
rtcJoined,
uid,
......@@ -449,6 +455,150 @@ export function RoomPage({ children }: any) {
mediaDevice,
canPublish
]);
const checkPerMission = (status: string) => {
// granted, denied, prompt
if(status === 'granted'){
globalStore.stopPermission();
} else {
globalStore.showPermission();
}
}
useEffect(() => {
console.log('~~~~~~~~~~~~~~~~')
navigator.permissions.query(
// { name: 'camera' }
{ name: 'microphone' }
// { name: 'geolocation' }
// { name: 'notifications' }
// { name: 'midi', sysex: false }
// { name: 'midi', sysex: true }
// { name: 'push', userVisibleOnly: true }
// { name: 'push' } // without userVisibleOnly isn't supported in chrome M45, yet
).then(function(permissionStatus){
checkPerMission(permissionStatus.state);
permissionStatus.onchange = function(){
checkPerMission(this.state);
}
})
navigator.permissions.query(
{ name: 'camera' }
).then(function(permissionStatus){
checkPerMission(permissionStatus.state);
permissionStatus.onchange = function(){
checkPerMission(this.state);
}
})
}, []);
useEffect(() => {
const webClient = roomStore.rtcClient as AgoraWebClient;
if (webClient.joined) {
return;
}
webClient.rtc.on('stream-reconnect-start', (evt: any) => {
console.log('[agora-web] stream-reconnect-start', evt);
});
webClient.rtc.on('connection-state-change', (evt: any) => {
console.log('[agora-web] connection-state-change', evt);
});
webClient.rtc.on('reconnect', (evt: any) => {
console.log('[agora-web] reconnect', evt);
});
webClient.rtc.on('connected', (evt: any) => {
console.log('[agora-web] connected', evt);
});
webClient.rtc.on('stream-fallback', (evt: any) => {
console.log('[agora-web] stream-fallback', evt);
});
webClient.rtc.on('stream-updated', (evt: any) => {
console.log('[agora-web] stream-updated', evt);
});
webClient.rtc.on('exception', (evt: any) => {
console.log('[agora-web] exception', evt);
});
webClient.rtc.on('onTokenPrivilegeWillExpire', (evt: any) => {
// you need obtain the `newToken` token from server side
const newToken = '';
webClient.rtc.renewToken(newToken);
console.log('[agora-web] onTokenPrivilegeWillExpire', evt);
});
webClient.rtc.on('onTokenPrivilegeDidExpire', (evt: any) => {
// you need obtain the `newToken` token from server side
const newToken = '';
webClient.rtc.renewToken(newToken);
console.log('[agora-web] onTokenPrivilegeDidExpire', evt);
});
webClient.rtc.on('error', (evt: any) => {
console.log('[agora-web] error evt', evt);
});
webClient.rtc.on('stream-published', ({ stream }: any) => {
const _stream = new AgoraStream(stream, stream.getId(), true);
roomStore.addLocalStream(_stream);
});
webClient.rtc.on('stream-subscribed', ({ stream }: any) => {
const streamID = stream.getId();
console.log('stream', 2, 'stream-subscribed', streamID)
// when streamID is not share_id use switch high or low stream in dual stream mode
if (/*location.pathname.match(/small-class/) && */streamID !== SHARE_ID) {
if (roomStore.state.course.teacherId
&& roomStore.state.course.teacherId === `${streamID}`) {
webClient.setRemoteVideoStreamType(stream, 0);
console.log("[agora-web] dual stream set high for teacher");
}
else {
webClient.setRemoteVideoStreamType(stream, 1);
console.log("[agora-web] dual stream set low for student");
}
}
console.log('stream step:', 3,'uid', streamID, 'addRemoteStream to play')
const _stream = new AgoraStream(stream, streamID, false);
console.log("[agora-web] subscribe remote stream, id: ", stream.getId());
roomStore.addRemoteStream(_stream);
});
webClient.rtc.on('stream-added', ({ stream }: any) => {
console.log('stream', 1, 'stream-added')
console.log("[agora-web] added remote stream, id: ", stream.getId());
webClient.subscribe(stream);
const uid = stream.getId();
roomStore.setUserStreamStatus(+uid, RTC_STATUS.STREAM_ADDED)
});
webClient.rtc.on('stream-removed', ({ stream }: any) => {
console.log("[agora-web] removed remote stream, id: ", stream.getId(), roomStore.applyUid);
const id = stream.getId();
if (id === roomStore.applyUid) {
globalStore.removeNotice();
roomStore.state.me.role === 'teacher' &&
roomStore.updateCourseLinkUid(0).then(() => {
console.log("update teacher link_uid to 0");
}).catch(console.warn);
}
roomStore.removeRemoteStream(stream.getId());
});
webClient.rtc.on('peer-online', ({uid}: any) => {
console.log("[agora-web] peer-online, id: ", uid);
roomStore.addPeerUser(uid);
});
webClient.rtc.on('peer-leave', ({ uid }: any) => {
console.log("[agora-web] peer-leave, id: ", uid, roomStore.applyUid);
if (uid === roomStore.applyUid) {
globalStore.removeNotice();
me.role === 'teacher' &&
roomStore.updateCourseLinkUid(0).then(() => {
console.log("update teacher link_uid to 0");
}).catch(console.warn);
}
roomStore.removePeerUser(uid);
roomStore.removeRemoteStream(uid);
});
webClient.rtc.on("stream-fallback", ({ uid, attr }: any) => {
const msg = attr === 0 ? 'resume to a&v mode' : 'fallback to audio mode';
console.info(`[agora-web] stream: ${uid} fallback: ${msg}`);
})
// eslint-disable-next-line
}, []);
useEffect(() => {
......@@ -460,107 +610,9 @@ export function RoomPage({ children }: any) {
return;
}
console.log("[agora-rtc] add event listener");
/* origin webClient.rtc.on in here */
webClient.rtc.on('stream-reconnect-start', (evt: any) => {
console.log('[agora-web] stream-reconnect-start', evt);
});
webClient.rtc.on('connection-state-change', (evt: any) => {
console.log('[agora-web] connection-state-change', evt);
});
webClient.rtc.on('reconnect', (evt: any) => {
console.log('[agora-web] reconnect', evt);
});
webClient.rtc.on('connected', (evt: any) => {
console.log('[agora-web] connected', evt);
});
webClient.rtc.on('stream-fallback', (evt: any) => {
console.log('[agora-web] stream-fallback', evt);
});
webClient.rtc.on('stream-updated', (evt: any) => {
console.log('[agora-web] stream-updated', evt);
});
webClient.rtc.on('exception', (evt: any) => {
console.log('[agora-web] exception', evt);
});
webClient.rtc.on('onTokenPrivilegeWillExpire', (evt: any) => {
// you need obtain the `newToken` token from server side
const newToken = '';
webClient.rtc.renewToken(newToken);
console.log('[agora-web] onTokenPrivilegeWillExpire', evt);
});
webClient.rtc.on('onTokenPrivilegeDidExpire', (evt: any) => {
// you need obtain the `newToken` token from server side
const newToken = '';
webClient.rtc.renewToken(newToken);
console.log('[agora-web] onTokenPrivilegeDidExpire', evt);
});
webClient.rtc.on('error', (evt: any) => {
console.log('[agora-web] error evt', evt);
});
webClient.rtc.on('stream-published', ({ stream }: any) => {
const _stream = new AgoraStream(stream, stream.getId(), true);
roomStore.addLocalStream(_stream);
});
webClient.rtc.on('stream-subscribed', ({ stream }: any) => {
const streamID = stream.getId();
console.log('stream', 2, 'stream-subscribed', streamID)
// when streamID is not share_id use switch high or low stream in dual stream mode
if (/*location.pathname.match(/small-class/) && */streamID !== SHARE_ID) {
if (roomStore.state.course.teacherId
&& roomStore.state.course.teacherId === `${streamID}`) {
webClient.setRemoteVideoStreamType(stream, 0);
console.log("[agora-web] dual stream set high for teacher");
}
else {
webClient.setRemoteVideoStreamType(stream, 1);
console.log("[agora-web] dual stream set low for student");
}
}
console.log('stream step:', 3,'uid', streamID, 'addRemoteStream to play')
const _stream = new AgoraStream(stream, streamID, false);
console.log("[agora-web] subscribe remote stream, id: ", stream.getId());
roomStore.addRemoteStream(_stream);
});
webClient.rtc.on('stream-added', ({ stream }: any) => {
console.log('stream', 1, 'stream-added')
console.log("[agora-web] added remote stream, id: ", stream.getId());
webClient.subscribe(stream);
});
webClient.rtc.on('stream-removed', ({ stream }: any) => {
console.log("[agora-web] removed remote stream, id: ", stream.getId(), roomStore.applyUid);
const id = stream.getId();
if (id === roomStore.applyUid) {
globalStore.removeNotice();
roomStore.state.me.role === 'teacher' &&
roomStore.updateCourseLinkUid(0).then(() => {
console.log("update teacher link_uid to 0");
}).catch(console.warn);
}
roomStore.removeRemoteStream(stream.getId());
});
webClient.rtc.on('peer-online', ({uid}: any) => {
console.log("[agora-web] peer-online, id: ", uid);
roomStore.addPeerUser(uid);
});
webClient.rtc.on('peer-leave', ({ uid }: any) => {
console.log("[agora-web] peer-leave, id: ", uid, roomStore.applyUid);
if (uid === roomStore.applyUid) {
globalStore.removeNotice();
me.role === 'teacher' &&
roomStore.updateCourseLinkUid(0).then(() => {
console.log("update teacher link_uid to 0");
}).catch(console.warn);
}
roomStore.removePeerUser(uid);
roomStore.removeRemoteStream(uid);
});
webClient.rtc.on("stream-fallback", ({ uid, attr }: any) => {
const msg = attr === 0 ? 'resume to a&v mode' : 'fallback to audio mode';
console.info(`[agora-web] stream: ${uid} fallback: ${msg}`);
})
rtc.current = true;
// WARN: IF YOU ENABLED APP CERTIFICATE, PLEASE SIGN YOUR TOKEN IN YOUR SERVER SIDE AND OBTAIN IT FROM YOUR OWN TRUSTED SERVER API
......@@ -576,7 +628,7 @@ export function RoomPage({ children }: any) {
}).then(() => {
console.info(2, 'rtc join ok', roomState.me.uid, [...studentsOrder], [...roomStore.state.studentsOrder], [...roomState.studentsOrder])
if (roomState.me.role == 'teacher' || roomStore.state.studentsOrder.includes(+roomState.me.uid)) {
if (roomState.me.role === 'teacher' || roomStore.state.studentsOrder.includes(+roomState.me.uid)) {
roomStore.publishMeStream();
}
......@@ -677,6 +729,7 @@ export function RoomPage({ children }: any) {
*/
}
// eslint-disable-next-line
}, [roomState.me.uid, roomState.course.rid]);
useEffect(() => {
......@@ -685,7 +738,7 @@ export function RoomPage({ children }: any) {
if (!webClient.joined) {
return;
}
if (me.role == 'student') {
if (me.role === 'student') {
if (studentsOrder.includes(+me.uid)) {
console.log(1.15,'stageup?', me.uid, 1111111 );
roomStore.publishMeStream();
......@@ -695,6 +748,7 @@ export function RoomPage({ children }: any) {
}
console.log(1.2 ,studentsOrder, 'studentsOrder changed publish stream');
}
// eslint-disable-next-line
}, [studentsOrder]);
return (
......
import React, {useEffect, useLayoutEffect, useMemo, useRef, useState} from 'react';
import React, {useMemo, useRef} from 'react';
// import VideoMarquee from '../../components/video-marquee';
import MediaBoard from '../../components/mediaboard';
// import Roomboard from '../../components/roomboard';
import './small-class.scss';
import CourseWareFrame from "../../components/courseware-frame";
import VideoShowList from "../../components/video-stage-list";
import {ToolsSwitcherController} from "../../components/tools-switcher-controller";
// import {ToolsSwitcherController} from "../../components/tools-switcher-controller";
import {roomStore} from "../../stores/room";
import {TOOL_TYPE} from "../../utils/types";
// import {platform} from "../../utils/platform";
......@@ -18,19 +18,19 @@ import Icon from "../../components/icon";
export default function SmallClass() {
const [tool, setTool] = useState(true);
// const [tool, setTool] = useState(true);
const roomState = useRoomState();
const changeTool = async () => {
/*const changeTool = async () => {
console.log(roomStore.state.course.currentTool);
if (roomStore.state.course.currentTool == TOOL_TYPE.WHITEBOARD) {
await roomStore.setCurrentTool(TOOL_TYPE.COURSE_WARE)
} else {
await roomStore.setCurrentTool(TOOL_TYPE.WHITEBOARD)
}
}
}*/
const {currentTool} = useMemo(() => {
return {
currentTool: roomStore.state.course.currentTool
currentTool: roomState.course.currentTool
}
}, [roomState]);
......@@ -84,9 +84,7 @@ export default function SmallClass() {
*/
}
useEffect(() => {
}, [roomStore.state.course.currentTool]);
return (
<div className="room-container">
{/*<VideoMarquee />*/}
......@@ -96,16 +94,21 @@ export default function SmallClass() {
{/* changeTool();*/}
{/*}}/> : null}*/}
{currentTool == TOOL_TYPE.WHITEBOARD
{currentTool === TOOL_TYPE.WHITEBOARD
? <MediaBoard />
: <CourseWareFrame></CourseWareFrame>}
<Icon
data='hands_up'
onClick={handleClick}
className={`items hands_up ${false ? 'active' : ''}`}
/>
{
roomStore.state.me.role !== 'teacher'
? <Icon
data='hands_up'
onClick={handleClick}
className={`items hands_up ${false ? 'active' : ''}`}
/>
: null
}
{/*{ roomStore.state.me.role == 'teacher' ? <Roomboard currentActive={'media'} /> : null}*/}
</div>
......
......@@ -98,11 +98,11 @@ function HomePage() {
setClasses([])
return
}
// setLoading(true);
setLoading(true);
globalStore.showLoading();
const data = await endPoint.fetchClasses(session.yourName);
console.log(data);
// setLoading(false);
setLoading(false);
globalStore.stopLoading();
setSessionInfo({
...session,
......@@ -185,9 +185,9 @@ function HomePage() {
// console.log(1111111111111, location );
const params = new URLSearchParams(location.search);
let token:any = params.get('token');
let isDebug = params.get('debug') && params.get('debug') == '1' ? true : false;
let hasLogin = params.get('login') && params.get('login') == '1' ? true : false;
let isLocal = params.get('isLocal') && params.get('isLocal') == '1' ? true : false;
let isDebug = params.get('debug') && params.get('debug') === '1' ? true : false;
let hasLogin = params.get('login') && params.get('login') === '1' ? true : false;
let isLocal = params.get('isLocal') && params.get('isLocal') === '1' ? true : false;
console.log('token', token)
console.log('isDebug', isDebug)
console.log('hasLogin', hasLogin)
......@@ -196,11 +196,11 @@ function HomePage() {
endPoint.setUserToken(token);
const tokenParts = token.split('.')
token = tokenParts[1];
token = token.replace(/[\+]/g, '-');
token = token.replace(/[+]/g, '-');
token = token.replace(/[/]/g, '_');
const eqc = token.length % 4;
const ea: any = [];
if ( eqc != 0 ) {
if ( eqc !== 0 ) {
ea.length = 4 - eqc;
token = `${token}${Array.from(ea).fill('=').join('')}`
}
......
......@@ -6,6 +6,8 @@ import Home from './home';
import DeviceTest from './device-test';
import { RoomPage } from './classroom';
import Loading from '../components/loading';
import Permission from '../components/permission';
import Toast from '../components/toast';
import '../icons.scss';
import { PlatformContainer } from '../containers/platform-container';
......@@ -23,6 +25,7 @@ export default function () {
<PlatformContainer>
<RootProvider>
<Loading />
<Permission />
<Toast />
<Route exact path="/">
<Home />
......@@ -53,4 +56,4 @@ export default function () {
</CustomBrowserRouter>
</ThemeContainer>
)
}
\ No newline at end of file
}
......@@ -147,7 +147,7 @@ class ReplayStore {
phase,
isPlaying,
}
this.commit(this.state);
}
......@@ -160,7 +160,7 @@ class ReplayStore {
this.commit(this.state);
}
async joinRoom(_uuid: string) {
return await WhiteboardAPI.joinRoom(_uuid);
}
......@@ -201,9 +201,9 @@ export const Replay: React.FC<{}> = () => {
const player = useMemo(() => {
if (!store.state || !store.state.player) return null;
return store.state.player as Player;
// eslint-disable-next-line
}, [store.state]);
const handlePlayerClick = () => {
if (!store.state || !player) return;
......@@ -267,6 +267,7 @@ export const Replay: React.FC<{}> = () => {
if (!startTime || !endTime) return 0;
const _duration = Math.abs(+startTime - +endTime);
return _duration;
// eslint-disable-next-line
}, [startTime, endTime]);
const lock = useRef<boolean>(false);
......@@ -275,6 +276,7 @@ export const Replay: React.FC<{}> = () => {
return () => {
lock.current = true;
}
// eslint-disable-next-line
}, []);
useEffect(() => {
......@@ -338,6 +340,7 @@ export const Replay: React.FC<{}> = () => {
window.removeEventListener('resize', onWindowResize);
window.removeEventListener('keydown', onWindowResize);
}
// eslint-disable-next-line
}, []);
const totalTime = useMemo(() => {
......@@ -358,12 +361,14 @@ export const Replay: React.FC<{}> = () => {
return (
<div className="player-cover">
{player.phase === PlayerPhase.Buffering ? <Progress title={"loading..."} />: null}
{player.phase === PlayerPhase.Pause || player.phase === PlayerPhase.Ended || player.phase === PlayerPhase.WaitingFirstFrame ?
{player.phase === PlayerPhase.Pause || player.phase === PlayerPhase.Ended || player.phase === PlayerPhase.WaitingFirstFrame ?
<div className="play-btn" onClick={handlePlayerClick}></div> : null}
</div>
)
// eslint-disable-next-line
}, [player]);
return (
<div className="replay">
<div className={`player-container`} >
......@@ -416,4 +421,4 @@ export const Replay: React.FC<{}> = () => {
</div>
</div>
)
}
\ No newline at end of file
}
......@@ -46,6 +46,7 @@ export interface RoomParams {
export function goHome(history: any){
GlobalStorage.clear('agora_room');
window.onbeforeunload = null;
window.location.href = 'http://iteachabc.com'
}
export function goLogin(){
......
......@@ -12,4 +12,4 @@ module.exports = function (app) {
// changeOrigin: true,
// })
// )
}
\ No newline at end of file
}
......@@ -2,6 +2,7 @@ import {Subject} from 'rxjs';
export type GlobalState = {
loading: boolean
permission: boolean
toast: {
type: string
message: string
......@@ -31,6 +32,7 @@ export class Root {
public state: GlobalState;
public readonly defaultState: GlobalState = {
loading: false,
permission: false,
toast: {
type: '',
message: '',
......@@ -198,6 +200,22 @@ export class Root {
}
this.commit(this.state);
}
showPermission () {
this.state = {
...this.state,
permission: true
}
this.commit(this.state);
}
stopPermission () {
this.state = {
...this.state,
permission: false
}
this.commit(this.state);
}
}
export const globalStore = new Root();
......
......@@ -2,11 +2,11 @@ import {platform} from './../utils/platform';
import {AgoraElectronClient} from './../utils/agora-electron-client';
import {AgoraStream, ChatMessage, TOOL_TYPE} from '../utils/types';
import {Subject} from 'rxjs';
import {List, OrderedMap, OrderedSet, Map as immuMap} from 'immutable';
import {List, OrderedMap, OrderedSet} from 'immutable';
import AgoraRTMClient, {RoomMessage} from '../utils/agora-rtm-client';
import {globalStore} from './global';
import AgoraWebClient from '../utils/agora-rtc-client';
import {get, isEqual} from 'lodash';
import {get} from 'lodash';
import {isElectron} from '../utils/platform';
import GlobalStorage from '../utils/custom-storage';
import {STAGE_NUM} from "../utils/consts";
......@@ -28,7 +28,7 @@ function canJoin({uid, onlineStatus, roomType, channelCount, role}: { uid: any,
// }
const teacher = get(onlineStatus, 'teacher', false);
const totalCount: number = get(onlineStatus, 'totalCount', 0);
// const totalCount: number = get(onlineStatus, 'totalCount', 0);
if (role === 'teacher') {
const isOnline = teacher && `${uid}` !== `${onlineStatus.teacherId}`;
......@@ -53,6 +53,10 @@ const WaitStreamPool = new Map();
// const stageUpStudentTsMap: Map<number, number> = new Map();
const studentsOrderTs: number[] = Array(STAGE_NUM).fill(0);
export enum RTC_STATUS{
PEER_ONLINE, STREAM_PUBLISHED, STREAM_ADDED, STREAM_SUBSCRIBED, STREAM_REMOVED, PEER_LEAVE
}
const userStreamStatus: any = {};
export interface AgoraUser {
uid: string
account: string
......@@ -430,7 +434,7 @@ export class RoomStore {
}
async studentHandsUp(uid: number) {
const hu = this.state.handsUpStudents[uid];
// const hu = this.state.handsUpStudents[uid];
// !hu && !this.state.studentsOrder.includes(uid)
const handleId = setTimeout(() => {
this.cancelHandsUp(uid);
......@@ -463,7 +467,7 @@ export class RoomStore {
const oldestTs = Math.min(...studentsOrderTs);
orderIndex = studentsOrderTs.indexOf(oldestTs);
}
if (studentsOrder[orderIndex] == +uid) {
if (studentsOrder[orderIndex] === +uid) {
return ;
}
......@@ -526,7 +530,7 @@ export class RoomStore {
const downUser: any = [];
users.forEach((u, uid) => {
if (`${u.uid}` != `${this.state.course.teacherId}` && !studentsOrder.includes(+u.uid)) {
if (`${u.uid}` !== `${this.state.course.teacherId}` && !studentsOrder.includes(+u.uid)) {
downUser.push(u);
}
})
......@@ -686,7 +690,7 @@ export class RoomStore {
}
_userIn(uid: number, role = 'student') {
if (role !== 'teacher' && this.state.me.role != 'teacher') {
if (role !== 'teacher' && this.state.me.role !== 'teacher') {
return;
}
const currUser: AgoraUser | undefined = this.state.users.get(`${uid}`);
......@@ -713,7 +717,7 @@ export class RoomStore {
}
}
_userOut(uid: number) {
if (this.state.me.role != 'teacher') {
if (this.state.me.role !== 'teacher') {
return;
}
console.log('userusage _userOut', uid);
......@@ -723,7 +727,7 @@ export class RoomStore {
uc.out = now;
if (uc.in < uc.out) {
let ts = 0;
if (uc.in != 0) {
if (uc.in !== 0) {
ts = uc.out - uc.in;;
}
if (!uc.all) {
......@@ -743,6 +747,7 @@ export class RoomStore {
// if (!userStars[uid]) {
// userStars[uid] = 0;
// }
this.setUserStreamStatus(uid, RTC_STATUS.PEER_ONLINE);
this.state = {
...this.state,
......@@ -761,6 +766,7 @@ export class RoomStore {
if (!uid) {
return;
}
this.deleteUserStreamStatus(uid)
// 如果一个流退了,检测是否是台上人员,移除掉,其实就是下台
// await this.stageDown(`${uid}`)
this.releaseWaitStreamHandle(uid);
......@@ -799,6 +805,19 @@ export class RoomStore {
await this.commit(this.state);
}
setUserStreamStatus(uid: number, status: RTC_STATUS){
userStreamStatus[uid] = status;
}
getUserStreamStatus(uid: number | undefined) {
if (uid) {
return userStreamStatus[uid];
}
return userStreamStatus;
}
deleteUserStreamStatus(uid: number) {
return delete userStreamStatus[uid];
}
async addRemoteStream(stream: AgoraStream) {
// const sod = this.state.studentsOrder;
// const hasMe = sod.indexOf(stream.streamID);
......@@ -806,6 +825,7 @@ export class RoomStore {
// const emptyIndex = sod.indexOf(0);
// sod.splice(emptyIndex, 1, stream.streamID)
// }
roomStore.setUserStreamStatus(stream.streamID, RTC_STATUS.STREAM_SUBSCRIBED)
console.log('remoteStreams added',5 , stream.streamID, this.state.users)
this.state = {
......@@ -817,13 +837,13 @@ export class RoomStore {
// studentsOrder: sod
}
await this.commit(this.state);
if (stream.streamID > 0 && +stream.streamID != +this.state.course.teacherId) {
if (stream.streamID > 0 && +stream.streamID !== +this.state.course.teacherId) {
this.stageUp(''+stream.streamID)
}
}
async removeRemoteStream(uid: number) {
this.setUserStreamStatus(uid, RTC_STATUS.STREAM_REMOVED)
this.state = {
...this.state,
rtc: {
......@@ -1033,7 +1053,7 @@ export class RoomStore {
async unmute(uid: string, type: string) {
// 有一个unmute的时候,就把course里的muteAudio 变成0
if (this.state.me.role == 'teacher') {
if (this.state.me.role === 'teacher') {
this.state = {
...this.state,
course: {
......@@ -1095,12 +1115,12 @@ export class RoomStore {
const channelCount = channelMemberCount[rid];
const channelMeta = await this.rtmClient.getChannelAttributeBy(rid);
console.log('channelMeta', channelMeta)
if (payload.role == 'student' && !channelMeta.teacher) {
if (payload.role === 'student' && !channelMeta.teacher) {
// eslint-disable-next-line
throw {
type: 'not_permitted',
reason: 'classroom not start yet'
}
return
}
let accounts = channelMeta.accounts;
const onlineStatus = await this.rtmClient.queryOnlineStatusBy(accounts);
......@@ -1142,7 +1162,7 @@ export class RoomStore {
let studentsOrder: number[] = channelMeta.studentsOrder || [];
if (result.permitted) {
if (payload.role == 'teacher') {
if (payload.role === 'teacher') {
// const t = this.state.userUsage[payload.uid];
this._userIn(payload.uid, 'teacher')
......@@ -1167,7 +1187,7 @@ export class RoomStore {
*/
}
console.log('login accounts', accounts)
let onlineMe = accounts.find((it: any) => `${it.uid}` == `${payload.uid}`);
let onlineMe = accounts.find((it: any) => `${it.uid}` === `${payload.uid}`);
if (onlineMe) {
payload.video = onlineMe.video;
payload.audio = onlineMe.audio;
......@@ -1182,7 +1202,7 @@ export class RoomStore {
console.log('login payload', payload)
console.log('login studentsOrder', studentsOrder)
let res = await this.rtmClient.join(rid).then(async r => {
await this.rtmClient.join(rid).then(async r => {
this.state = {
...this.state,
rtm: {
......@@ -1207,12 +1227,15 @@ export class RoomStore {
// await this.updateMe({...payload, grantBoard});
// this.commit(this.state);
return;
} else {
await this.rtmClient.logout();
// eslint-disable-next-line
throw {
type: 'not_permitted',
reason: result.reason
}
}
await this.rtmClient.logout();
throw {
type: 'not_permitted',
reason: result.reason
}
}
publishMeStream() {
......@@ -1307,7 +1330,7 @@ export class RoomStore {
chat: user.chat,
grant_board: user.grantBoard,
last_stage_ts: user.lastStageTs,
stars: user.stars
stars: user.stars || 0
}
if (user.role === 'teacher') {
Object.assign(attrs, {
......@@ -1326,7 +1349,7 @@ export class RoomStore {
const data: any = {};
data[key] = attrs;
// await this.rtmClient.addOrUpdateChannelAttributes(data);
let res = await this.rtmClient.updateChannelAttrsByKey(key, attrs);
await this.rtmClient.updateChannelAttrsByKey(key, attrs);
// return res;
}
async allStudentMuteOn(){
......@@ -1423,7 +1446,7 @@ export class RoomStore {
}
}
async lockWaitStreamHandle(streamId: number) {
if (this.state.me.role != 'teacher') {
if (this.state.me.role !== 'teacher') {
return
}
// console.log('waitStreamHandle', streamId);
......@@ -1444,7 +1467,7 @@ export class RoomStore {
}
async updateMe(user: any, studentsOrder: number[] = []) {
const {role, uid, account, rid, video, audio, chat, boardId, linkId, sharedId, muteChat, muteAudio, grantBoard, stars} = user;
let {role, uid, account, /*rid,*/ video, audio, chat, boardId, linkId, sharedId, /*muteChat, muteAudio,*/ grantBoard, stars} = user;
const key = role === 'teacher' ? 'teacher' : uid;
const me = this.state.me;
const attrs = {
......@@ -1454,6 +1477,7 @@ export class RoomStore {
video: me.video,
audio: me.audio,
}
stars = stars || 0;
Object.assign(attrs, {
uid,
account,
......@@ -1511,9 +1535,9 @@ export class RoomStore {
this._userOut(+memberId);
const studentsOrder = [...this.state.studentsOrder];
const userIndex = studentsOrder.indexOf(+memberId);
let rtc = {
...this.state.rtc,
};
// let rtc = {
// ...this.state.rtc,
// };
if (userIndex > -1) {
studentsOrder.splice(userIndex, 1, 0);
studentsOrder[userIndex] = 0;
......@@ -1558,11 +1582,11 @@ export class RoomStore {
async rtmJoinUser(memberId: string) {
console.log('新学生登录', memberId, this.state.studentsOrder);
const data: any = {};
// const data: any = {};
let needUpdate = false;
const newUid = +memberId;
const studentsOrder = [...this.state.studentsOrder];
if (studentsOrder.length != STAGE_NUM) {
if (studentsOrder.length !== STAGE_NUM) {
const len = STAGE_NUM - studentsOrder.length ? STAGE_NUM - studentsOrder.length : 0;
if (len > 0) {
Array(len).forEach(_ =>{
......@@ -1603,7 +1627,7 @@ export class RoomStore {
const newAccData: any = {};
const newUids: number[] = []
newUsers.forEach(([uid, userInfo]) =>{
if (userInfo.role != 'teacher') {
if (userInfo.role !== 'teacher') {
newAccData[uid] = userInfo;
newUids.push(+uid);
}
......@@ -1611,7 +1635,7 @@ export class RoomStore {
const oldUids: number[] = []
oldUsers.forEach( ([uid, userInfo]) => {
if (userInfo.role != 'teacher') {
if (userInfo.role !== 'teacher') {
oldUids.push(+uid)
}
});
......@@ -1652,7 +1676,7 @@ export class RoomStore {
_to2.sort((a, b) => a - b)
const tSOrderStr2 = JSON.stringify(_to2)
console.log(tSOrderStr1, tSOrderStr2);
if (tSOrderStr1 != tSOrderStr2) {
if (tSOrderStr1 !== tSOrderStr2) {
data['studentsOrder'] = [...tSOrder];
console.log('new channel attr to every one');
return data
......@@ -1667,7 +1691,7 @@ export class RoomStore {
async updateRoomAttrs ({teacher, accounts, room, studentsOrder, userStars}: {teacher: any, accounts: any, room: any, studentsOrder: number[], userStars: any}) {
console.log("[agora-board], room: ",teacher, accounts, room, studentsOrder);
const currentRoomUsers = this.state.users.toArray();
const exitUserIds = [];
// const exitUserIds = [];
const users: OrderedMap<string, AgoraUser> = accounts.reduce((acc: OrderedMap<string, AgoraUser>, it: any) => {
roomStore.releaseWaitStreamHandle(it.uid);
return acc.set(it.uid, {
......@@ -1683,10 +1707,10 @@ export class RoomStore {
lockBoard: it.lock_board,
grantBoard: it.grant_board,
lastStageTs: it.last_stage_ts,
stars: it.stars
stars: it.stars || 0
});
}, OrderedMap<string, AgoraUser>());
if (this.state.studentsOrder.length == 0) {
if (this.state.studentsOrder.length === 0) {
this.state.studentsOrder = Array(STAGE_NUM).fill(0)
}
/*
......@@ -1730,7 +1754,7 @@ export class RoomStore {
let cos = JSON.stringify(studentsOrder);
console.log('频道StudentsOrder', newStudentsOrder);
console.log('用户保存StudentsOrder', this.state.studentsOrder);
let updateOrders = false;
// let updateOrders = false;
if (me.role === 'teacher') {
/*
// remove exist user from studentsOrder
......@@ -1765,7 +1789,7 @@ export class RoomStore {
console.log('newInfo', newInfo)
if (newInfo) {
updateOrders = true;
// updateOrders = true;
newStudentsOrder = newInfo['studentsOrder'];
cos = JSON.stringify(newInfo['studentsOrder']);
await this.rtmClient.addOrUpdateChannelAttributes(newInfo);
......@@ -1808,7 +1832,7 @@ export class RoomStore {
userStars
}
console.log('update orders?', cos, uos)
if (cos != uos) {
if (cos !== uos) {
this.state = {
...this.state,
studentsOrder: newStudentsOrder
......@@ -1858,6 +1882,7 @@ export class RoomStore {
ifm.remove()
})
}
/*
const events = [
'onTokenPrivilegeWillExpire',
'onTokenPrivilegeDidExpire',
......@@ -1870,6 +1895,7 @@ export class RoomStore {
'peer-leave',
'stream-fallback'
]
*/
const webClient = roomStore.rtcClient as AgoraWebClient;
// for (let eventName of events) {
// webClient.rtc.off(eventName, () => {});
......@@ -1900,7 +1926,7 @@ export class RoomStore {
console.log('exitAll');
try {
if (this.state.me.role == 'teacher') {
if (this.state.me.role === 'teacher') {
await this.rtmClient.clearChannelAttributes()
} else {
await this.rtmClient.clearChannelAttributesByKeys([`${this.state.me.uid}`]);
......@@ -1909,7 +1935,7 @@ export class RoomStore {
await this.rtmClient.logout();
} catch(e) {}
const webClient = roomStore.rtcClient as AgoraWebClient;
// const webClient = roomStore.rtcClient as AgoraWebClient;
// setTimeout(()=>{
// alert('clear2')
GlobalStorage.clear('agora_room');
......@@ -1953,7 +1979,7 @@ class WindowMonitor {
this.roomStore = roomStore
}
b4Leave(e: any){
if (this.roomStore.state.me.role != 'teacher') {
if (this.roomStore.state.me.role !== 'teacher') {
return
}
return "确定退出吗?";
......@@ -1968,7 +1994,7 @@ class WindowMonitor {
// }
}
leave(){
if (this.roomStore.state.me.role != 'teacher') {
if (this.roomStore.state.me.role !== 'teacher') {
return
}
const userUsage = this.roomStore.getUserUsage();
......@@ -1984,16 +2010,16 @@ class WindowMonitor {
const students: any = [];
Object.values(userUsage).forEach( u => {
let _e = now;
if (u.out != 0 ) {
if (u.out !== 0 ) {
_e = u.out;
}
const time = u.all + (u.in > 0 ? (_e - u.in) : 0);
if (u.role == "student") {
if (u.role === "student") {
students.push({
uid: u.uid,
time
})
} else if (u.role == 'teacher') {
} else if (u.role === 'teacher') {
data.time = time;
data.uid = +this.roomStore.state.course.teacherId;
}
......@@ -2019,7 +2045,7 @@ class WindowMonitor {
return !!window.onbeforeunload;
}
addUnloadEvent(){
if (this.roomStore.state.me.role != 'teacher') {
if (this.roomStore.state.me.role !== 'teacher') {
return
}
if (this.hasUnloadEvent()) {
......@@ -2029,7 +2055,7 @@ class WindowMonitor {
window.onunload = this.leave
}
removeUnloadEvent() {
if (this.roomStore.state.me.role != 'teacher') {
if (this.roomStore.state.me.role !== 'teacher') {
return
}
window.onbeforeunload = null
......
......@@ -37,7 +37,7 @@ export interface SceneResource {
}
const pathName = (path: string): string => {
const reg = /\/([^\/]*)\//g;
const reg = /\/([^/]*)\//g;
reg.exec(path);
if (RegExp.$1 === "aria") {
return "";
......
......@@ -14,7 +14,7 @@ if (AgoraRtcEngine) {
AgoraRtcEngine.setVideoProfile(43, false);
}
const SHARE_ID = 7;
const SHARE_ID = 0;
export interface Stream {
uid: number
......@@ -31,10 +31,12 @@ export class AgoraElectronStream {
public stream: Stream;
public playing: boolean = false;
private domID: string;
public uid: number;
constructor(
public uid: number = uid,
uid: number,
public readonly type: StreamType = StreamType.remote,
) {
this.uid = uid;
this.domID = '';
this.stream = {
uid: this.uid,
......
......@@ -46,7 +46,7 @@ const clientEvents: string[] = [
export const APP_ID = process.env.REACT_APP_AGORA_APP_ID as string;
export const APP_TOKEN = process.env.REACT_APP_AGORA_APP_TOKEN as string;
export const ENABLE_LOG = process.env.REACT_APP_AGORA_LOG as string === "true";
export const SHARE_ID = 65535;
export const SHARE_ID = 0;
const BindEventMap: any = {};
class AgoraRTCClient {
......
......@@ -121,7 +121,11 @@ export default class AgoraRTMClient {
async login (uid: string, token?: string) {
this._channelAttrsKey = uid;
await this._client.login({uid, token});
try{
await this._client.login({uid, token});
} catch (e) {
}
this._client.on("ConnectionStateChanged", (newState: string, reason: string) => {
this._bus.emit("ConnectionStateChanged", {newState, reason});
});
......
......@@ -120,6 +120,7 @@ export class RecordOperator {
if (typeof res.resourceId === "string") {
this.resourceId = res.resourceId;
} else {
// eslint-disable-next-line
throw {
recordingErr: {
message: 'acquire recording failed',
......@@ -129,6 +130,7 @@ export class RecordOperator {
}
}
public async release(): Promise<void> {
this.resourceId = undefined;
this.recordId = undefined;
......@@ -137,6 +139,7 @@ export class RecordOperator {
public async start(): Promise<any> {
if (this.resourceId === undefined) {
// eslint-disable-next-line
throw {
recordingErr: {
message: 'start recording failed',
......@@ -164,6 +167,7 @@ export class RecordOperator {
if (typeof res.sid === "string") {
this.recordId = res.sid;
} else {
// eslint-disable-next-line
throw {
recordingErr: {
message: 'start recording failed',
......@@ -176,6 +180,7 @@ export class RecordOperator {
public async stop(): Promise<any> {
if (this.resourceId === undefined) {
// eslint-disable-next-line
throw {
recordingErr: {
message: 'stop recording failed',
......@@ -184,6 +189,7 @@ export class RecordOperator {
}
}
if (this.recordId === undefined) {
// eslint-disable-next-line
throw {
recordingErr: {
message: 'stop recording failed',
......@@ -216,6 +222,7 @@ export class RecordOperator {
public async query(): Promise<any> {
if (this.resourceId === undefined) {
// eslint-disable-next-line
throw {
recordingErr: {
message: 'query recording failed',
......@@ -224,6 +231,7 @@ export class RecordOperator {
}
}
if (this.recordId === undefined) {
// eslint-disable-next-line
throw {
recordingErr: {
message: 'query recording failed',
......
......@@ -341,6 +341,10 @@ export function resolveChannelAttrs(json: object) {
});
}
for (let student of students) {
student.stars = +student.stars;
if (!student.stars || isNaN(student.stars)) {
student.stars = 0;
}
accounts.push({
role: 'student',
account: student.account,
......
......@@ -27,8 +27,11 @@ export interface AgoraMediaStream {
export class AgoraStream {
constructor(
// eslint-disable-next-line
public readonly stream: any = stream,
// eslint-disable-next-line
public readonly streamID: number = streamID,
// eslint-disable-next-line
public readonly local: boolean = local,
) {
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment