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()) {
stream.stop();
// 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}
<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"}/>
<>
{
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"}
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');
......
This diff is collapsed.
......@@ -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 {
......
......@@ -25,4 +25,4 @@ export class CustomStorage {
}
const GlobalStorage = new CustomStorage();
export default GlobalStorage;
\ No newline at end of file
export default GlobalStorage;
......@@ -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