Commit 8cb42e29 authored by liujiaxin's avatar liujiaxin

输入修改,老师全部静音的时候学生无权开启

parent 0c1868b2
......@@ -234,7 +234,7 @@ const MemberHolder: React.FC<MemberHolderProps> = ({
{/*me.uid === id ||*/}
{me.role === 'teacher' ?
<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}
{/*<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"} />*/}
......
......@@ -43,12 +43,12 @@ export default function RoomToolsBar (props: any) {
muteAudio: roomState.course.muteAudio
}
}, [roomState.course]);
const audioOn = async () => {
console.log('audioOn');
const allMuteOn = async () => {
console.log('allStudentMuteOn');
await roomStore.allStudentMuteOn()
}
const audioOff = async () => {
console.log('audioOff');
const allMuteOff = async () => {
console.log('allStudentMuteOff');
await roomStore.allStudentMuteOff()
}
const randomStageUp = async () => {
......@@ -61,9 +61,10 @@ export default function RoomToolsBar (props: any) {
{roomStore.state.me.role == 'teacher' ?
<>
{/*<div className="tool-btn" onClick={audioOn}><VoiceOverOffIcon/></div>*/}
{muteAudio
? <div className="tool-btn" onClick={audioOn}><VoiceOverOffIcon/></div>
: <div onClick={audioOff} className="tool-btn"><RecordVoiceOverIcon/></div>
? <div className="tool-btn" onClick={allMuteOff}><RecordVoiceOverIcon/></div>
: <div onClick={allMuteOn} className="tool-btn"><VoiceOverOffIcon/></div>
}
{currentTool == TOOL_TYPE.WHITEBOARD
? <div className="tool-btn" onClick={changeTool}><ImportContacts/></div>
......
......@@ -6,6 +6,7 @@ import { useRoomState } from '../containers/root-container';
import { platform } from '../utils/platform';
import ArrowDownwardIcon from '@material-ui/icons/ArrowDownward';
import {makeStyles} from '@material-ui/core/styles';
import {roomStore} from "../stores/room";
const useStyles = makeStyles({
stageDown : {
......@@ -40,6 +41,8 @@ interface VideoPlayerProps {
handleClose?: (uid: string, streamID: number) => void
}
let reloadStreamTimer: number | null = null;
const VideoPlayer: React.FC<VideoPlayerProps> = ({
preview,
role,
......@@ -60,6 +63,11 @@ const VideoPlayer: React.FC<VideoPlayerProps> = ({
const loadVideo = useRef<boolean>(false);
const loadAudio = useRef<boolean>(false);
const stateError = useRef<boolean>(false);
// const hasError = useMemo(() => {
// return stateError.current;
// }, [stateError]);
const lockPlay = useRef<boolean>(false);
const AgoraRtcEngine = useMemo(() => {
......@@ -130,15 +138,53 @@ useEffect(() => {
if (platform === 'web') {
if (!stream || !domId || lockPlay.current && stream.isPlaying()) return;
lockPlay.current = true;
/*const playFn = () => {
if (reloadStreamTimer) {
clearTimeout(reloadStreamTimer)
reloadStreamTimer = null;
}
reloadStreamTimer = window.setTimeout(() => {
stream.play(`${domId}`, { fit: 'cover' }, (err: any) => {
console.log('reloadStreamTimer reloadStreamTimer reloadStreamTimer')
lockPlay.current = false;
if (err && err.status !== 'aborted') {
// 播放失败,一般为浏览器策略阻止。引导用户用手势触发恢复播放。
console.warn('[video-player] ', err, id);
if (stream.isPlaying()) {
stream.stop();
}
playFn();
}
})
}, 1000)
}*/
stream.play(`${domId}`, { fit: 'cover' }, (err: any) => {
// console.log('reloadStreamTimer reloadStreamTimer reloadStreamTimer')
lockPlay.current = false;
if (err && err.status !== 'aborted') {
lockPlay.current = true;
// 播放失败,一般为浏览器策略阻止。引导用户用手势触发恢复播放。
console.warn('[video-player] ', err, id);
stateError.current = true;
// @ts-ignore
window.errorPlayer = stream;
}
})
return () => {
console.log(2343454567,local, streamID, me)
if (reloadStreamTimer) {
clearTimeout(reloadStreamTimer)
reloadStreamTimer = null;
}
if (stream.isPlaying()) {
// debugger
try{
stream.stop();
} catch (e) {
// console.log(e);
}
// stream.stop();
}
local && stream && stream.close();
}
......@@ -253,6 +299,10 @@ const onClose = (evt: any) => {
handleClose('close', streamID);
}
}
const resumeStream = (evt: any) => {
stateError.current = false;
stream.resume()
}
const me = useRoomState().me;
......@@ -264,18 +314,22 @@ return (
account ?
<div className="video-profile">
<span className="account">{account}</span>
{/*{stateError.current?<span onClick={resumeStream}>恢复</span>: null}*/}
{streamID <= 0 ? null :
<div>
{
me.uid === id || me.role === 'teacher'
/*me.uid === id ||*/ me.role === 'teacher'
? <span className="media-btn">
{me.role === 'teacher' && me.uid !== id ?
<ArrowDownwardIcon onClick={onStageDownClick} className={style.stageDown}></ArrowDownwardIcon>
: null}
<>
{
id != roomStore.state.course.teacherId ?<ArrowDownwardIcon onClick={onStageDownClick} className={style.stageDown}></ArrowDownwardIcon>
:null}
<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"}
< 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"}/>
......
......@@ -233,7 +233,7 @@
top: 10px;
pointer-events: none;
//
top: 110px;
top: 4px;
right: 10px;
.upload-btn {
user-select: none;
......
......@@ -135,7 +135,7 @@ export default function Control({
: null}
</div>
<div className="controls">
{/*!sharing && role === 'teacher' ?
{!sharing && role === 'teacher' ?
<>
<ControlItem name={`first_page`}
active={'first_page' === current}
......@@ -154,7 +154,7 @@ export default function Control({
onClick={onClick} />
<div className="menu-split" style={{ marginLeft: '7px', marginRight: '7px' }}></div>
</> : null
*/}
}
{role === 'teacher' ?
<>
{/*<ControlItem*/}
......
......@@ -99,6 +99,7 @@ export const RootProvider: React.FC<any> = ({children}) => {
}
});
rtmClient.on("MessageFromPeer", ({ message: { text }, peerId, props }: { message: { text: string }, peerId: string, props: any }) => {
console.log('MessageFromPeer', text);
const body = resolvePeerMessage(text);
resolveMessage(peerId, body);
roomStore.handlePeerMessage(body.cmd, peerId)
......@@ -114,14 +115,22 @@ export const RootProvider: React.FC<any> = ({children}) => {
history.push('/');
return;
}
console.log('[rtm-client] updated origin attributes', JSON.parse(JSON.stringify(attributes)));
const channelAttrs = resolveChannelAttrs(attributes);
// console.log('[rtm-client] updated resolved attrs', channelAttrs);
console.log('[rtm-client] updated origin attributes', attributes);
roomStore.updateRoomAttrs(channelAttrs)
});
rtmClient.on("MemberJoined", (memberId: string) => {
rtmClient.on("MemberJoined", async (memberId: string) => {
console.log(memberId, '[rtm] MemberJoined MemberJoined MemberJoined MemberJoined');
if (roomStore.state.me.role === 'teacher') {
await roomStore.rtmJoinUser(memberId)
}
});
rtmClient.on("MemberLeft", (memberId: string) => {
rtmClient.on("MemberLeft", async (memberId: string) => {
console.log(memberId, '[rtm] MemberLeft MemberLeft MemberLeft MemberLeft');
if (roomStore.state.me.role === 'teacher') {
await roomStore.rtmLeaveUser(memberId)
}
if (roomStore.state.applyUid === +memberId) {
roomStore.updateCourseLinkUid(0)
.then(() => {
......@@ -130,6 +139,7 @@ export const RootProvider: React.FC<any> = ({children}) => {
}
});
rtmClient.on("MemberCountUpdated", (count: number) => {
console.log(count, '[rtm] MemberCountUpdated MemberCountUpdated MemberCountUpdated');
!ref.current && roomStore.updateMemberCount(count);
});
rtmClient.on("ChannelMessage", ({ memberId, message }: { message: { text: string }, memberId: string }) => {
......@@ -151,8 +161,11 @@ export const RootProvider: React.FC<any> = ({children}) => {
const location = useLocation();
useEffect(() => {
if (location.pathname === '/') {
GlobalStorage.clear('agora_room');
return;
}
const room = value.roomState;
......@@ -171,6 +184,7 @@ export const RootProvider: React.FC<any> = ({children}) => {
//@ts-ignore
window.whiteboard = whiteboardState;
}, [value, location]);
return (
<RootContext.Provider value={value}>
{children}
......
......@@ -130,7 +130,7 @@ export default function useStream () {
if (!me.uid || userAttrs.count() === 0) return [];
const teacherUid = course.teacherId;
const peerUsers = roomState.rtc.users;
const studentsOrder = roomStore.state.studentsOrder || [];
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') {
......@@ -163,14 +163,23 @@ export default function useStream () {
const usr = userAttrs.get(`${ouid}`)
console.log('channel has ', ouid, usr)
if (usr) {
sids.push(-1/*+usr.uid*/);
sids.push(-usr.uid/*+usr.uid*/);
} else {
// sids.push(-1);
sids[orderIdx] = 0;
studentsOrder[orderIdx] = 0
studentsOrder[orderIdx] = 0;
/*
const _tmpStream = {
account: '空闲',
streamID: 0,
video: 0,
audio: 0,
local: false,
}
studentStreams.push(_tmpStream);
*/
}
}
}
orderIdx++
}
......@@ -197,7 +206,7 @@ export default function useStream () {
studentStreams.push(_tmpStream);
continue
}
if (studentId == -1) {
if (studentId < 0 ) {
const _tmpStream = {
account: '等待中...',
streamID: studentId,
......@@ -216,7 +225,7 @@ export default function useStream () {
...roomState.rtc.localStream,
account: myAttr.account,
video: myAttr.video,
audio: roomState.course.muteAudio ? 0 : myAttr.audio,
audio: myAttr.audio, // roomState.course.muteAudio ? 0 : myAttr.audio,
local: true,
}
studentStreams.push(_tmpStream);
......@@ -231,7 +240,7 @@ export default function useStream () {
streamID: studentId,
account: studentAttr.account,
video: studentAttr.video,
audio: roomState.course.muteAudio ? 0 : studentAttr.audio,
audio: studentAttr.audio, // roomState.course.muteAudio ? 0 : studentAttr.audio,
}
if (stream) {
_tmpStream = {
......@@ -239,10 +248,19 @@ export default function useStream () {
streamID: studentId,
account: studentAttr.account,
video: studentAttr.video,
audio: roomState.course.muteAudio ? 0 : studentAttr.audio,
audio: studentAttr.audio , // roomState.course.muteAudio ? 0 : studentAttr.audio,
}
}
studentStreams.push(_tmpStream);
} else {
const _tmpStream = {
account: '空闲',
streamID: 0,
video: 0,
audio: 0,
local: false,
}
studentStreams.push(_tmpStream);
}
}
userAttrs.forEach((v, k) => {
......@@ -252,7 +270,7 @@ export default function useStream () {
streamID: +v.uid,
account: v.account,
video: v.video,
audio: roomState.course.muteAudio ? 0 : v.audio,
audio: v.audio, // roomState.course.muteAudio ? 0 : v.audio,
}
if (`${me.uid}` == `${v.uid}`) {
s.local = true;
......@@ -264,9 +282,10 @@ export default function useStream () {
console.log('studentStreams', studentStreams);
return studentStreams;
}, [
course,
// course,
me.uid,
// roomStore.state.studentsOrder,
roomStore.state.studentsOrder,
roomState.users,
roomState.rtc.users,
roomState.rtc.remoteStreams,
roomState.rtc.localStream
......
......@@ -169,10 +169,12 @@ export function RoomPage({ children }: any) {
if (platform === 'web') {
// const webClient = roomStore.rtcClient as AgoraWebClient;
const uid = +roomStore.state.me.uid as number;
const video = roomStore.state.studentsOrder.includes(uid) ? 1 : roomStore.state.me.video;
const audio = roomStore.state.studentsOrder.includes(uid) ? 1 : roomStore.state.me.audio;
const streamSpec: AgoraStreamSpec = {
streamID: uid,
video: true,
audio: true,
video: !!video,
audio: !!audio,
mirror: false,
screen: false,
microphoneId: mediaDevice.microphoneId,
......@@ -331,31 +333,7 @@ export function RoomPage({ children }: any) {
return () => {
console.log('exit')
const events = [
'onTokenPrivilegeWillExpire',
'onTokenPrivilegeDidExpire',
'error',
'stream-published',
'stream-subscribed',
'stream-added',
'stream-removed',
'peer-online',
'peer-leave',
'stream-fallback'
]
for (let eventName of events) {
webClient.rtc.off(eventName, () => {});
}
console.log("[agora-web] rtmClient logout");
roomStore.rtmClient.logout();
console.log("[agora-web] remove event listener");
!rtc.current && webClient.exit().then(() => {
console.log("[agora-web] do remove event listener");
}).catch(console.warn)
.finally(() => {
rtc.current = true;
roomStore.removeLocalStream();
});
roomStore.removeRtcListener();
}
}
/*
......@@ -439,17 +417,17 @@ export function RoomPage({ children }: any) {
}, [roomState.me.uid, roomState.course.rid]);
useEffect(() => {
console.log('studentsOrder changed');
const webClient = roomStore.rtcClient as AgoraWebClient;
if (!webClient.joined) {
return;
}
if (me.role == 'student') {
if (studentsOrder.includes(+me.uid)) {
console.log(1.15,'stageup?', 1111111 );
console.log(1.15,'stageup?', me.uid, 1111111 );
roomStore.publishMeStream();
} else {
console.log(1.15,'stagedown?', 222222 );
console.log(1.15,'stagedown?', me.uid, 222222 );
roomStore.unPublishMeStream();
}
console.log(1.2 ,studentsOrder, 'studentsOrder changed publish stream');
......
......@@ -6,7 +6,7 @@ import {List, OrderedMap, OrderedSet} from 'immutable';
import AgoraRTMClient, {RoomMessage} from '../utils/agora-rtm-client';
import {globalStore} from './global';
import AgoraWebClient, {SHARE_ID} from '../utils/agora-rtc-client';
import {get} from 'lodash';
import {get, isEqual} from 'lodash';
import {isElectron} from '../utils/platform';
import GlobalStorage from '../utils/custom-storage';
import {STAGE_NUM} from "../utils/consts";
......@@ -62,6 +62,7 @@ export interface AgoraUser {
linkId: number // link_uid
lockBoard?: number // lock_board
grantBoard: number
lastStageTs: 0
}
export interface ClassState {
......@@ -131,10 +132,18 @@ export type AgoraMediaStream = {
streamID: number
stream?: any
}
interface userStatus extends AgoraUser{
onStage: boolean
}
const _studentsStatus: {[key: number]: userStatus } = {};
let _sOrderStatus: number[]= [];
export class RoomStore {
private subject: Subject<RoomState> | null;
public _state: RoomState;
private syncStudentsOrderTimer = null;
private _sOrderStatus = _sOrderStatus;
private _studentsStatus = _studentsStatus;
get state () {
return this._state;
......@@ -245,8 +254,8 @@ export class RoomStore {
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);
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);
});
......@@ -295,36 +304,57 @@ export class RoomStore {
// debugger
//把台上位置变零
let studentsOrder: any[] = [...this.state.studentsOrder];
console.log('下台', uid, studentsOrder)
const uidIndex = studentsOrder.indexOf(+uid)
if (uidIndex > -1) {
studentsOrder.splice(uidIndex, 1, 0);
console.log('下台后', uid, studentsOrder)
const data: any = {};
data['studentsOrder'] = studentsOrder;
const downUser: AgoraUser | undefined = this.state.users.get(`${uid}`);
if (downUser) {
downUser.audio = 0;
downUser.video = 0;
// @ts-ignore
downUser.last_stage_ts = 0;
data[uid] = downUser
}
this.state = {
...this.state,
studentsOrder
}
await this.commit(this.state);
await this.rtmClient.addOrUpdateChannelAttributes(data);
}
}
async stageUp(uid: string) {
let studentsOrder: any[] = [...this.state.studentsOrder];
if (studentsOrder.indexOf(+uid) > -1) {
return;
}
const data: any = {};
const emptyIndex = studentsOrder.indexOf(0);
if (emptyIndex > -1) {
if (emptyIndex > -1 && !studentsOrder.includes(uid)) {
studentsOrder[emptyIndex] = +uid;
const upUser: AgoraUser | undefined = this.state.users.get(`${uid}`);
if (upUser) {
upUser.video = 1;
upUser.audio = 1;
// @ts-ignore
upUser.last_stage_ts = Date.now();
data[upUser.uid] = upUser;
}
} else {
return
}
this.state = {
...this.state,
studentsOrder
}
await this.commit(this.state);
data['studentsOrder'] = studentsOrder;
await this.rtmClient.addOrUpdateChannelAttributes(data);
}
......@@ -451,8 +481,10 @@ export class RoomStore {
this.subject = null;
}
commit (state: RoomState) {
this.subject && this.subject.next(state);
async commit (state: RoomState) {
console.log('state changed', state);
return this.subject && this.subject.next(state);
}
updateState(rootState: RoomState) {
......@@ -479,7 +511,7 @@ export class RoomStore {
return false;
}
addLocalStream(stream: AgoraStream) {
async addLocalStream(stream: AgoraStream) {
this.state = {
...this.state,
rtc: {
......@@ -487,10 +519,10 @@ export class RoomStore {
localStream: stream
}
}
this.commit(this.state);
await this.commit(this.state);
}
removeLocalStream() {
async removeLocalStream() {
this.state = {
...this.state,
rtc: {
......@@ -499,10 +531,10 @@ export class RoomStore {
localSharedStream: null
}
}
this.commit(this.state);
await this.commit(this.state);
}
addLocalSharedStream(stream: any) {
async addLocalSharedStream(stream: any) {
this.state = {
...this.state,
rtc: {
......@@ -510,10 +542,10 @@ export class RoomStore {
localSharedStream: stream
}
}
this.commit(this.state);
await this.commit(this.state);
}
removeLocalSharedStream() {
async removeLocalSharedStream() {
this.state = {
...this.state,
rtc: {
......@@ -521,10 +553,13 @@ export class RoomStore {
localSharedStream: null
}
}
this.commit(this.state);
await this.commit(this.state);
}
addPeerUser(uid: number) {
async addPeerUser(uid: number) {
if (!uid) {
return;
}
this.state = {
...this.state,
rtc: {
......@@ -532,21 +567,45 @@ export class RoomStore {
users: this.state.rtc.users.add(uid),
}
}
this.commit(this.state);
await this.commit(this.state);
}
removePeerUser(uid: number) {
async removePeerUser(uid: number) {
// 如果一个流退了,检测是否是台上人员,移除掉,其实就是下台
// await this.stageDown(`${uid}`)
const orders = [...this.state.studentsOrder];
const checkIdx1 = orders.indexOf(+uid)
const checkIdx2 = orders.indexOf(-uid)
if (checkIdx1 > 0) {
orders.splice(checkIdx1, 1, 0)
}
if (checkIdx2 > 0) {
orders.splice(checkIdx2, 1, 0)
}
const remoteStream = this.state.rtc.remoteStreams.get(uid);
if (platform === 'web') {
if (remoteStream && remoteStream.stream && remoteStream.stream.isPlaying) {
remoteStream.stream.isPlaying() && remoteStream.stream.stop();
}
}
if (checkIdx1 > 0 || checkIdx2 > 0) {
await this.rtmClient.addOrUpdateChannelAttributes({studentsOrder: orders});
}
this.state = {
...this.state,
rtc: {
...this.state.rtc,
users: this.state.rtc.users.delete(uid),
},
studentsOrder: orders
}
}
this.commit(this.state);
await this.commit(this.state);
}
addRemoteStream(stream: AgoraStream) {
async addRemoteStream(stream: AgoraStream) {
console.log('remoteStreams added',5 , stream.streamID, this.state.users)
this.state = {
...this.state,
......@@ -555,16 +614,11 @@ export class RoomStore {
remoteStreams: this.state.rtc.remoteStreams.set(stream.streamID, stream)
}
}
this.commit(this.state);
await this.commit(this.state);
}
removeRemoteStream(uid: number) {
const remoteStream = this.state.rtc.remoteStreams.get(uid);
if (platform === 'web') {
if (remoteStream && remoteStream.stream && remoteStream.stream.isPlaying) {
remoteStream.stream.isPlaying() && remoteStream.stream.stop();
}
}
async removeRemoteStream(uid: number) {
this.state = {
......@@ -572,11 +626,14 @@ export class RoomStore {
rtc: {
...this.state.rtc,
remoteStreams: this.state.rtc.remoteStreams.delete(uid)
},
}
}
await this.commit(this.state);
}
updateMemberCount(count: number) {
async updateMemberCount(count: number) {
console.log('updateMemberCount1', this.state.studentsOrder);
this.state = {
...this.state,
rtm: {
......@@ -584,7 +641,8 @@ export class RoomStore {
memberCount: count,
}
}
this.commit(this.state);
// await this.commit(this.state);
console.log('updateMemberCount2', this.state.studentsOrder);
}
updateRtc(newState: any) {
......@@ -609,7 +667,7 @@ export class RoomStore {
async handlePeerMessage(cmd: RoomMessage, peerId: string) {
if (!peerId) return console.warn('state is not assigned');
const myUid = this.state.me.uid;
console.log("Teacher: ", this.isTeacher(myUid) , ", peerId: ", this.isStudent(peerId));
console.log("Teacher: ", this.isTeacher(myUid) , ", peerId: ", this.isStudent(peerId), cmd);
// student follow teacher peer message
if (!this.isTeacher(myUid) && this.isTeacher(peerId)) {
......@@ -676,6 +734,14 @@ export class RoomStore {
// when i m teacher & received student message
if (this.isTeacher(myUid) && this.isStudent(peerId)) {
switch(cmd) {
case RoomMessage.stageUp: {
this.stageUp(peerId)
return
}
case RoomMessage.stageDown: {
this.stageDown(peerId);
return
}
case RoomMessage.applyCoVideo: {
// WARN: LOCK
if (this.state.course.linkId) {
......@@ -758,6 +824,17 @@ export class RoomStore {
}
async unmute(uid: string, type: string) {
// 有一个unmute的时候,就把course里的muteAudio 变成0
if (this.state.me.role == 'teacher') {
this.state = {
...this.state,
course: {
...this.state.course,
muteAudio: 0
}
}
this.commit(this.state)
}
const me = this.state.me;
if (me.uid === `${uid}`) {
if (type === 'audio') {
......@@ -806,6 +883,7 @@ export class RoomStore {
const channelMemberCount = await this.rtmClient.getChannelMemberCount([rid]);
const channelCount = channelMemberCount[rid];
const channelMeta = await this.rtmClient.getChannelAttributeBy(rid);
console.log('channelMeta', channelMeta)
if (payload.role == 'student' && !channelMeta.teacher) {
throw {
type: 'not_permitted',
......@@ -837,8 +915,8 @@ export class RoomStore {
payload.audio = 0;
payload.video = 0;
if (role === 'teacher') {
payload.audio = 1;
payload.video = 1;
payload.audio = channelMeta['teacher'] ? channelMeta['teacher'].audio : 1;
payload.video = channelMeta['teacher'] ? channelMeta['teacher'].video : 1;
}
const argsJoin = {
......@@ -862,46 +940,16 @@ export class RoomStore {
}
} else {
//查看有无空闲
if (!studentsOrder.includes(+payload.uid)) {
/*if (!studentsOrder.includes(+payload.uid)) {
const emptyIndex = studentsOrder.indexOf(0);
if (emptyIndex > -1) {
studentsOrder.splice(emptyIndex, 1, +payload.uid);
}
}
/*
if (!studentsOrder.length) {
accounts.forEach(a => {
if (!studentsOrder.includes(+a.uid)) {
studentsOrder.push(+a.uid);
}
})
} else {
const accs = accounts.filter(a=> a.role != 'teacher');
const accIds = accs.map(a=> +a.uid);
// if (accIds.length >= studentsOrder.length) {
let a = new Set(accIds);
let b = new Set(studentsOrder);
let diff = new Set([...a].filter(x => !b.has(x)));
diff.forEach(d => {
if (!studentsOrder.includes(+d)) {
studentsOrder.push(+d);
}
})
// }
}
if (!studentsOrder.includes(+uid)) {
studentsOrder.push(+uid);
} else {
if (!pass) {
const i = studentsOrder.indexOf(+uid)
studentsOrder.splice(i,1)
studentsOrder.push(+uid)
}
}
*/
}
console.log('login accounts', accounts)
let onlineMe = accounts.find((it: any) => `${it.uid}` == `${payload.uid}`);
if (onlineMe) {
......@@ -913,7 +961,6 @@ export class RoomStore {
payload.audio = 1;
}
}
}
console.log('login payload', payload)
console.log('login studentsOrder', studentsOrder)
......@@ -926,7 +973,7 @@ export class RoomStore {
}
}
const grantBoard = role === 'teacher' ? 1 : 0;
console.log(">>>>>>>>>>#room: ", grantBoard);
console.log(">>>>>>>>>>#room: ", grantBoard,this.state);
await this.updateMe({...payload, grantBoard}, studentsOrder);
this.commit(this.state);
});
......@@ -950,7 +997,7 @@ export class RoomStore {
}
}
publishMeStream() {
console.log(3, 'set rtc join flag, should auto publish')
console.log(3, 'set rtc join flag, should auto publish', this.state.rtc.joined)
// return await (this.rtcClient as AgoraWebClient).publishStream()
// 通过index.tsx里的监听来触发发布
if (!this.state.rtc.joined) {
......@@ -959,7 +1006,7 @@ export class RoomStore {
}
unPublishMeStream() {
console.log(3, 'set rtc join flag, should auto publish')
console.log(3, 'set rtc join flag false, should unPublishMeStream')
// return await (this.rtcClient as AgoraWebClient).publishStream()
if (this.state.rtc.joined) {
this.setRTCJoined(false);
......@@ -967,6 +1014,7 @@ export class RoomStore {
}
setRTCJoined(joined: boolean) {
console.log('setRTCJoined', joined);
this.state = {
...this.state,
rtc: {
......@@ -976,6 +1024,20 @@ export class RoomStore {
}
this.commit(this.state);
}
async leaveStage(uid: number) {
const sOrders = [...this.state.studentsOrder];
const idx = sOrders.indexOf(+uid)
const newInfo: any = {};
if (idx > -1) {
sOrders.splice(idx, 1, 0);
this.state = {
...this.state,
studentsOrder: sOrders
}
newInfo['studentsOrder'] = sOrders;
await this.rtmClient.addOrUpdateChannelAttributes(newInfo);
}
}
async updateCourseLinkUid(linkId: number) {
const me = this.state.me;
......@@ -1024,6 +1086,7 @@ export class RoomStore {
audio: user.audio,
chat: user.chat,
grant_board: user.grantBoard,
last_stage_ts: user.lastStageTs
}
if (user.role === 'teacher') {
Object.assign(attrs, {
......@@ -1047,28 +1110,48 @@ export class RoomStore {
}
async allStudentMuteOn(){
const channelMeta = await this.rtmClient.getChannelAttributeBy(this.state.course.rid);
// let accounts = channelMeta.accounts;
let accounts = channelMeta.accounts;
const data: any = {};
// accounts.forEach((acc: any) => {
// acc.audio = 0;
// data[acc.uid] = acc;
// })
channelMeta.teacher.mute_audio = 0;
data['teacher'] = channelMeta.teacher;
accounts.forEach((acc: any) => {
acc.audio = 0;
data[acc.uid] = acc;
})
// channelMeta.teacher.mute_audio = 0;
// data['teacher'] = channelMeta.teacher;
this.state = {
...this.state,
course: {
...this.state.course,
muteAudio: 1
},
}
this.commit(this.state);
if (Object.keys(data).length) {
await this.rtmClient.addOrUpdateChannelAttributes(data);
}
}
async allStudentMuteOff(){
const channelMeta = await this.rtmClient.getChannelAttributeBy(this.state.course.rid);
// let accounts = channelMeta.accounts;
let accounts = channelMeta.accounts;
const data: any = {};
// accounts.forEach((acc: any) => {
// acc.audio = 1;
// data[acc.uid] = acc;
// })
channelMeta.teacher.mute_audio = 1;
data['teacher'] = channelMeta.teacher;
accounts.forEach((acc: any) => {
acc.audio = 1;
data[acc.uid] = acc;
})
// channelMeta.teacher.mute_audio = 1;
// data['teacher'] = channelMeta.teacher;
this.state = {
...this.state,
course: {
...this.state.course,
muteAudio: 0
},
}
this.commit(this.state);
if (Object.keys(data).length) {
await this.rtmClient.addOrUpdateChannelAttributes(data);
}
}
async updateMe(user: any, studentsOrder: number[] = []) {
const {role, uid, account, rid, video, audio, chat, boardId, linkId, sharedId, muteChat, muteAudio, grantBoard} = user;
......@@ -1091,6 +1174,7 @@ export class RoomStore {
link_uid: linkId,
shared_uid: sharedId,
grant_board: grantBoard,
last_stage_ts: Date.now()
});
console.log('users', user);
......@@ -1103,7 +1187,7 @@ export class RoomStore {
const class_state = get(user, 'courseState', this.state.course.courseState);
const whiteboard_uid = get(user, 'boardId', this.state.course.boardId);
const mute_chat = get(user, 'muteChat', this.state.course.muteChat);
const mute_audio = get(user, 'muteChat', this.state.course.muteAudio);
const mute_audio = get(user, 'muteAudio', this.state.course.muteAudio);
const shared_uid = get(user, 'sharedId', this.state.course.sharedId);
const link_uid = get(user, 'linkId', this.state.course.linkId);
const lock_board = get(user, 'lockBoard', this.state.course.lockBoard);
......@@ -1131,204 +1215,200 @@ export class RoomStore {
// let res = await this.rtmClient.updateChannelAttrsByKey(key, attrs);
// return res;
}
async syncStageStudent__(accounts: any[], studentsOrder: number[]) {
// debugger
let needUpdate =false;
const data: any = {};
const accData: any = {};
accounts.forEach(acc => {
if (acc.role == 'student') {
accData[acc.uid] = acc
}
})
const accIds: any[] = Object.keys(accData).map(uid => +uid);
if (!accIds.length) {
return
async rtmLeaveUser(memberId: string) {
console.log('学生退出', memberId, this.state.studentsOrder);
const studentsOrder = [...this.state.studentsOrder];
const userIndex = studentsOrder.indexOf(+memberId);
if (userIndex > -1) {
studentsOrder.splice(userIndex, 1, 0)
this.state = {
...this.state,
studentsOrder
}
// 学生在台上并且退出了
const exitUserIds = studentsOrder.filter( uid => {
return !accIds.includes(uid) && uid != 0;
});
if (exitUserIds.length) {
exitUserIds.forEach( uid => {
if (studentsOrder.includes(uid)) {
studentsOrder.splice(studentsOrder.indexOf(uid), 1)
needUpdate = true
await this.commit(this.state);
// const data: any = {};
// data['studentsOrder'] = studentsOrder;
// console.log('update me', data);
// await this.rtmClient.addOrUpdateChannelAttributes(data);
await this.rtmClient.clearChannelAttributesByKeys([`${memberId}`]);
}
})
}
async rtmJoinUser(memberId: string) {
console.log('新学生登录', memberId, this.state.studentsOrder);
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 lostIdx: number[] = [];
[...Array(studentsOrder.length - STAGE_NUM)].forEach( (_, i) => {
console.log(i)
const idx = studentsOrder.length - 1 - i
lostIdx.push(idx)
const len = STAGE_NUM - studentsOrder.length ? STAGE_NUM - studentsOrder.length : 0;
Array(len).forEach(_ =>{
studentsOrder.push(0)
})
lostIdx.forEach( uid => {
if (studentsOrder.includes(uid)) {
if ( accData[uid]) {
const u = accData[uid];
// if (u.video != 0 || u.audio != 0) {
u.video = 0;
u.audio = 0;
data[uid] = u;
// }
}
studentsOrder.splice(studentsOrder.indexOf(uid), 1)
needUpdate = true
}
})
studentsOrder.length = STAGE_NUM;
}
if (studentsOrder.length < STAGE_NUM) {
const newUid = accIds.find( uid => {
return !studentsOrder.includes(+uid) ;
});
const newStudents = accData[newUid];
if (newStudents) {
const uid = newStudents.uid;
// if (newStudents.video != 1 || newStudents.audio != 1) {
//上台的打开音视频
newStudents.video = 1;
newStudents.audio = 1;
data[uid] = newStudents;
studentsOrder.push(+uid)
if (studentsOrder.includes(newUid)) {
return;
} else {
// 台上有空闲
const emptyIndex = studentsOrder.indexOf(0);
if (emptyIndex > -1) {
//从台下找人
studentsOrder.splice(emptyIndex, 1, +newUid)
console.log('加入studentsOrder', newUid, studentsOrder);
needUpdate = true;
// }
}
}
}
for (const uid of Object.keys(accData)) {
if (!studentsOrder.includes(+uid)) {
const ud = {...accData[uid]};
ud.video = 0;
ud.audio = 0;
data[uid] = ud
}
}
if (needUpdate) {
data['studentsOrder'] = studentsOrder;
// await this.rtmClient.addOrUpdateChannelAttributes(data);
return data;
this.state = {
...this.state,
studentsOrder
}
// this.state.studentsOrder = studentsOrder;
await this.commit(this.state);
}
console.log('加入完登录学生后', this.state.studentsOrder);
}
async syncStageStudent(accounts: any[], studentsOrder: number[]) {
// debugger
let needUpdate =false;
const data: any = {};
async syncStageStudentByTeacherOrder(accounts: any[], channelStudentsOrder: number[]){
console.log('pass in channel studentsOrder', channelStudentsOrder);
console.log('teacher keep studentsOrder', this.state.studentsOrder);
const tSOrder = [...this.state.studentsOrder]
const accData: any = {};
const data: any = {};
accounts.forEach(acc => {
if (acc.role == 'student') {
console.log('account', acc.uid, acc)
accData[acc.uid] = acc
}
})
const accIds: any[] = Object.keys(accData).map(uid => +uid);
if (!accIds.length) {
return
}
// 学生在台上并且退出了
const exitUserIds = studentsOrder.filter( uid => {
return !accIds.includes(uid) && uid != 0;
});
if (exitUserIds.length) {
exitUserIds.forEach( uid => {
if (studentsOrder.includes(uid)) {
studentsOrder.splice(studentsOrder.indexOf(uid), 1, 0)
needUpdate = true
let shouldOut = channelStudentsOrder.filter(x => !tSOrder.includes(x) && x !== 0);
let shouldIn = tSOrder.filter(x => !channelStudentsOrder.includes(x) && x !== 0);
console.log('shouldOut', shouldOut);
shouldOut.forEach(o => {
const oi = tSOrder.indexOf(o);
if (oi > -1) {
tSOrder.splice(oi, 1, 0)
}
})
console.log('after shouldOut', tSOrder);
console.log('shouldIn', shouldIn);
shouldIn.forEach(o => {
const user = accData[o];
if (user) {
user.audio = 1;
user.video = 1;
data[o] = user;
}
if (studentsOrder.length != STAGE_NUM) {
if (studentsOrder.length > STAGE_NUM) {
//台上队列尾部挤下去的人音视频关闭
const lostIdx: number[] = [];
[...Array(studentsOrder.length - STAGE_NUM)].forEach( (_, i) => {
console.log(i)
const idx = studentsOrder.length - 1 - i
lostIdx.push(idx)
})
lostIdx.forEach( uid => {
if (studentsOrder.includes(uid)) {
if ( accData[uid]) {
const u = accData[uid];
// if (u.video != 0 || u.audio != 0) {
u.video = 0;
u.audio = 0;
data[uid] = u;
// }
if(!tSOrder.includes(o)) {
const ii = tSOrder.indexOf(0);
if (ii > -1) {
tSOrder.splice(ii, 1, o)
}
studentsOrder.splice(studentsOrder.indexOf(uid), 1)
needUpdate = true
}
})
studentsOrder.length = STAGE_NUM;
console.log('after shouldIn', tSOrder);
if (shouldIn.length || shouldOut.length) {
data['studentsOrder'] = [...tSOrder];
return data
}
if (studentsOrder.length < STAGE_NUM) {
const newUid = accIds.find( uid => {
return !studentsOrder.includes(+uid) ;
});
const newStudents = accData[newUid];
if (newStudents) {
const uid = newStudents.uid;
// if (newStudents.video != 1 || newStudents.audio != 1) {
//上台的打开音视频
newStudents.video = 1;
newStudents.audio = 1;
data[uid] = newStudents;
studentsOrder.push(+uid)
needUpdate = true;
// }
return
//不在直播间的学生过滤出来
const exitUsers = tSOrder.filter(uid => {
return !accData[uid];
})
let localSync = false;
console.log('不在直播间的学生',exitUsers, tSOrder);
exitUsers.forEach(uid => {
const idx1 = channelStudentsOrder.indexOf(+uid);
if (idx1 > -1){
channelStudentsOrder.splice(idx1, 1 ,0)
}
const idx2 = tSOrder.indexOf(+uid);
if (idx2 > -1){
localSync = true;
tSOrder.splice(idx2, 1 ,0)
}
} else {
// 台上有空闲
const emptyIndex = studentsOrder.indexOf(0);
if (emptyIndex > -1) {
//和小于台上人数补进去一样
const newUid = accIds.find( uid => {
return !studentsOrder.includes(+uid) ;
});
studentsOrder.splice(emptyIndex, 1, +newUid)
const newStudents = accData[newUid];
if (newStudents) {
const uid = newStudents.uid;
// if (newStudents.video != 1 || newStudents.audio != 1) {
//上台的打开音视频
newStudents.video = 1;
newStudents.audio = 1;
data[uid] = newStudents;
studentsOrder.push(+uid)
needUpdate = true;
// }
})
console.log('移除不在直播间的学生后', channelStudentsOrder, tSOrder);
if (tSOrder.length < STAGE_NUM) {
Array(STAGE_NUM - tSOrder.length).fill(0).forEach((zero) => {
tSOrder.push(zero)
})
}
let shouldDown = channelStudentsOrder.filter(x => !tSOrder.includes(x) && x !== 0);
let shouldUp = tSOrder.filter(x => !channelStudentsOrder.includes(x) && x !== 0);
console.log('shouldDown', shouldDown);
console.log('shouldUp', shouldUp);
shouldDown.forEach(d => {
const user = accData[d];
if (user) {
user.audio = 0;
user.video = 0;
data[d] = user;
}
})
shouldUp.forEach(u => {
const user = accData[u];
if (user) {
user.audio = 1;
user.video = 1;
data[u] = user;
}
for (const uid of Object.keys(accData)) {
if (!studentsOrder.includes(+uid)) {
const ud = {...accData[uid]};
ud.video = 0;
ud.audio = 1;
data[uid] = ud
})
// studentsOrder.forEach(uid => {
// if (uid != 0) {
// const user = accData[uid];
// if (!user.audio ) {
// this.rtmClient.sendPeerMessage(`${uid}`, {cmd: RoomMessage.unmuteAudio});
// }
// if (!user.video) {
// this.rtmClient.sendPeerMessage(`${uid}`, {cmd: RoomMessage.unmuteVideo});
// }
// }
// })
if (localSync){
console.log('同步教师sorders', tSOrder);
this.state = {
...this.state,
studentsOrder: tSOrder
}
await this.commit(this.state)
}
if (needUpdate) {
data['studentsOrder'] = studentsOrder;
// await this.rtmClient.addOrUpdateChannelAttributes(data);
return data;
if (Object.keys(data).length) {
data['studentsOrder'] = [...tSOrder];
return data
}
}
async updateRoomAttrs ({teacher, accounts, room, studentsOrder}: {teacher: any, accounts: any, room: any, studentsOrder: number[]}) {
console.log("[agora-board], room: ",teacher, accounts, room, studentsOrder);
const exitUserIds = [];
const users: OrderedMap<string, AgoraUser> = accounts.reduce((acc: OrderedMap<string, AgoraUser>, it: any) => {
return acc.set(it.uid, {
......@@ -1343,9 +1423,12 @@ export class RoomStore {
linkId: it.link_uid,
lockBoard: it.lock_board,
grantBoard: it.grant_board,
lastStageTs: it.last_stage_ts
});
}, OrderedMap<string, AgoraUser>());
if (this.state.studentsOrder.length == 0) {
this.state.studentsOrder = [0,0,0,0,0,0]
}
/*
let users = OrderedMap<string, AgoraUser>();
for (const it of accounts) {
......@@ -1365,13 +1448,7 @@ export class RoomStore {
}
*/
console.log('users ', users.toArray());
// remove exist user from studentsOrder
// for (const uid of [...studentsOrder]) {
// const has = users.get(`${uid}`)
// if (!has) {
// studentsOrder.splice(studentsOrder.indexOf(+uid), 1)
// }
// }
const me = this.state.me;
......@@ -1387,21 +1464,49 @@ export class RoomStore {
// this.meDown()
// }
// }
let newStudentsOrder = studentsOrder;
console.log('频道StudentsOrder', newStudentsOrder);
if (me.role === 'teacher') {
/*
// remove exist user from studentsOrder
for (const uid of [...studentsOrder]) {
if (uid <= 0) {
continue
}
const has = users.get(`${uid}`)
if (!has) {
studentsOrder.splice(studentsOrder.indexOf(+uid), 1)
}
}*/
newStudentsOrder = [...this.state.studentsOrder];//studentsOrder;
Object.assign(me, {
linkId: room.link_uid,
boardId: room.whiteboard_uid,
lockBoard: room.lock_board,
})
if (this.syncStudentsOrderTimer) {
// @ts-ignore
clearTimeout(this.syncStudentsOrderTimer);
this.syncStudentsOrderTimer = null;
}
//教师维护学生顺序,仅保留STAGE_NUM个,并更新到频道属性
/*const newInfo: any = await this.syncStageStudent(JSON.parse(JSON.stringify(accounts)), [...studentsOrder]);
const newInfo: any = await this.syncStageStudentByTeacherOrder(JSON.parse(JSON.stringify(accounts)), [...studentsOrder/*this.state.studentsOrder*/]);
console.log('newInfo', newInfo)
// debugger
if (newInfo) {
newStudentsOrder = newInfo['studentsOrder'];
await this.rtmClient.addOrUpdateChannelAttributes(newInfo);
}*/
// @ts-ignore
// this.syncStudentsOrderTimer = setTimeout(async () => {
// }, 1000)
} else {
// newStudentsOrder = [];
}
}
const newClassState: ClassState = {} as ClassState;
......@@ -1411,7 +1516,7 @@ export class RoomStore {
boardId: room.whiteboard_uid,
courseState: room.class_state,
muteChat: room.mute_chat,
muteAudio: room.mute_audio,
// muteAudio: room.mute_audio,
lockBoard: room.lock_board,
currentTool: room.current_tool
})
......@@ -1432,6 +1537,9 @@ export class RoomStore {
},
studentsOrder: newStudentsOrder
}
// if (newStudentsOrder.length) {
// this.state.studentsOrder = newStudentsOrder;
// }
this.commit(this.state);
}
......@@ -1459,18 +1567,17 @@ export class RoomStore {
}
this.commit(this.state);
}
async removeRtcListener() {
async exitAll() {
console.log('exitAll');
try {
if (this.state.me.role == 'teacher') {
await this.rtmClient.clearChannelAttributes()
} else {
await this.rtmClient.clearChannelAttributesByKeys([`${this.state.me.uid}`]);
const iframes = document.querySelectorAll("iframe");
if (iframes && iframes.length) {
iframes.forEach(ifm => {
// @ts-ignore
ifm.contentWindow.location.href='about:blank'
// @ts-ignore
ifm.contentWindow.document.write('')
})
}
await this.rtmClient.logout();
const webClient = roomStore.rtcClient as AgoraWebClient;
const events = [
'onTokenPrivilegeWillExpire',
'onTokenPrivilegeDidExpire',
......@@ -1483,6 +1590,7 @@ export class RoomStore {
'peer-leave',
'stream-fallback'
]
const webClient = roomStore.rtcClient as AgoraWebClient;
for (let eventName of events) {
webClient.rtc.off(eventName, () => {});
}
......@@ -1491,13 +1599,28 @@ export class RoomStore {
console.log("[agora-web] remove event listener");
webClient.exit().then(() => {
console.log("[agora-web] do remove event listener");
GlobalStorage.clear('agora_room');
}).catch(console.warn)
.finally(() => {
roomStore.removeLocalStream();
this.removeLocalStream();
});
// await this.rtcClient.exit();
}
async exitAll() {
console.log('exitAll');
try {
if (this.state.me.role == 'teacher') {
await this.rtmClient.clearChannelAttributes()
} else {
await this.rtmClient.clearChannelAttributesByKeys([`${this.state.me.uid}`]);
}
await this.rtmClient.logout();
const webClient = roomStore.rtcClient as AgoraWebClient;
GlobalStorage.clear('agora_room');
await this.removeRtcListener();
// await this.rtcClient.exit();
} catch(err) {
// debugger
console.warn('exitAll', err);
......
......@@ -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 = 7;
export const SHARE_ID = 999;
class AgoraRTCClient {
......@@ -60,7 +60,7 @@ class AgoraRTCClient {
public _localStream: any = null;
public _streamEvents: string[];
public _clientEvents: string[];
// public _enableBeauty = false;
constructor () {
this.streamID = null;
this._streamEvents = [];
......@@ -101,6 +101,7 @@ class AgoraRTCClient {
for (let evtName of clientEvents) {
this._clientEvents.push(evtName);
this._client.on(evtName, (args: any) => {
// console.log("[agora-web] " +evtName+ ": ", args);
if (evtName === "peer-leave") {
console.log("[agora-web] peer-leave: ", args);
}
......@@ -175,6 +176,12 @@ class AgoraRTCClient {
if (!this._published || !this._localStream) {
return resolve();
}
if (this._localStream ) {
if (this._localStream._enableBeauty) {
this._localStream.setBeautyEffectOptions(false);
this._localStream._enableBeauty = false
}
}
this._client.unpublish(this._localStream, (err: any) => {
reject(err);
})
......@@ -199,9 +206,22 @@ class AgoraRTCClient {
createLocalStream(data: AgoraStreamSpec): Promise<any> {
this._localStream = AgoraRTC.createStream({...data, mirror: false});
return new Promise((resolve, reject) => {
this._localStream.init(() => {
this._localStream.init(async () => {
this.streamID = data.streamID;
this.subscribeLocalStreamEvents();
// debugger
if (roomStore.state.me.role == 'teacher') {
const result = await this._localStream.setBeautyEffectOptions(true, {
lighteningContrastLevel: 2,
lighteningLevel: 0.9,
rednessLevel: 0.2,
smoothnessLevel: 0.9
})
this._localStream._enableBeauty = true;
// this._enableBeauty = true;
console.log('%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%', result)
}
if (data.audioOutput && data.audioOutput.deviceId) {
this.setAudioOutput(data.audioOutput.deviceId).then(() => {
resolve();
......@@ -234,10 +254,13 @@ class AgoraRTCClient {
})
}
async leave () { console.log(9999, 'rtc leave');
async leave () { console.log(9999, 'rtc leave', roomStore.state.me);
if (this._client) {
return new Promise((resolve, reject) => {
this._client.leave(resolve, reject);
this._client.leave(() => {
resolve()
}, reject);
})
}
}
......@@ -337,6 +360,7 @@ export default class AgoraWebClient {
await this.rtc.createClient(APP_ID, true);
await this.rtc.join(this.localUid, channel, token);
dual && await this.rtc.enableDualStream();
// console.log('555555555555555555555')
// 改成手动发布
// roomStore.setRTCJoined(true);
this.joined = true;
......
......@@ -19,7 +19,9 @@ export enum RoomMessage {
muteChat = 109,
unmuteChat = 110,
muteBoard = 200,
unmuteBoard = 201
unmuteBoard = 201,
stageUp = 301,
stageDown = 302,
}
export interface MessageBody {
......
......@@ -165,6 +165,12 @@ export function resolveMessage(peerId: string, { cmd, text }: { cmd: number, tex
case RoomMessage.unmuteVideo:
type = 'unmute video'
break;
case RoomMessage.stageDown:
type = 'stage down'
break;
case RoomMessage.stageUp:
type = 'stage up'
break;
default:
return console.warn(`[RoomMessage] unknown type, from peerId: ${peerId}`);
}
......@@ -334,6 +340,7 @@ export function resolveChannelAttrs(json: object) {
shared_uid: student.shared_uid,
whiteboard_uid: student.whiteboard_uid,
grant_board: +student.grant_board,
last_stage_ts: +student.last_stage_ts
});
}
// console.log('resolveChannelAttrs 3', accounts);
......
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