Commit 3a2d2dba authored by liujiaxin's avatar liujiaxin

添加iframe和白板切换

parent 4e8f74c3
...@@ -25,7 +25,7 @@ const useStyles = makeStyles({ ...@@ -25,7 +25,7 @@ const useStyles = makeStyles({
flex: 1 flex: 1
}, },
style4: { style4: {
height: 30, height: 36,
width: 100, width: 100,
flex: 0 flex: 0
}, },
...@@ -39,7 +39,6 @@ const CourseWareFrame: React.FC = () => { ...@@ -39,7 +39,6 @@ const CourseWareFrame: React.FC = () => {
const ref = useRef<any>(''); const ref = useRef<any>('');
const [src, setSrc] = useState('') const [src, setSrc] = useState('')
const changSrc = (evt: any) => { const changSrc = (evt: any) => {
debugger
setSrc(ref.current.value); setSrc(ref.current.value);
} }
......
...@@ -23,6 +23,7 @@ import AgoraWebClient, { SHARE_ID } from '../utils/agora-rtc-client'; ...@@ -23,6 +23,7 @@ import AgoraWebClient, { SHARE_ID } from '../utils/agora-rtc-client';
import "white-web-sdk/style/index.css"; import "white-web-sdk/style/index.css";
import { ViewMode } from 'white-web-sdk'; import { ViewMode } from 'white-web-sdk';
const pathName = (path: string): string => { const pathName = (path: string): string => {
const reg = /\/([^/]*)\//g; const reg = /\/([^/]*)\//g;
reg.exec(path); reg.exec(path);
...@@ -46,13 +47,13 @@ const MediaBoard: React.FC<MediaBoardProps> = ({ ...@@ -46,13 +47,13 @@ const MediaBoard: React.FC<MediaBoardProps> = ({
const roomState = useRoomState(); const roomState = useRoomState();
const whiteboardState = useWhiteboardState(); const whiteboardState = useWhiteboardState();
const role = roomState.me.role; const role = roomState.me.role;
const room = whiteboardState.room; const room = whiteboardState.room;
const me = roomState.me; const me = roomState.me;
const course = roomState.course; const course = roomState.course;
const rtmState = roomState.rtm; const rtmState = roomState.rtm;
const ref = useRef<any>(false); const ref = useRef<any>(false);
const [pageTool, setPageTool] = useState<string>(''); const [pageTool, setPageTool] = useState<string>('');
...@@ -184,7 +185,7 @@ const MediaBoard: React.FC<MediaBoardProps> = ({ ...@@ -184,7 +185,7 @@ const MediaBoard: React.FC<MediaBoardProps> = ({
return +roomStore.state.me.uid === +roomStore.state.course.linkId; return +roomStore.state.me.uid === +roomStore.state.course.linkId;
}, [roomStore.state.me.uid, }, [roomStore.state.me.uid,
roomStore.state.course.linkId]); roomStore.state.course.linkId]);
const location = useLocation(); const location = useLocation();
const current = useMemo(() => { const current = useMemo(() => {
...@@ -309,7 +310,7 @@ const items = [ ...@@ -309,7 +310,7 @@ const items = [
}, [me.role, me.grantBoard, location]); }, [me.role, me.grantBoard, location]);
const [tool, setTool] = useState<string | any>(drawable === 'drawable' ? 'pencil' : ''); const [tool, setTool] = useState<string | any>(drawable === 'drawable' ? 'pencil' : '');
const [selector, updateSelector] = useState<string>(''); const [selector, updateSelector] = useState<string>('');
const handleToolClick = (evt: any, name: string) => { const handleToolClick = (evt: any, name: string) => {
...@@ -417,7 +418,7 @@ const items = [ ...@@ -417,7 +418,7 @@ const items = [
const UploadPanel = useCallback(() => { const UploadPanel = useCallback(() => {
if (tool !== 'upload' || !room) return null; if (tool !== 'upload' || !room) return null;
return (<UploadBtn return (<UploadBtn
room={room} room={room}
uuid={room.uuid} uuid={room.uuid}
roomToken={room.roomToken} roomToken={room.roomToken}
...@@ -505,7 +506,7 @@ const items = [ ...@@ -505,7 +506,7 @@ const items = [
return ( return (
<Progress title={"uploading..."} /> <Progress title={"uploading..."} />
) )
} else } else
if (convertPhase === 'converting') { if (convertPhase === 'converting') {
return ( return (
<Progress title={"converting..."} /> <Progress title={"converting..."} />
...@@ -524,10 +525,10 @@ const items = [ ...@@ -524,10 +525,10 @@ const items = [
b: color[2], b: color[2],
} }
} }
return ( return (
<div className={`media-board ${drawable}`}> <div className={`media-board ${drawable}`}>
{sharedStream ? {sharedStream ?
<VideoPlayer <VideoPlayer
id={`${sharedStream.streamID}`} id={`${sharedStream.streamID}`}
domId={`shared-${sharedStream.streamID}`} domId={`shared-${sharedStream.streamID}`}
...@@ -545,7 +546,7 @@ const items = [ ...@@ -545,7 +546,7 @@ const items = [
/> />
} }
<div className="layer"> <div className="layer">
{!sharedStream ? {!sharedStream ?
<> <>
<Tools <Tools
items={toolItems} items={toolItems}
...@@ -560,7 +561,7 @@ const items = [ ...@@ -560,7 +561,7 @@ const items = [
<UploadPanel /> <UploadPanel />
{children ? children : null} {children ? children : null}
</div> </div>
{me.role === 'teacher' && room ? {/*me.role === 'teacher' && room ?
<ScaleController <ScaleController
zoomScale={scale} zoomScale={scale}
onClick={() => { onClick={() => {
...@@ -577,8 +578,7 @@ const items = [ ...@@ -577,8 +578,7 @@ const items = [
}} }}
/> />
: :
null null*/}
}
{ showControl ? { showControl ?
<Control <Control
notice={globalState.notice} notice={globalState.notice}
...@@ -589,7 +589,7 @@ const items = [ ...@@ -589,7 +589,7 @@ const items = [
totalPage={totalPage} totalPage={totalPage}
isHost={isHost} isHost={isHost}
onClick={handlePageTool}/> : null } onClick={handlePageTool}/> : null }
{tool === 'folder' && whiteboardState.room ? {tool === 'folder' && whiteboardState.room ?
<ResourcesMenu <ResourcesMenu
active={whiteboardState.activeDir} active={whiteboardState.activeDir}
items={whiteboardState.dirs} items={whiteboardState.dirs}
...@@ -609,6 +609,6 @@ const items = [ ...@@ -609,6 +609,6 @@ const items = [
<UploadProgressView /> <UploadProgressView />
</div> </div>
) )
} }
export default React.memo(MediaBoard); export default React.memo(MediaBoard);
\ No newline at end of file
...@@ -234,7 +234,7 @@ const MemberHolder: React.FC<MemberHolderProps> = ({ ...@@ -234,7 +234,7 @@ const MemberHolder: React.FC<MemberHolderProps> = ({
{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>
<Link component="button" onClick={onStageUp}>上台</Link> {me.role === 'teacher' ? <Link component="button" onClick={onStageUp}>上台</Link> : null}
{/*<Icon onClick={onAudioClick} className={audio ? "icon-speaker-on" : "icon-speaker-off"} data={"audio"} />*/} {/*<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"} />*/} {/*<Icon onClick={onVideoClick} className={video ? "icons-camera-unmute-s" : "icons-camera-mute-s"} data={"video"} />*/}
</span> : null} </span> : null}
......
...@@ -9,7 +9,7 @@ export default function Roomboard (props: any) { ...@@ -9,7 +9,7 @@ export default function Roomboard (props: any) {
messages, sendMessage, handleChange messages, sendMessage, handleChange
} = useChatText(); } = useChatText();
const [active, setActive] = useState('chatroom'); const [active, setActive] = useState('studentList');
const [visible, setVisible] = useState(true); const [visible, setVisible] = useState(true);
const toggleCollapse = (evt: any) => { const toggleCollapse = (evt: any) => {
...@@ -19,10 +19,10 @@ export default function Roomboard (props: any) { ...@@ -19,10 +19,10 @@ export default function Roomboard (props: any) {
return ( return (
<> <>
<div className={`${visible ? "icon-collapse-off" : "icon-collapse-on" } fixed`} onClick={toggleCollapse}></div> <div className={`${visible ? "icon-collapse-off" : "icon-collapse-on" } fixed`} onClick={toggleCollapse}></div>
{visible ? {visible ?
<div className={`small-class chat-board`}> <div className={`small-class chat-board`}>
<div className="menu"> <div className="menu">
<div onClick={() => { setActive('chatroom') }} className={`item ${active === 'chatroom' ? 'active' : ''}`}>Chatroom</div> {/*<div onClick={() => { setActive('chatroom') }} className={`item ${active === 'chatroom' ? 'active' : ''}`}>Chatroom</div>*/}
<div onClick={() => { setActive('studentList') }} className={`item ${active === 'studentList' ? 'active' : ''}`}>Student List</div> <div onClick={() => { setActive('studentList') }} className={`item ${active === 'studentList' ? 'active' : ''}`}>Student List</div>
</div> </div>
{ {
...@@ -42,4 +42,4 @@ export default function Roomboard (props: any) { ...@@ -42,4 +42,4 @@ export default function Roomboard (props: any) {
: null} : null}
</> </>
) )
} }
\ No newline at end of file
...@@ -22,13 +22,14 @@ ...@@ -22,13 +22,14 @@
font-weight:400; font-weight:400;
color:rgba(3,3,3,1); color:rgba(3,3,3,1);
line-height:17px; line-height:17px;
max-width: 113px; //max-width: 113px;
min-width: 113px; //min-width: 113px;
flex: 1;
} }
.attrs-group { .attrs-group {
display: flex; display: flex;
min-width: 148px; //min-width: 148px;
max-width: 148px; //max-width: 148px;
justify-content: space-evenly; justify-content: space-evenly;
.items { .items {
margin: 4px; margin: 4px;
...@@ -43,4 +44,4 @@ ...@@ -43,4 +44,4 @@
} }
} }
} }
} }
\ No newline at end of file
...@@ -89,8 +89,8 @@ export default function StudentList ({ ...@@ -89,8 +89,8 @@ export default function StudentList ({
<div key={key} className="item"> <div key={key} className="item">
<div className="nickname">{item.account}</div> <div className="nickname">{item.account}</div>
<div className="attrs-group"> <div className="attrs-group">
<CustomIcon type="grantBoard" id={item.uid} value={Boolean(item.grantBoard)} icon="connect" onClick={handleClick} /> {/*<CustomIcon type="grantBoard" id={item.uid} value={Boolean(item.grantBoard)} icon="connect" onClick={handleClick} />*/}
<CustomIcon type="chat" id={item.uid} value={Boolean(item.chat)} icon="chat" onClick={handleClick} /> {/*<CustomIcon type="chat" id={item.uid} value={Boolean(item.chat)} icon="chat" onClick={handleClick} />*/}
<CustomIcon type="audio" id={item.uid} value={Boolean(item.audio)} icon="audio" onClick={handleClick} /> <CustomIcon type="audio" id={item.uid} value={Boolean(item.audio)} icon="audio" onClick={handleClick} />
<CustomIcon type="video" id={item.uid} value={Boolean(item.video)} icon="video" onClick={handleClick} /> <CustomIcon type="video" id={item.uid} value={Boolean(item.video)} icon="video" onClick={handleClick} />
</div> </div>
...@@ -98,4 +98,4 @@ export default function StudentList ({ ...@@ -98,4 +98,4 @@ export default function StudentList ({
))} ))}
</div> </div>
) )
} }
\ No newline at end of file
import React from 'react';
import BuildIcon from '@material-ui/icons/Build';
import {makeStyles} from "@material-ui/core/styles";
import {Link} from "react-router-dom";
export type ToolsSwitcherControllerProps = {
// zoomScale: number
// zoomChange: (scale: number) => void
onClick: () => void
// onClickBoardLock: () => void
};
const toolsStyle = makeStyles({
button: {
width: '42px!important',
lineHeight: 42,
cursor: 'pointer',
userSelect: 'none',
display: 'flex',
alignItems: 'center',
boxSizing: 'border-box',
position: 'absolute',
left: 10,
bottom: 10,
height: 42,
background: '#fff',
boxShadow: '0 2px 4px 0 rgba(0,0,0,.1)',
borderRadius: 6,
border: '1px solid #dbe2e5',
zIndex:9,
},
icon: {
margin: '0 auto'
}
});
export const ToolsSwitcherController: React.FC<ToolsSwitcherControllerProps> = ({onClick}) => {
const classes = toolsStyle();
return (
<div className={`tool-switcher-controls ${classes.button}`} onClick={() => onClick()}>
<BuildIcon className={classes.icon}></BuildIcon>
{/*<div className="zoom-icon" onClick={() => this.props.onClick()}>*/}
{/*</div>*/}
{/*<div className="zoom-hold"></div>*/}
{/*<div className="zoom-size">{Math.ceil(this.props.zoomScale * 100)} %</div>*/}
{/*<div className="zoom-items">*/}
{/* <div className="item zoom-in" onClick={() => this.moveRuleIndex(-1)}>-</div>*/}
{/* <div className="item zoom-out" onClick={() => this.moveRuleIndex(+1)}>+</div>*/}
{/*</div>*/}
{/*<div className="lock-board" onClick={() => this.props.onClickBoardLock() }></div>*/}
</div>
);
}
...@@ -11,8 +11,8 @@ import MemberHolder from "./member-holder"; ...@@ -11,8 +11,8 @@ import MemberHolder from "./member-holder";
function VideoShowList() { function VideoShowList() {
const {teacher, stageStudents, onPlayerClick} = useStream();
const {teacher, students, onPlayerClick} = useStream();
...@@ -65,7 +65,7 @@ function VideoShowList() { ...@@ -65,7 +65,7 @@ function VideoShowList() {
// return <div className="camera"> // return <div className="camera">
// <div key={`stage${i}`} className="agora-video-view camera-holder">{i}</div> // <div key={`stage${i}`} className="agora-video-view camera-holder">{i}</div>
// </div> ; // </div> ;
const student = stageStudents.stage && stageStudents.stage[i]; const student = students && students.slice(0,STAGE_NUM)[i];
return <div className="camera" key={`stage_video${i}`}> return <div className="camera" key={`stage_video${i}`}>
{student ? <VideoPlayer {student ? <VideoPlayer
...@@ -122,7 +122,7 @@ function VideoShowList() { ...@@ -122,7 +122,7 @@ function VideoShowList() {
)*/} )*/}
{ stageStudents.wait ? stageStudents.wait.map((student: AgoraMediaStream, key: number) => ( { students ? students.slice(STAGE_NUM).map((student: AgoraMediaStream, key: number) => (
// <VideoPlayer // <VideoPlayer
// role="student" // role="student"
// domId={`dom-${student.streamID}`} // domId={`dom-${student.streamID}`}
......
...@@ -76,13 +76,13 @@ export default function Control({ ...@@ -76,13 +76,13 @@ export default function Control({
handleRecording(evt, type) handleRecording(evt, type)
.then(() => {}).catch(console.warn); .then(() => {}).catch(console.warn);
} }
const handleRecording = async (evt: any, type: string) => { const handleRecording = async (evt: any, type: string) => {
try { try {
const roomState = roomStore.state; const roomState = roomStore.state;
const me = roomState.me; const me = roomState.me;
if (lock.current || !me.uid) return; if (lock.current || !me.uid) return;
if (whiteboard.state.recording) { if (whiteboard.state.recording) {
if (!canStop()) return; if (!canStop()) return;
let mediaUrl = await whiteboard.stopRecording(); let mediaUrl = await whiteboard.stopRecording();
...@@ -90,7 +90,7 @@ export default function Control({ ...@@ -90,7 +90,7 @@ export default function Control({
type: 'recording', type: 'recording',
message: 'stop recording success', message: 'stop recording success',
}); });
if (whiteboard.state.endTime if (whiteboard.state.endTime
&& whiteboard.state.startTime) { && whiteboard.state.startTime) {
const {endTime, startTime, roomUUID} = whiteboard.clearRecording(); const {endTime, startTime, roomUUID} = whiteboard.clearRecording();
await roomStore.rtmClient.sendChannelMessage(JSON.stringify({ await roomStore.rtmClient.sendChannelMessage(JSON.stringify({
...@@ -128,14 +128,14 @@ export default function Control({ ...@@ -128,14 +128,14 @@ export default function Control({
return ( return (
<div className="controls-container"> <div className="controls-container">
<div className="interactive"> <div className="interactive">
{notice ? {notice ?
<ControlItem name={notice.reason} <ControlItem name={notice.reason}
onClick={onClick} onClick={onClick}
active={notice.reason === current} /> active={notice.reason === current} />
: null} : null}
</div> </div>
<div className="controls"> <div className="controls">
{!sharing && role === 'teacher' ? {/*!sharing && role === 'teacher' ?
<> <>
<ControlItem name={`first_page`} <ControlItem name={`first_page`}
active={'first_page' === current} active={'first_page' === current}
...@@ -154,14 +154,14 @@ export default function Control({ ...@@ -154,14 +154,14 @@ export default function Control({
onClick={onClick} /> onClick={onClick} />
<div className="menu-split" style={{ marginLeft: '7px', marginRight: '7px' }}></div> <div className="menu-split" style={{ marginLeft: '7px', marginRight: '7px' }}></div>
</> : null </> : null
} */}
{role === 'teacher' ? {role === 'teacher' ?
<> <>
<ControlItem {/*<ControlItem*/}
name={whiteboard.state.recording ? 'stop_recording' : 'recording'} {/*name={whiteboard.state.recording ? 'stop_recording' : 'recording'}*/}
onClick={onRecordButtonClick} {/*onClick={onRecordButtonClick}*/}
active={false} {/*active={false}*/}
/> {/*/>*/}
<ControlItem <ControlItem
name={sharing ? 'quit_screen_sharing' : 'screen_sharing'} name={sharing ? 'quit_screen_sharing' : 'screen_sharing'}
onClick={onClick} onClick={onClick}
...@@ -183,4 +183,4 @@ export default function Control({ ...@@ -183,4 +183,4 @@ export default function Control({
</div> </div>
) )
} }
\ No newline at end of file
...@@ -7,8 +7,7 @@ import {STAGE_NUM} from "../utils/consts"; ...@@ -7,8 +7,7 @@ import {STAGE_NUM} from "../utils/consts";
type StreamValue ={ type StreamValue ={
teacher: any teacher: any
students?: any[] students: any[]
stageStudents: {stage:any[], wait:any[]}
sharedStream: any sharedStream: any
currentHost: any currentHost: any
onPlayerClick: (type: string, streamID: number, uid: string) => Promise<any> onPlayerClick: (type: string, streamID: number, uid: string) => Promise<any>
...@@ -61,7 +60,7 @@ export default function useStream () { ...@@ -61,7 +60,7 @@ export default function useStream () {
roomState.rtc.remoteStreams, roomState.rtc.remoteStreams,
roomState.rtc.localStream roomState.rtc.localStream
]); ]);
/*
const students__ = useMemo(() => { const students__ = useMemo(() => {
const userAttrs = roomStore.state.users; const userAttrs = roomStore.state.users;
if (!me.uid || userAttrs.count() === 0) return []; if (!me.uid || userAttrs.count() === 0) return [];
...@@ -125,33 +124,44 @@ export default function useStream () { ...@@ -125,33 +124,44 @@ export default function useStream () {
roomState.rtc.remoteStreams, roomState.rtc.remoteStreams,
roomState.rtc.localStream roomState.rtc.localStream
]); ]);
const students_old = useMemo(() => { */
const students = useMemo(() => {
const userAttrs = roomStore.state.users; const userAttrs = roomStore.state.users;
if (!me.uid || userAttrs.count() === 0) return []; if (!me.uid || userAttrs.count() === 0) return [];
const teacherUid = course.teacherId; const teacherUid = course.teacherId;
const peerUsers = roomState.rtc.users; const peerUsers = roomState.rtc.users;
// exclude teacher and me // exclude teacher and me
let studentIds = peerUsers.filter((it: number) => it !== +teacherUid && it !== +me.uid && it !== SHARE_ID); let studentIds = peerUsers.filter((it: number) => it !== +teacherUid && it !== +me.uid && it !== SHARE_ID);
studentIds = studentIds.add(+me.uid);
const studentStreams: any[] = []; const studentStreams: any[] = [];
const myAttr = userAttrs.get(me.uid); const myAttr = userAttrs.get(me.uid);
const studentsOrder = roomStore.state.studentsOrder || [];
console.log(100000, studentsOrder);
console.log(11111111, studentIds.toArray());
studentIds = studentIds.sort(function(a, b){
return studentsOrder.indexOf(+a) - studentsOrder.indexOf(+b);
});
console.log(222222, studentIds.toArray());
// when i m student // when i m student
if (me.role === 'student') {
if (myAttr && roomState.rtc.localStream) {
const _tmpStream = {
...roomState.rtc.localStream,
account: myAttr.account,
video: myAttr.video,
audio: myAttr.audio,
local: true,
}
studentStreams.push(_tmpStream);
}
}
// capture all remote streams // capture all remote streams
for (let studentId of studentIds) { for (let studentId of studentIds) {
if (me.role === 'student' && +me.uid == studentId) {
if (myAttr && roomState.rtc.localStream) {
const _tmpStream = {
...roomState.rtc.localStream,
account: myAttr.account,
video: myAttr.video,
audio: myAttr.audio,
local: true,
}
studentStreams.push(_tmpStream);
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) {
...@@ -173,6 +183,7 @@ export default function useStream () { ...@@ -173,6 +183,7 @@ export default function useStream () {
studentStreams.push(_tmpStream); studentStreams.push(_tmpStream);
} }
} }
console.log('studentStreams', studentStreams);
return studentStreams; return studentStreams;
}, [ }, [
course, course,
...@@ -182,6 +193,7 @@ export default function useStream () { ...@@ -182,6 +193,7 @@ export default function useStream () {
roomState.rtc.localStream roomState.rtc.localStream
]); ]);
/*
const stageStudents: { wait: any[]; stage: any[] } = useMemo(() => { const stageStudents: { wait: any[]; stage: any[] } = useMemo(() => {
const userAttrs = roomStore.state.users; const userAttrs = roomStore.state.users;
if (!me.uid || userAttrs.count() === 0) return { wait: [], stage:[] }; if (!me.uid || userAttrs.count() === 0) return { wait: [], stage:[] };
...@@ -191,7 +203,8 @@ export default function useStream () { ...@@ -191,7 +203,8 @@ export default function useStream () {
let studentIds = peerUsers.filter((it: number) => it !== +teacherUid && it !== +me.uid && it !== SHARE_ID); let studentIds = peerUsers.filter((it: number) => it !== +teacherUid && it !== +me.uid && it !== SHARE_ID);
const studentStreams: any[] = []; const studentStreams: any[] = [];
userAttrs.forEach(u => { userAttrs.forEach(u => {
if (me.role === 'student' && `${u.uid}` === `${me.uid}`) { const uid = u.uid;
if (me.role === 'student' && `${uid}` === `${me.uid}`) {
if (roomState.rtc.localStream) { if (roomState.rtc.localStream) {
const _tmpStream = { const _tmpStream = {
...roomState.rtc.localStream, ...roomState.rtc.localStream,
...@@ -203,11 +216,11 @@ export default function useStream () { ...@@ -203,11 +216,11 @@ export default function useStream () {
studentStreams.push(_tmpStream); studentStreams.push(_tmpStream);
} }
} else { } else {
const studentAttr = userAttrs.get(`${u.uid}`); const studentAttr = userAttrs.get(`${uid}`);
const stream = roomState.rtc.remoteStreams.get(+u.uid); const stream = roomState.rtc.remoteStreams.get(+uid);
if (studentAttr) { if (studentAttr) {
let _tmpStream = { let _tmpStream = {
streamID: u.uid, streamID: uid,
account: studentAttr.account, account: studentAttr.account,
video: studentAttr.video, video: studentAttr.video,
audio: studentAttr.audio, audio: studentAttr.audio,
...@@ -215,7 +228,7 @@ export default function useStream () { ...@@ -215,7 +228,7 @@ export default function useStream () {
if (stream) { if (stream) {
_tmpStream = { _tmpStream = {
...stream, ...stream,
streamID: u.uid, streamID: uid,
account: studentAttr.account, account: studentAttr.account,
video: studentAttr.video, video: studentAttr.video,
audio: studentAttr.audio, audio: studentAttr.audio,
...@@ -225,55 +238,6 @@ export default function useStream () { ...@@ -225,55 +238,6 @@ export default function useStream () {
} }
} }
}) })
/*
const myAttr = userAttrs.get(me.uid);
const ss = [];
// when i m student
if (me.role === 'student') {
if (myAttr && roomState.rtc.localStream) {
const _tmpStream = {
...roomState.rtc.localStream,
account: myAttr.account,
video: myAttr.video,
audio: myAttr.audio,
local: true,
}
studentStreams.push(_tmpStream);
ss.push(me.uid)
}
}
for (let studentId of studentIds) {
ss.push(studentId)
}
console.log('studentIds', ss.join(', '))
// capture all remote streams
for (let studentId of studentIds) {
const studentAttr = userAttrs.get(''+studentId);
const stream = roomState.rtc.remoteStreams.get(+studentId);
if (studentAttr) {
let _tmpStream = {
streamID: studentId,
account: studentAttr.account,
video: studentAttr.video,
audio: studentAttr.audio,
}
if (stream) {
_tmpStream = {
...stream,
streamID: studentId,
account: studentAttr.account,
video: studentAttr.video,
audio: studentAttr.audio,
}
}
studentStreams.push(_tmpStream);
}
}*/
console.log('studentStreams', studentStreams) console.log('studentStreams', studentStreams)
return { return {
stage: [...studentStreams.slice(0,STAGE_NUM)], stage: [...studentStreams.slice(0,STAGE_NUM)],
...@@ -286,6 +250,8 @@ export default function useStream () { ...@@ -286,6 +250,8 @@ export default function useStream () {
roomState.rtc.remoteStreams, roomState.rtc.remoteStreams,
roomState.rtc.localStream roomState.rtc.localStream
]); ]);
*/
const sharedStream = useMemo(() => { const sharedStream = useMemo(() => {
const sharedUid = SHARE_ID; const sharedUid = SHARE_ID;
...@@ -358,8 +324,8 @@ export default function useStream () { ...@@ -358,8 +324,8 @@ export default function useStream () {
const value: StreamValue = { const value: StreamValue = {
teacher: teacher, teacher: teacher,
// students: students, students: students,
stageStudents, // stageStudents,
sharedStream: sharedStream, sharedStream: sharedStream,
currentHost: currentHost, currentHost: currentHost,
onPlayerClick: async (type: string, streamID: number, uid: string) => { onPlayerClick: async (type: string, streamID: number, uid: string) => {
......
...@@ -93,7 +93,7 @@ export function RoomPage({ children }: any) { ...@@ -93,7 +93,7 @@ export function RoomPage({ children }: any) {
const classroom = Boolean(location.pathname.match(/classroom/)); const classroom = Boolean(location.pathname.match(/classroom/));
const isBigClass = Boolean(location.pathname.match(/big-class/)); 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); const prevRoute = useRef<string>(location.pathname);
useEffect(() => { useEffect(() => {
console.log("[route] prevRoute: ", prevRoute.current); console.log("[route] prevRoute: ", prevRoute.current);
...@@ -107,12 +107,12 @@ export function RoomPage({ children }: any) { ...@@ -107,12 +107,12 @@ export function RoomPage({ children }: any) {
}); });
} }
}, [location]); }, [location]);
const rtc = useRef<boolean>(false); const rtc = useRef<boolean>(false);
const canPublish = useMemo(() => { const canPublish = useMemo(() => {
return !isBigClass || return !isBigClass ||
(isBigClass && (isBigClass &&
(me.role === 'teacher' || (me.role === 'teacher' ||
+me.uid === +course.linkId)); +me.uid === +course.linkId));
}, [me.uid, course.linkId, me.role, isBigClass]); }, [me.uid, course.linkId, me.role, isBigClass]);
...@@ -141,6 +141,7 @@ export function RoomPage({ children }: any) { ...@@ -141,6 +141,7 @@ export function RoomPage({ children }: any) {
if (platform === 'web') { if (platform === 'web') {
const webClient = rtcClient as AgoraWebClient; const webClient = rtcClient as AgoraWebClient;
if (!webClient.published) return; if (!webClient.published) return;
console.log('unpublish' ,2);
webClient webClient
.unpublishLocalStream() .unpublishLocalStream()
.then(() => { .then(() => {
...@@ -181,7 +182,7 @@ export function RoomPage({ children }: any) { ...@@ -181,7 +182,7 @@ export function RoomPage({ children }: any) {
webClient webClient
.publishLocalStream(streamSpec) .publishLocalStream(streamSpec)
.then(() => { .then(() => {
console.log("[agora-web] publish local stream"); console.log("[agora-web] publish local stream", roomStore.state.me.uid);
}).catch(console.warn) }).catch(console.warn)
.finally(() => { .finally(() => {
publishLock.current = false; publishLock.current = false;
...@@ -215,13 +216,13 @@ export function RoomPage({ children }: any) { ...@@ -215,13 +216,13 @@ export function RoomPage({ children }: any) {
} }
console.log("[agora-rtc] add event listener"); console.log("[agora-rtc] add event listener");
webClient.rtc.on('onTokenPrivilegeWillExpire', (evt: any) => { webClient.rtc.on('onTokenPrivilegeWillExpire', (evt: any) => {
// you need obtain the `newToken` token from server side // you need obtain the `newToken` token from server side
const newToken = ''; const newToken = '';
webClient.rtc.renewToken(newToken); webClient.rtc.renewToken(newToken);
console.log('[agora-web] onTokenPrivilegeWillExpire', evt); console.log('[agora-web] onTokenPrivilegeWillExpire', evt);
}); });
webClient.rtc.on('onTokenPrivilegeDidExpire', (evt: any) => { webClient.rtc.on('onTokenPrivilegeDidExpire', (evt: any) => {
// you need obtain the `newToken` token from server side // you need obtain the `newToken` token from server side
const newToken = ''; const newToken = '';
webClient.rtc.renewToken(newToken); webClient.rtc.renewToken(newToken);
console.log('[agora-web] onTokenPrivilegeDidExpire', evt); console.log('[agora-web] onTokenPrivilegeDidExpire', evt);
...@@ -234,6 +235,7 @@ export function RoomPage({ children }: any) { ...@@ -234,6 +235,7 @@ export function RoomPage({ children }: any) {
roomStore.addLocalStream(_stream); roomStore.addLocalStream(_stream);
}); });
webClient.rtc.on('stream-subscribed', ({ stream }: any) => { webClient.rtc.on('stream-subscribed', ({ stream }: any) => {
console.log('stream', 2, 'stream-subscribed')
const streamID = stream.getId(); const streamID = stream.getId();
// when streamID is not share_id use switch high or low stream in dual stream mode // 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 (location.pathname.match(/small-class/) && streamID !== SHARE_ID) {
...@@ -247,11 +249,13 @@ export function RoomPage({ children }: any) { ...@@ -247,11 +249,13 @@ export function RoomPage({ children }: any) {
console.log("[agora-web] dual stream set low for student"); console.log("[agora-web] dual stream set low for student");
} }
} }
console.log('stream', 3, 'addRemoteStream to play')
const _stream = new AgoraStream(stream, stream.getId(), false); const _stream = new AgoraStream(stream, stream.getId(), false);
console.log("[agora-web] subscribe remote stream, id: ", stream.getId()); console.log("[agora-web] subscribe remote stream, id: ", stream.getId());
roomStore.addRemoteStream(_stream); roomStore.addRemoteStream(_stream);
}); });
webClient.rtc.on('stream-added', ({ stream }: any) => { webClient.rtc.on('stream-added', ({ stream }: any) => {
console.log('stream', 1, 'stream-added')
console.log("[agora-web] added remote stream, id: ", stream.getId()); console.log("[agora-web] added remote stream, id: ", stream.getId());
webClient.subscribe(stream); webClient.subscribe(stream);
}); });
...@@ -291,12 +295,12 @@ export function RoomPage({ children }: any) { ...@@ -291,12 +295,12 @@ export function RoomPage({ children }: any) {
// 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
webClient webClient
.joinChannel({ .joinChannel({
uid: +roomState.me.uid, uid: +roomState.me.uid,
channel: roomState.course.rid, channel: roomState.course.rid,
token: '', token: '',
dual: isSmallClass dual: isSmallClass
}).then(() => { }).then(() => {
}).catch(console.warn).finally(() => { }).catch(console.warn).finally(() => {
rtc.current = false; rtc.current = false;
}); });
...@@ -316,6 +320,8 @@ export function RoomPage({ children }: any) { ...@@ -316,6 +320,8 @@ export function RoomPage({ children }: any) {
for (let eventName of events) { for (let eventName of events) {
webClient.rtc.off(eventName, () => {}); webClient.rtc.off(eventName, () => {});
} }
console.log("[agora-web] rtmClient logout");
roomStore.rtmClient.logout();
console.log("[agora-web] remove event listener"); console.log("[agora-web] remove event listener");
!rtc.current && webClient.exit().then(() => { !rtc.current && webClient.exit().then(() => {
console.log("[agora-web] do remove event listener"); console.log("[agora-web] do remove event listener");
...@@ -379,7 +385,7 @@ export function RoomPage({ children }: any) { ...@@ -379,7 +385,7 @@ export function RoomPage({ children }: any) {
}); });
// 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
nativeClient.joinChannel({ nativeClient.joinChannel({
uid: +roomState.me.uid, uid: +roomState.me.uid,
channel: roomState.course.rid, channel: roomState.course.rid,
token: '', token: '',
dual: isSmallClass dual: isSmallClass
......
import React, {useLayoutEffect, useRef} from 'react'; import React, {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";
export default function SmallClass() { export default function SmallClass() {
// let search = window.location.search; const [tool, setTool] = useState(true);
// let params = new URLSearchParams(search);
// let src = params.get('src');
// console.log(9999, src)
// useLayoutEffect(() => {
// }, [src]);
return ( return (
<div className="room-container"> <div className="room-container">
{/*<VideoMarquee />*/} {/*<VideoMarquee />*/}
<VideoShowList/> <VideoShowList/>
<div className="container"> <div className="container">
{/*<MediaBoard />*/} <ToolsSwitcherController onClick={() => {
<CourseWareFrame></CourseWareFrame> setTool(!tool);
}}/>
{tool ? <MediaBoard /> : <CourseWareFrame></CourseWareFrame>}
<Roomboard currentActive={'media'} /> <Roomboard currentActive={'media'} />
</div> </div>
</div> </div>
......
This diff is collapsed.
...@@ -20,7 +20,7 @@ export interface AgoraStreamSpec { ...@@ -20,7 +20,7 @@ export interface AgoraStreamSpec {
} }
const streamEvents: string[] = [ const streamEvents: string[] = [
"accessAllowed", "accessAllowed",
"accessDenied", "accessDenied",
"stopScreenSharing", "stopScreenSharing",
"videoTrackEnded", "videoTrackEnded",
...@@ -104,7 +104,7 @@ class AgoraRTCClient { ...@@ -104,7 +104,7 @@ class AgoraRTCClient {
if (evtName === "peer-leave") { if (evtName === "peer-leave") {
console.log("[agora-web] peer-leave: ", args); console.log("[agora-web] peer-leave: ", args);
} }
this._bus.emit(evtName, args); this._bus.emit(evtName, args);
}); });
} }
...@@ -155,7 +155,7 @@ class AgoraRTCClient { ...@@ -155,7 +155,7 @@ class AgoraRTCClient {
this._bus.off(evtName, cb); this._bus.off(evtName, cb);
} }
async publish() { async publish() { console.log('rtc publish')
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
if (this._published) { if (this._published) {
return resolve(); return resolve();
...@@ -170,7 +170,7 @@ class AgoraRTCClient { ...@@ -170,7 +170,7 @@ class AgoraRTCClient {
}) })
} }
async unpublish() { async unpublish() {console.log('unpublish' , 1);
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
if (!this._published || !this._localStream) { if (!this._published || !this._localStream) {
return resolve(); return resolve();
...@@ -234,7 +234,7 @@ class AgoraRTCClient { ...@@ -234,7 +234,7 @@ class AgoraRTCClient {
}) })
} }
async leave () { async leave () { console.log(9999, 'rtc leave');
if (this._client) { if (this._client) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
this._client.leave(resolve, reject); this._client.leave(resolve, reject);
...@@ -341,7 +341,7 @@ export default class AgoraWebClient { ...@@ -341,7 +341,7 @@ export default class AgoraWebClient {
roomStore.setRTCJoined(true); roomStore.setRTCJoined(true);
} }
async leaveChannel() { async leaveChannel() { console.log('unpublish leaveChannel' , 3);
this.localUid = 0; this.localUid = 0;
this.channel = ''; this.channel = '';
await this.unpublishLocalStream(); await this.unpublishLocalStream();
...@@ -357,17 +357,17 @@ export default class AgoraWebClient { ...@@ -357,17 +357,17 @@ export default class AgoraWebClient {
} }
async publishLocalStream(data: AgoraStreamSpec) { async publishLocalStream(data: AgoraStreamSpec) {
console.log(" publish local stream ", this.published); console.log(" publish local stream ", roomStore.state.me.uid);
if (this.published) { if (this.published) {
await this.unpublishLocalStream(); await this.unpublishLocalStream();
console.log("[agora-web] unpublished", this.published); console.log("[agora-web] unpublished", roomStore.state.me.uid);
} }
await this.rtc.createLocalStream(data); await this.rtc.createLocalStream(data);
await this.rtc.publish(); await this.rtc.publish();
this.published = true; this.published = true;
} }
async unpublishLocalStream() { async unpublishLocalStream() { console.log('unpublish LocalStream' , 4);
console.log("[agora-web] invoke unpublishStream"); console.log("[agora-web] invoke unpublishStream");
await this.rtc.unpublish(); await this.rtc.unpublish();
this.published = false; this.published = false;
...@@ -443,4 +443,4 @@ export default class AgoraWebClient { ...@@ -443,4 +443,4 @@ export default class AgoraWebClient {
setRemoteVideoStreamType(stream: any, type: number) { setRemoteVideoStreamType(stream: any, type: number) {
this.rtc.setRemoteVideoStreamType(stream, type); this.rtc.setRemoteVideoStreamType(stream, type);
} }
} }
\ No newline at end of file
...@@ -54,8 +54,8 @@ export default class AgoraRTMClient { ...@@ -54,8 +54,8 @@ export default class AgoraRTMClient {
this._channelAttrsKey = null; this._channelAttrsKey = null;
this._client = AgoraRTM.createInstance(APP_ID, { enableLogUpload: false, logFilter }); this._client = AgoraRTM.createInstance(APP_ID, { enableLogUpload: false, logFilter });
} }
async addOrUpdateChannelAttributes(data: any): Promise<string> { async addOrUpdateChannelAttributes(data: any, enableNotificationToChannelMembers = true): Promise<string> {
return await this._client.addOrUpdateChannelAttributes(this._currentChannelName, data, {enableNotificationToChannelMembers: true}); return await this._client.addOrUpdateChannelAttributes(this._currentChannelName, data, {enableNotificationToChannelMembers});
} }
public removeAllListeners(): any { public removeAllListeners(): any {
...@@ -83,6 +83,7 @@ export default class AgoraRTMClient { ...@@ -83,6 +83,7 @@ export default class AgoraRTMClient {
} }
async login (uid: string, token?: string) { async login (uid: string, token?: string) {
this._channelAttrsKey = uid;
await this._client.login({uid, token}); await this._client.login({uid, token});
this._client.on("ConnectionStateChanged", (newState: string, reason: string) => { this._client.on("ConnectionStateChanged", (newState: string, reason: string) => {
this._bus.emit("ConnectionStateChanged", {newState, reason}); this._bus.emit("ConnectionStateChanged", {newState, reason});
...@@ -96,6 +97,7 @@ export default class AgoraRTMClient { ...@@ -96,6 +97,7 @@ export default class AgoraRTMClient {
async logout () { async logout () {
if (!this._logged) return; if (!this._logged) return;
await this.leave(this._currentChannelName);
await this._client.logout(); await this._client.logout();
this.destroy(); this.destroy();
this._logged = false; this._logged = false;
...@@ -155,6 +157,9 @@ export default class AgoraRTMClient { ...@@ -155,6 +157,9 @@ export default class AgoraRTMClient {
async sendChannelMessage(msg: string) { async sendChannelMessage(msg: string) {
return this._currentChannel.sendMessage({ text: msg }); return this._currentChannel.sendMessage({ text: msg });
} }
async setChannelAttrsKey(key: any) {
this._channelAttrsKey = `${key}`;
}
async updateChannelAttrsByKey (data: {[key: string]: string}/*key: string, attrs: any*/) { async updateChannelAttrsByKey (data: {[key: string]: string}/*key: string, attrs: any*/) {
// this._channelAttrsKey = key; // this._channelAttrsKey = key;
const channelAttributes: {[key: string]: string} = {}; const channelAttributes: {[key: string]: string} = {};
...@@ -217,6 +222,7 @@ export default class AgoraRTMClient { ...@@ -217,6 +222,7 @@ export default class AgoraRTMClient {
const teacher = accounts.find((it: any) => it.role === 'teacher'); const teacher = accounts.find((it: any) => it.role === 'teacher');
if (teacher && results[teacher.uid]) { if (teacher && results[teacher.uid]) {
results.teacher = results[teacher.uid]; results.teacher = results[teacher.uid];
results.teacherId = teacher.uid;
results.teacherCount = 1; results.teacherCount = 1;
} }
results.totalCount = accounts.filter((it: any) => results[it.uid]).length; results.totalCount = accounts.filter((it: any) => results[it.uid]).length;
...@@ -240,11 +246,16 @@ export default class AgoraRTMClient { ...@@ -240,11 +246,16 @@ export default class AgoraRTMClient {
} }
continue; continue;
} }
const student = jsonParse(_.get(json, `${key}.value`)); // if (key === 'studentsOrder') {
// when student is not empty object // continue
if (student && Object.keys(student).length) { // }
student.uid = key; if (/^[0-9]+$/.test(key)) {
accounts.push(student); const student = jsonParse(_.get(json, `${key}.value`));
// when student is not empty object
if (student && Object.keys(student).length) {
student.uid = key;
accounts.push(student);
}
} }
} }
return accounts; return accounts;
......
...@@ -226,6 +226,7 @@ export function resolveChannelAttrs(json: object) { ...@@ -226,6 +226,7 @@ export function resolveChannelAttrs(json: object) {
let studentsOrder: number[] = []; let studentsOrder: number[] = [];
if ((json as any).studentsOrder && (json as any).studentsOrder.value) { if ((json as any).studentsOrder && (json as any).studentsOrder.value) {
studentsOrder = JSON.parse((json as any).studentsOrder.value) || []; studentsOrder = JSON.parse((json as any).studentsOrder.value) || [];
studentsOrder = studentsOrder.map(id => +id)
} }
delete (json as any).studentsOrder; delete (json as any).studentsOrder;
...@@ -249,52 +250,32 @@ export function resolveChannelAttrs(json: object) { ...@@ -249,52 +250,32 @@ export function resolveChannelAttrs(json: object) {
} }
} }
} }
const students = []; 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;
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;
student.role = 'student';
students.push(student); students.push(student);
} }
} }
console.log('resolveChannelAttrs 1', students);
console.log('resolveChannelAttrs 2', studentsOrder); // const orderedStudents: any[] = [];
/* // students.sort(function(a, b){
const studentsMeta = []; // return studentsOrder.indexOf(+a.uid) - studentsOrder.indexOf(+b.uid);
for (let key of Object.keys(json)) { // });
if (key === 'teacher') continue;
// if (!/^[0-9]+$/.test(key)) continue;
// const student = jsonParse(_.get(json, `${key}.value`));
// @ts-ignore
const studentMeta = json[key];
studentMeta.key = key;
studentsMeta.push(studentMeta)
// if (student && Object.keys(student).length) {
// student.uid = key;
// students.push(student);
// }
}
studentsMeta.sort((a, b)=>{
return a.lastUpdateTs - b.lastUpdateTs
})
let i = 0;
for (const s of studentsMeta) {
// const studentMeta = jsonParse(s);
const student = jsonParse(_.get(json, `${s.key}.value`));
if (student && Object.keys(student).length) {
student.uid = s.key;
// student.posIdx = i;
students.push(student);
i++;
}
}*/
// console.log('resolveChannelAttrs', studentsMeta);
// console.log('resolveChannelAttrs 1', students);
// console.log('resolveChannelAttrs 2', studentsOrder);
const accounts = [];
const accounts:any[] = [];
if (teacherJson && Object.keys(teacherJson).length) { if (teacherJson && Object.keys(teacherJson).length) {
accounts.push({ accounts.push({
role: 'teacher', role: 'teacher',
...@@ -324,33 +305,15 @@ export function resolveChannelAttrs(json: object) { ...@@ -324,33 +305,15 @@ export function resolveChannelAttrs(json: object) {
grant_board: +student.grant_board, grant_board: +student.grant_board,
}); });
} }
// console.log('resolveChannelAttrs 3', accounts);
if (studentsOrder.length == 0) {
accounts.forEach(a => {
studentsOrder.push(+a.uid);
})
} else {
const notInOrder = [];
accounts.forEach(a => {
if (!studentsOrder.includes(+a.uid)) {
notInOrder.push(+a.uid)
}
})
const aUids = accounts.map(a => {
return +a.uid;
});
const a = new Set(studentsOrder);
const b = new Set(aUids);
}
return { return {
teacher: teacherJson, teacher: teacherJson,
students: students, students: students,
accounts, accounts,
room, room,
studentsOrder
}; };
} }
......
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