Commit 6236ec53 authored by liujiaxin's avatar liujiaxin

台上位置固定6人。下台为空闲状态

parent da303d2d
...@@ -109,7 +109,7 @@ ...@@ -109,7 +109,7 @@
"electron:copy:web": "cross-env REACT_APP_RUNTIME_PLATFORM=electron react-app-rewired build", "electron:copy:web": "cross-env REACT_APP_RUNTIME_PLATFORM=electron react-app-rewired build",
"electron:copy:electron": "cpx ./app/**/*.js ./build", "electron:copy:electron": "cpx ./app/**/*.js ./build",
"electron:build": "npm run electron:copy:web && npm run electron:copy:electron", "electron:build": "npm run electron:copy:web && npm run electron:copy:electron",
"dev": "cross-env REACT_APP_RUNTIME_PLATFORM=web react-app-rewired start", "dev": "cross-env REACT_APP_RUNTIME_PLATFORM=web react-app-rewired start ",
"build": "cross-env REACT_APP_RUNTIME_PLATFORM=web react-app-rewired build", "build": "cross-env REACT_APP_RUNTIME_PLATFORM=web react-app-rewired build",
"test": "react-app-rewired test --env=jsdom", "test": "react-app-rewired test --env=jsdom",
"analyze": "source-map-explorer 'build/static/js/*.js'", "analyze": "source-map-explorer 'build/static/js/*.js'",
......
...@@ -36,8 +36,8 @@ const useStyles = makeStyles({ ...@@ -36,8 +36,8 @@ const useStyles = makeStyles({
} }
}); });
const CourseWareFrame: React.FC = () => { const CourseWareFrame: React.FC = () => {
const classes = useStyles(); const classes = useStyles();
// `${ENDPOINT}/airclass_ol?token=${this.userToken}`;
const src = endPoint.getCourseUrl(); const src = endPoint.getCourseUrl();
return ( return (
<div className={classes.style1}> <div className={classes.style1}>
......
...@@ -83,8 +83,14 @@ const DialogContainer = () => { ...@@ -83,8 +83,14 @@ const DialogContainer = () => {
const onConfirm = (type: string) => { const onConfirm = (type: string) => {
if (type === 'exitRoom') { if (type === 'exitRoom') {
globalStore.removeDialog(); // debugger
history.push('/'); globalStore.showLoading();
roomStore.exitAll().then(() => {
globalStore.stopLoading();
globalStore.removeDialog();
history.push('/');
})
} }
else if (type === 'apply') { else if (type === 'apply') {
Promise.all([ Promise.all([
...@@ -103,16 +109,16 @@ const DialogContainer = () => { ...@@ -103,16 +109,16 @@ const DialogContainer = () => {
} }
return ( return (
visible ? visible ?
<RoomDialog <RoomDialog
type={dialog.type} type={dialog.type}
desc={dialog.message} desc={dialog.message}
onClose={onClose} onClose={onClose}
onConfirm={onConfirm} onConfirm={onConfirm}
/> : /> :
null null
) )
} }
export default React.memo(DialogContainer); export default React.memo(DialogContainer);
\ No newline at end of file
...@@ -231,7 +231,8 @@ const MemberHolder: React.FC<MemberHolderProps> = ({ ...@@ -231,7 +231,8 @@ const MemberHolder: React.FC<MemberHolderProps> = ({
{account ? {account ?
<div className="user-profile"> <div className="user-profile">
<span className="account">{account}</span> <span className="account">{account}</span>
{me.uid === id || me.role === 'teacher' ? {/*me.uid === id ||*/}
{me.role === 'teacher' ?
<span className="media-btn"> <span className="media-btn">
<Link component="button" onClick={onAudioClick}>{audio ? "静音" : "开麦"}</Link> <Link component="button" onClick={onAudioClick}>{audio ? "静音" : "开麦"}</Link>
{me.role === 'teacher' ? <Link component="button" onClick={onStageUp}>上台</Link> : null} {me.role === 'teacher' ? <Link component="button" onClick={onStageUp}>上台</Link> : null}
......
...@@ -13,7 +13,9 @@ import { isElectron, platform } from '../utils/platform'; ...@@ -13,7 +13,9 @@ import { isElectron, platform } from '../utils/platform';
import { useRoomState } from '../containers/root-container'; import { useRoomState } from '../containers/root-container';
import { roomStore } from '../stores/room'; import { roomStore } from '../stores/room';
import { globalStore } from '../stores/global'; import { globalStore } from '../stores/global';
import VoiceOverOffIcon from '@material-ui/icons/VoiceOverOff';
import RecordVoiceOverIcon from '@material-ui/icons/RecordVoiceOver';
import RoomToolsBar from "./room-tools-bar";
interface NavProps { interface NavProps {
delay: string delay: string
network: string network: string
...@@ -41,7 +43,7 @@ export function Nav ({ ...@@ -41,7 +43,7 @@ export function Nav ({
}: NavProps) { }: NavProps) {
const {NavBtn} = usePlatform(); const {NavBtn} = usePlatform();
const handleFinish = (evt: any) => { const handleFinish = (evt: any) => {
onCardConfirm('setting'); onCardConfirm('setting');
} }
...@@ -51,7 +53,7 @@ export function Nav ({ ...@@ -51,7 +53,7 @@ export function Nav ({
<div className={`nav-container ${isElectron ? 'draggable' : ''}`}> <div className={`nav-container ${isElectron ? 'draggable' : ''}`}>
<div className="class-title"> <div className="class-title">
<span className="room-name">{roomName}</span> <span className="room-name">{roomName}</span>
{role === 'teacher' ? {role === 'teacher' ?
<Button className={`nav-button ${classState ? "stop" : "start"}`} name={classState ? "Class end" : "Class start"} onClick={(evt: any) => { <Button className={`nav-button ${classState ? "stop" : "start"}`} name={classState ? "Class end" : "Class start"} onClick={(evt: any) => {
handleClick("classState") handleClick("classState")
}} /> : null} }} /> : null}
...@@ -68,18 +70,21 @@ export function Nav ({ ...@@ -68,18 +70,21 @@ export function Nav ({
<span className="time">{moment.utc(time).format('HH:mm:ss')}</span> <span className="time">{moment.utc(time).format('HH:mm:ss')}</span>
</div> </div>
<span className="menu-split" /> <span className="menu-split" />
<div className={platform === 'web' ? "btn-group" : 'electron-btn-group' }>
{ roomStore.state.me.role == 'teacher' ? <RoomToolsBar onClick={handleClick} /> : null}
{/*<div className={platform === 'web' ? "btn-group" : 'electron-btn-group' }>
{platform === 'web' ? <Icon className="icon-setting" onClick={(evt: any) => { {platform === 'web' ? <Icon className="icon-setting" onClick={(evt: any) => {
handleClick("setting"); handleClick("setting");
}}/> : null} }}/> : null}
<Icon className="icon-exit" onClick={(evt: any) => { <Icon className="icon-exit" onClick={(evt: any) => {
handleClick("exit"); handleClick("exit");
}} /> }} />
</div> </div> */}
<NavBtn /> <NavBtn />
</div> </div>
</div> </div>
{showSetting ? {showSetting ?
<SettingCard className="internal-card" <SettingCard className="internal-card"
handleFinish={handleFinish} /> : null handleFinish={handleFinish} /> : null
} }
...@@ -228,7 +233,7 @@ export default function NavContainer() { ...@@ -228,7 +233,7 @@ export default function NavContainer() {
} }
return ( return (
<Nav <Nav
role={me.role} role={me.role}
roomName={course.roomName} roomName={course.roomName}
classState={Boolean(course.courseState)} classState={Boolean(course.courseState)}
...@@ -241,4 +246,4 @@ export default function NavContainer() { ...@@ -241,4 +246,4 @@ export default function NavContainer() {
handleClick={handleClick} handleClick={handleClick}
/> />
) )
} }
\ No newline at end of file
.room-tool-box{ .room-tool-box{
right: 10px;
width: 46px;
border: 1px solid #dbe2e5;
bottom: 10px;
cursor: pointer;
display: flex; display: flex;
z-index: 9; flex-direction: row;
position: absolute;
//background: #fff;
box-shadow: 0 2px 4px 0 rgba(0,0,0,.1);
box-sizing: border-box;
align-items: center;
line-height: 42;
user-select: none;
border-radius: 6px;
top: 10px;
flex-direction: column;
height: 90px;
padding: 3px;
background-color: rgba(51, 51, 51, 0.4);
.tool-btn{ .tool-btn{
cursor: pointer; cursor: pointer;
display: flex; display: flex;
height: 38px; height: 32px;
width: 38px; width: 32px;
margin: 2px; margin: 4px;
border-radius: 4px; border-radius: 4px;
background: #565656; //background: #565656;
box-sizing: border-box; box-sizing: border-box;
color: #eee; //color: #eee;
svg { svg {
width: 38px; width: 30px;
height: 38px; height: 30px;
display: block; display: block;
} }
} }
.tool-btn:hover{
background-color: rgba(0, 0, 0, 0.07);
border-radius: 4px;
}
} }
...@@ -6,9 +6,38 @@ import { VolumeOff, VolumeUp, ImportExport } from '@material-ui/icons'; ...@@ -6,9 +6,38 @@ import { VolumeOff, VolumeUp, ImportExport } from '@material-ui/icons';
import {roomStore} from "../stores/room"; import {roomStore} from "../stores/room";
import {useRoomState} from "../containers/root-container"; import {useRoomState} from "../containers/root-container";
import './room-tools-bar.scss'; import './room-tools-bar.scss';
import VoiceOverOffIcon from "@material-ui/icons/VoiceOverOff";
import RecordVoiceOverIcon from "@material-ui/icons/RecordVoiceOver";
import Category from "@material-ui/icons/Category";
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";
type Props = {
// zoomScale: number
// zoomChange: (scale: number) => void
onClick: (type: string) => void
// onClickBoardLock: () => void
};
export default function RoomToolsBar (props: any) { export default function RoomToolsBar (props: any) {
// export const RoomToolsBar: React.FC<Props> = ({onClick}) => {
const roomState = useRoomState(); const roomState = useRoomState();
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
}
}, [roomState]);
const {muteAudio} = useMemo(() => { const {muteAudio} = useMemo(() => {
return { return {
muteAudio: roomState.course.muteAudio muteAudio: roomState.course.muteAudio
...@@ -25,11 +54,27 @@ export default function RoomToolsBar (props: any) { ...@@ -25,11 +54,27 @@ export default function RoomToolsBar (props: any) {
const randomStageUp = async () => { const randomStageUp = async () => {
await roomStore.randomStageUp() await roomStore.randomStageUp()
} }
return ( return (
<> <>
<div className={'room-tool-box'}> <div className={'room-tool-box'}>
{muteAudio ? <div className="tool-btn" onClick={audioOn}><VolumeUp></VolumeUp></div> : <div onClick={audioOff} className="tool-btn"><VolumeOff></VolumeOff></div> }
<div className="tool-btn"><ImportExport onClick={randomStageUp}></ImportExport></div>
{muteAudio
? <div className="tool-btn" onClick={audioOn}><RecordVoiceOverIcon/></div>
: <div onClick={audioOff} className="tool-btn"><VoiceOverOffIcon/></div>
}
{currentTool == TOOL_TYPE.WHITEBOARD
? <div className="tool-btn" onClick={changeTool}><ImportContacts/></div>
: <div onClick={changeTool} className="tool-btn"><Category/></div>
}
<div className="tool-btn" onClick={(evt: any) => {
props.onClick("setting");
}}><SettingsApplicationsIcon/></div>
<div className="tool-btn" onClick={(evt: any) => {
props.onClick("exit");
}}><SettingsPowerIcon/></div>
{/*<div className="tool-btn"><ImportExport onClick={randomStageUp}></ImportExport></div>*/}
</div> </div>
</> </>
) )
......
...@@ -18,7 +18,30 @@ ...@@ -18,7 +18,30 @@
z-index: 9; z-index: 9;
} }
} }
.menu-close {
cursor: pointer;
width: 18px;
top: 15px;
right: 15px;
position: absolute;
background-size: 18px;
height: 18px;
border-radius: 8px;
&:hover {
background: rgba(0, 0, 0, 0.07);
}
&::after {
border-radius: 8px;
display: block;
width: 18px;
height: 18px;
content: ' ';
background-position: center;
background-repeat: no-repeat;
background-size: 18px;
background-image: url('../assets/icon-resource-menu-close.png');
}
}
.video-profile { .video-profile {
z-index: 3; z-index: 3;
width: 100%; width: 100%;
......
...@@ -4,6 +4,21 @@ import './video-player.scss'; ...@@ -4,6 +4,21 @@ import './video-player.scss';
import { AgoraElectronStream, StreamType, nativeRTCClient as nativeClient } from '../utils/agora-electron-client'; import { AgoraElectronStream, StreamType, nativeRTCClient as nativeClient } from '../utils/agora-electron-client';
import { useRoomState } from '../containers/root-container'; import { useRoomState } from '../containers/root-container';
import { platform } from '../utils/platform'; import { platform } from '../utils/platform';
import ArrowDownwardIcon from '@material-ui/icons/ArrowDownward';
import {makeStyles} from '@material-ui/core/styles';
const useStyles = makeStyles({
stageDown : {
display: 'flex',
width: 18,
height: 24,
color: '#fff',
lineHeight: 24,
opacity: .8,
cursor:'pointer'
}
});
const contentMode = 0; const contentMode = 0;
...@@ -41,6 +56,7 @@ const VideoPlayer: React.FC<VideoPlayerProps> = ({ ...@@ -41,6 +56,7 @@ const VideoPlayer: React.FC<VideoPlayerProps> = ({
handleClose, handleClose,
close close
}) => { }) => {
const style = useStyles();
const loadVideo = useRef<boolean>(false); const loadVideo = useRef<boolean>(false);
const loadAudio = useRef<boolean>(false); const loadAudio = useRef<boolean>(false);
...@@ -219,6 +235,12 @@ const onAudioClick = (evt: any) => { ...@@ -219,6 +235,12 @@ const onAudioClick = (evt: any) => {
handleClick('audio', streamID, id); handleClick('audio', streamID, id);
} }
} }
const onStageDownClick = (evt: any) => {
if (handleClick && id) {
handleClick('stageDown', streamID, id);
}
}
const onVideoClick = (evt: any) => { const onVideoClick = (evt: any) => {
if (handleClick && id) { if (handleClick && id) {
...@@ -242,17 +264,30 @@ return ( ...@@ -242,17 +264,30 @@ return (
account ? account ?
<div className="video-profile"> <div className="video-profile">
<span className="account">{account}</span> <span className="account">{account}</span>
{me.uid === id || me.role === 'teacher' ? {streamID <= 0 ? null :
<span className="media-btn"> <div>
<Icon onClick={onAudioClick} className={audio ? "icon-speaker-on" : "icon-speaker-off"} data={"audio"} /> {
<Icon onClick={onVideoClick} className={video ? "icons-camera-unmute-s" : "icons-camera-mute-s"} data={"video"} /> me.uid === id || me.role === 'teacher'
</span> : ? <span className="media-btn">
<span className="media-btn"> {me.role === 'teacher' && me.uid !== id ?
<Icon className={audio ? "icon-speaker-on disabled" : "icon-speaker-off disabled"} data={"audio"} /> <ArrowDownwardIcon onClick={onStageDownClick} className={style.stageDown}></ArrowDownwardIcon>
<Icon className={video ? "icons-camera-unmute-s disabled" : "icons-camera-mute-s disabled"} data={"video"} /> : null}
</span> <Icon onClick={onAudioClick} className={audio ? "icon-speaker-on" : "icon-speaker-off"}
data={"audio"}/>
<Icon onClick={onVideoClick} className={video ? "icons-camera-unmute-s" : "icons-camera-mute-s"}
data={"video"}/>
</span>
: <span className="media-btn">
<Icon className={audio ? "icon-speaker-on disabled" : "icon-speaker-off disabled"} data={"audio"}/>
<Icon className={video ? "icons-camera-unmute-s disabled" : "icons-camera-mute-s disabled"}
data={"video"}/>
</span>
}</div>
} }
</div> </div>
: null : null
} }
......
...@@ -5,6 +5,7 @@ import { WhiteboardState, whiteboard } from '../stores/whiteboard'; ...@@ -5,6 +5,7 @@ import { WhiteboardState, whiteboard } from '../stores/whiteboard';
import { useHistory, useLocation } from 'react-router-dom'; import { useHistory, useLocation } from 'react-router-dom';
import { resolveMessage, resolvePeerMessage, resolveChannelAttrs, jsonParse } from '../utils/helper'; import { resolveMessage, resolvePeerMessage, resolveChannelAttrs, jsonParse } from '../utils/helper';
import GlobalStorage from '../utils/custom-storage'; import GlobalStorage from '../utils/custom-storage';
import {endPoint} from "../services/agora-end-points";
export type IRootProvider = { export type IRootProvider = {
globalState: GlobalState globalState: GlobalState
...@@ -105,9 +106,17 @@ export const RootProvider: React.FC<any> = ({children}) => { ...@@ -105,9 +106,17 @@ export const RootProvider: React.FC<any> = ({children}) => {
}).catch(console.warn); }).catch(console.warn);
}); });
rtmClient.on("AttributesUpdated", (attributes: object) => { rtmClient.on("AttributesUpdated", (attributes: object) => {
if (Object.keys(attributes).length == 0) {
globalStore.showToast({
type: 'rtmClient',
message: 'teacher close classroom'
});
history.push('/');
return;
}
const channelAttrs = resolveChannelAttrs(attributes); const channelAttrs = resolveChannelAttrs(attributes);
// console.log('[rtm-client] updated resolved attrs', channelAttrs); // console.log('[rtm-client] updated resolved attrs', channelAttrs);
// console.log('[rtm-client] updated origin attributes', attributes); console.log('[rtm-client] updated origin attributes', attributes);
roomStore.updateRoomAttrs(channelAttrs) roomStore.updateRoomAttrs(channelAttrs)
}); });
rtmClient.on("MemberJoined", (memberId: string) => { rtmClient.on("MemberJoined", (memberId: string) => {
...@@ -152,6 +161,8 @@ export const RootProvider: React.FC<any> = ({children}) => { ...@@ -152,6 +161,8 @@ export const RootProvider: React.FC<any> = ({children}) => {
me: room.me, me: room.me,
course: room.course, course: room.course,
mediaDevice: room.mediaDevice, mediaDevice: room.mediaDevice,
cwLink: endPoint.userToken,
studentsOrder: room.studentsOrder
}); });
// WARN: DEBUG ONLY MUST REMOVED IN PRODUCTION // WARN: DEBUG ONLY MUST REMOVED IN PRODUCTION
//@ts-ignore //@ts-ignore
......
...@@ -143,17 +143,67 @@ export default function useStream () { ...@@ -143,17 +143,67 @@ export default function useStream () {
console.log(100000, studentsOrder); console.log(100000, studentsOrder);
console.log(11111111, studentIds.toArray()); console.log(11111111, studentIds.toArray());
studentIds = studentIds.sort(function(a, b){ // studentIds = studentIds.sort(function(a, b){
if (studentsOrder.indexOf(+a) < 0) {return 0} // if (studentsOrder.indexOf(+a) < 0) {return 0}
if (studentsOrder.indexOf(+b) < 0) {return 0} // if (studentsOrder.indexOf(+b) < 0) {return 0}
return studentsOrder.indexOf(+a) - studentsOrder.indexOf(+b); // return studentsOrder.indexOf(+a) - studentsOrder.indexOf(+b);
}); // });
console.log(222222, studentIds.toArray()); const sids: any = [];
for (const ouid of studentsOrder) {
if (ouid == 0) {
sids.push(0)
} else {
// find in peer
const uid = studentIds.find((it: number) => `${ouid}` == `${it}`);
if (uid) {
sids.push(uid);
} else {
// find in channel
const usr = userAttrs.get(`${uid}`)
if (usr) {
sids.push(+usr.uid);
} else {
sids.push(-1);
}
}
}
}
console.log(222222, userAttrs.toArray());
console.log(333333, sids);
// capture all remote streams // capture all remote streams
for (let studentId of studentIds) { for (let studentId of /*studentIds*/sids) {
console.log('*****************', studentId)
if (studentId == undefined) {
continue
}
if (studentId == 0) {
const _tmpStream = {
account: '空闲',
streamID: studentId,
video: 0,
audio: 0,
local: false,
}
studentStreams.push(_tmpStream);
continue
}
if (studentId == -1) {
const _tmpStream = {
account: '等待中...',
streamID: studentId,
video: 0,
audio: 0,
local: false,
}
studentStreams.push(_tmpStream);
continue
}
if (me.role === 'student' && +me.uid == studentId) { if (me.role === 'student' && +me.uid == studentId) {
if (myAttr && roomState.rtc.localStream) { if (myAttr && roomState.rtc.localStream) {
console.log('use local stream') console.log('use local stream')
...@@ -168,6 +218,7 @@ export default function useStream () { ...@@ -168,6 +218,7 @@ export default function useStream () {
continue continue
} }
} }
const studentAttr = userAttrs.get(''+studentId); const studentAttr = userAttrs.get(''+studentId);
const stream = roomState.rtc.remoteStreams.get(+studentId); const stream = roomState.rtc.remoteStreams.get(+studentId);
if (studentAttr) { if (studentAttr) {
...@@ -190,7 +241,7 @@ export default function useStream () { ...@@ -190,7 +241,7 @@ export default function useStream () {
} }
} }
userAttrs.forEach((v, k) => { userAttrs.forEach((v, k) => {
if (!studentIds.includes(+v.uid)) { if (!sids.includes(+v.uid)) {
if (`${v.uid}` != `${teacherUid}`) { if (`${v.uid}` != `${teacherUid}`) {
const s: any = { const s: any = {
streamID: +v.uid, streamID: +v.uid,
...@@ -210,7 +261,7 @@ export default function useStream () { ...@@ -210,7 +261,7 @@ export default function useStream () {
}, [ }, [
course, course,
me.uid, me.uid,
roomStore.state.studentsOrder, // roomStore.state.studentsOrder,
roomState.rtc.users, roomState.rtc.users,
roomState.rtc.remoteStreams, roomState.rtc.remoteStreams,
roomState.rtc.localStream roomState.rtc.localStream
......
...@@ -95,7 +95,7 @@ body { ...@@ -95,7 +95,7 @@ body {
background: #F5F7F8; background: #F5F7F8;
border-radius:8px 0px 0px 8px; border-radius:8px 0px 0px 8px;
position: relative; position: relative;
.cover-placeholder { .cover-placeholder {
display: block; display: block;
background-repeat: no-repeat; background-repeat: no-repeat;
...@@ -288,13 +288,13 @@ body { ...@@ -288,13 +288,13 @@ body {
@media screen and (max-width: 780px) { @media screen and (max-width: 780px) {
.home-cover-web { .home-cover-web {
min-width: 780px; //min-width: 780px;
} }
} }
@media screen and (max-height: 768px) { @media screen and (max-height: 768px) {
.home-cover-web { .home-cover-web {
min-height: 768px; //min-height: 768px;
} }
} }
...@@ -322,4 +322,4 @@ body { ...@@ -322,4 +322,4 @@ body {
} }
} }
} }
} }
\ No newline at end of file
...@@ -213,7 +213,7 @@ export function RoomPage({ children }: any) { ...@@ -213,7 +213,7 @@ export function RoomPage({ children }: any) {
]); ]);
useEffect(() => { useEffect(() => {
debugger // debugger
if (!roomState.me.uid || !roomState.course.rid) return; if (!roomState.me.uid || !roomState.course.rid) return;
if (classroom) { if (classroom) {
if (platform === 'web') { if (platform === 'web') {
...@@ -301,7 +301,7 @@ export function RoomPage({ children }: any) { ...@@ -301,7 +301,7 @@ export function RoomPage({ children }: any) {
}) })
*/ */
rtc.current = true; rtc.current = true;
debugger // debugger
// WARN: IF YOU ENABLED APP CERTIFICATE, PLEASE SIGN YOUR TOKEN IN YOUR SERVER SIDE AND OBTAIN IT FROM YOUR OWN TRUSTED SERVER API // WARN: IF YOU ENABLED APP CERTIFICATE, PLEASE SIGN YOUR TOKEN IN YOUR SERVER SIDE AND OBTAIN IT FROM YOUR OWN TRUSTED SERVER API
console.info(1.1, 'rtc join') console.info(1.1, 'rtc join')
// if (roomState.me.role == 'teacher') { // if (roomState.me.role == 'teacher') {
...@@ -311,7 +311,7 @@ export function RoomPage({ children }: any) { ...@@ -311,7 +311,7 @@ export function RoomPage({ children }: any) {
uid: +roomState.me.uid, uid: +roomState.me.uid,
channel: roomState.course.rid, channel: roomState.course.rid,
token: '', token: '',
dual: isSmallClass dual: true
}).then(() => { }).then(() => {
console.info(2, 'rtc join ok') console.info(2, 'rtc join ok')
roomStore.publishMeStream(); roomStore.publishMeStream();
...@@ -452,10 +452,11 @@ export function RoomPage({ children }: any) { ...@@ -452,10 +452,11 @@ export function RoomPage({ children }: any) {
console.log(1.15,'stagedown?', 222222 ); console.log(1.15,'stagedown?', 222222 );
roomStore.unPublishMeStream(); roomStore.unPublishMeStream();
} }
console.log(1.2 ,studentsOrder, 'studentsOrder changed publish stream');
} }
console.log(1.2 ,studentsOrder, 'studentsOrder changed publish stream');
}, [studentsOrder]); }, [studentsOrder]);
......
import React, {useEffect, useLayoutEffect, useMemo, useRef, useState} from 'react'; import React, {useEffect, useLayoutEffect, useMemo, useRef, useState} from 'react';
// import VideoMarquee from '../../components/video-marquee'; // import VideoMarquee from '../../components/video-marquee';
import MediaBoard from '../../components/mediaboard'; import MediaBoard from '../../components/mediaboard';
import Roomboard from '../../components/roomboard'; // import Roomboard from '../../components/roomboard';
import './small-class.scss'; import './small-class.scss';
import CourseWareFrame from "../../components/courseware-frame"; import CourseWareFrame from "../../components/courseware-frame";
import VideoShowList from "../../components/video-stage-list"; 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 {roomStore} from "../../stores/room";
import {TOOL_TYPE} from "../../utils/types"; import {TOOL_TYPE} from "../../utils/types";
import {platform} from "../../utils/platform"; // import {platform} from "../../utils/platform";
import AgoraWebClient from "../../utils/agora-rtc-client"; // import AgoraWebClient from "../../utils/agora-rtc-client";
import {AgoraElectronClient} from "../../utils/agora-electron-client"; // import {AgoraElectronClient} from "../../utils/agora-electron-client";
import {useRoomState} from "../../containers/root-container"; import {useRoomState} from "../../containers/root-container";
import RoomToolsBar from "../../components/room-tools-bar"; // import RoomToolsBar from "../../components/room-tools-bar";
export default function SmallClass() { export default function SmallClass() {
const [tool, setTool] = useState(true); const [tool, setTool] = useState(true);
...@@ -39,15 +39,15 @@ export default function SmallClass() { ...@@ -39,15 +39,15 @@ export default function SmallClass() {
{/*<VideoMarquee />*/} {/*<VideoMarquee />*/}
<VideoShowList/> <VideoShowList/>
<div className="container"> <div className="container">
{roomStore.state.me.role == 'teacher' ?<ToolsSwitcherController onClick={() => { {/*{roomStore.state.me.role == 'teacher' ?<ToolsSwitcherController onClick={() => {*/}
changeTool(); {/* changeTool();*/}
}}/> : null} {/*}}/> : null}*/}
{currentTool == TOOL_TYPE.WHITEBOARD {currentTool == TOOL_TYPE.WHITEBOARD
? <MediaBoard /> ? <MediaBoard />
: <CourseWareFrame></CourseWareFrame>} : <CourseWareFrame></CourseWareFrame>}
{ roomStore.state.me.role == 'teacher' ? <RoomToolsBar /> : null}
{/*{ roomStore.state.me.role == 'teacher' ? <Roomboard currentActive={'media'} /> : null}*/} {/*{ roomStore.state.me.role == 'teacher' ? <Roomboard currentActive={'media'} /> : null}*/}
</div> </div>
</div> </div>
......
...@@ -79,17 +79,70 @@ function HomePage() { ...@@ -79,17 +79,70 @@ function HomePage() {
setRequired({...required, yourPass: 'missing your password'}); setRequired({...required, yourPass: 'missing your password'});
return; return;
} }
///////////////////////////////
/*
session.roomName = "test_01__123";// userInfo["class_id"];
// session.yourName = userInfo["nick_name"];
session.role = `${session.yourName}`==="1"?"teacher":"student";
session.roomType = 1;
const path = roomTypes[session.roomType].path
const payload = {
uid: `${session.yourName}`, // genUid(),
rid: `${session.roomName}`, // `${session.roomType}${MD5(session.roomName)}`,
role: session.role,
roomName: session.roomName,
roomType: session.roomType,
video: 0,
audio: 0,
chat: 1,
account: session.yourName,
token: '',
boardId: '',
linkId: 0,
sharedId: 0,
lockBoard: 0,
}
ref.current = true;
globalStore.showLoading();
roomStore.loginAndJoin(payload).then(() => {
roomStore.updateSessionInfo(payload);
history.push(`/classroom/${path}`);
}).catch((err: any) => {
if (err.reason) {
globalStore.showToast({
type: 'rtmClient',
message: err.reason
})
} else {
globalStore.showToast({
type: 'rtmClient',
message: 'login failure, please checkout ur network'
})
}
console.warn(err);
})
.finally(() => {
ref.current = false;
globalStore.stopLoading();
})
*/
///////////////////////////////
endPoint.login({username: session.yourName, password: session.yourPass}).then((userInfo: any) => { endPoint.login({username: session.yourName, password: session.yourPass}).then((userInfo: any) => {
console.log(userInfo); console.log(userInfo);
session.roomName = userInfo["class_id"]; session.roomName = userInfo["class_id"];// userInfo["class_id"];
session.yourName = userInfo["nick_name"]; // session.yourName = userInfo["nick_name"];
session.role = userInfo["classRole"]==="tea"?"teacher":"student"; session.role = userInfo["classRole"]==="tea"?"teacher":"student";
session.roomType = 1; session.roomType = 1;
if (!roomTypes[session.roomType]) return; if (!roomTypes[session.roomType]) return;
const path = roomTypes[session.roomType].path const path = roomTypes[session.roomType].path
const payload = { const payload = {
uid: `${userInfo["id"]}`, // genUid(), uid: userInfo["classRole"]==="tea"?"100":`${session.yourName.substr(-2)}`, // `${userInfo["id"]}`, // genUid(),
rid: `${session.roomName}`, // `${session.roomType}${MD5(session.roomName)}`, rid: `${session.roomName}`, // `${session.roomType}${MD5(session.roomName)}`,
role: session.role, role: session.role,
roomName: session.roomName, roomName: session.roomName,
...@@ -133,6 +186,8 @@ function HomePage() { ...@@ -133,6 +186,8 @@ function HomePage() {
message: err message: err
}) })
}); });
} }
return ( return (
......
import { AgoraFetch } from "../utils/fetch"; import { AgoraFetch } from "../utils/fetch";
import jwt_decode from 'jwt-decode'; import jwt_decode from 'jwt-decode';
import {roomStore} from "../stores/room";
const ENDPOINT: string = process.env.REACT_APP_AGORA_ENDPOINT as string; const ENDPOINT: string = process.env.REACT_APP_AGORA_ENDPOINT as string;
...@@ -78,6 +79,10 @@ export class EndPoint { ...@@ -78,6 +79,10 @@ export class EndPoint {
} }
getCourseUrl(){ getCourseUrl(){
if (!this.userToken) {
this.userToken = roomStore.state.cwLink;
}
console.log('getCourseUrl', this.userToken)
return `${ENDPOINT}/airclass_ol?token=${this.userToken}`; return `${ENDPOINT}/airclass_ol?token=${this.userToken}`;
} }
......
This diff is collapsed.
...@@ -98,9 +98,12 @@ export default class AgoraRTMClient { ...@@ -98,9 +98,12 @@ export default class AgoraRTMClient {
this._logged = true; this._logged = true;
return return
} }
async clearChannelAttributesByKeys(uids: string[]) {
await this._client.deleteChannelAttributesByKeys(this._currentChannelName, uids, {enableNotificationToChannelMembers: true});
}
async clearChannelAttributes() { async clearChannelAttributes() {
await this._client.clearChannelAttributes(this._currentChannelName); await this._client.clearChannelAttributes(this._currentChannelName, {enableNotificationToChannelMembers: true});
} }
async logout () { async logout () {
...@@ -155,7 +158,11 @@ export default class AgoraRTMClient { ...@@ -155,7 +158,11 @@ export default class AgoraRTMClient {
this.destroyChannel(channel); this.destroyChannel(channel);
} }
} }
async leaveChannel() {
// await this._client.clearLocalUserAttributes();
await this.leave(this._currentChannelName);
await this.logout();
}
async exit() { async exit() {
await this.deleteChannelAttributesByKey(); await this.deleteChannelAttributesByKey();
await this.leave(this._currentChannelName); await this.leave(this._currentChannelName);
......
export const STAGE_NUM: number = 1; export const STAGE_NUM: number = 6;
...@@ -256,6 +256,7 @@ export function resolveChannelAttrs(json: object) { ...@@ -256,6 +256,7 @@ export function resolveChannelAttrs(json: object) {
let students: any[] = []; let students: any[] = [];
for (let key of Object.keys(json)) { for (let key of Object.keys(json)) {
if (key === 'teacher') continue; if (key === 'teacher') continue;
if (!/^[0-9]+$/.test(key)) continue;
const student = jsonParse(_.get(json, `${key}.value`)); const student = jsonParse(_.get(json, `${key}.value`));
if (student && Object.keys(student).length) { if (student && Object.keys(student).length) {
student.uid = key; student.uid = key;
......
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