Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
live
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
liujiaxin
live
Commits
6236ec53
Commit
6236ec53
authored
Feb 15, 2020
by
liujiaxin
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
台上位置固定6人。下台为空闲状态
parent
da303d2d
Changes
20
Hide whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
617 additions
and
324 deletions
+617
-324
package.json
package.json
+1
-1
courseware-frame.tsx
src/components/courseware-frame.tsx
+2
-2
room.tsx
src/components/dialog/room.tsx
+12
-6
member-holder.tsx
src/components/member-holder.tsx
+2
-1
nav.tsx
src/components/nav.tsx
+13
-8
room-tools-bar.scss
src/components/room-tools-bar.scss
+12
-26
room-tools-bar.tsx
src/components/room-tools-bar.tsx
+47
-2
video-player.scss
src/components/video-player.scss
+24
-1
video-player.tsx
src/components/video-player.tsx
+44
-9
root-container.tsx
src/containers/root-container.tsx
+12
-1
use-streams.ts
src/hooks/use-streams.ts
+60
-9
index.scss
src/index.scss
+4
-4
index.tsx
src/pages/classroom/index.tsx
+5
-4
small-class.tsx
src/pages/classroom/small-class.tsx
+9
-9
home.tsx
src/pages/home.tsx
+58
-3
agora-end-points.ts
src/services/agora-end-points.ts
+5
-0
room.ts
src/stores/room.ts
+296
-235
agora-rtm-client.ts
src/utils/agora-rtm-client.ts
+9
-2
consts.ts
src/utils/consts.ts
+1
-1
helper.ts
src/utils/helper.ts
+1
-0
No files found.
package.json
View file @
6236ec53
...
@@ -109,7 +109,7 @@
...
@@ -109,7 +109,7 @@
"electron:copy:web"
:
"cross-env REACT_APP_RUNTIME_PLATFORM=electron react-app-rewired build"
,
"electron:copy:web"
:
"cross-env REACT_APP_RUNTIME_PLATFORM=electron react-app-rewired build"
,
"electron:copy:electron"
:
"cpx ./app/**/*.js ./build"
,
"electron:copy:electron"
:
"cpx ./app/**/*.js ./build"
,
"electron:build"
:
"npm run electron:copy:web && npm run electron:copy:electron"
,
"electron:build"
:
"npm run electron:copy:web && npm run electron:copy:electron"
,
"dev"
:
"cross-env REACT_APP_RUNTIME_PLATFORM=web react-app-rewired start"
,
"dev"
:
"cross-env REACT_APP_RUNTIME_PLATFORM=web react-app-rewired start
"
,
"build"
:
"cross-env REACT_APP_RUNTIME_PLATFORM=web react-app-rewired build"
,
"build"
:
"cross-env REACT_APP_RUNTIME_PLATFORM=web react-app-rewired build"
,
"test"
:
"react-app-rewired test --env=jsdom"
,
"test"
:
"react-app-rewired test --env=jsdom"
,
"analyze"
:
"source-map-explorer 'build/static/js/*.js'"
,
"analyze"
:
"source-map-explorer 'build/static/js/*.js'"
,
...
...
src/components/courseware-frame.tsx
View file @
6236ec53
...
@@ -36,8 +36,8 @@ const useStyles = makeStyles({
...
@@ -36,8 +36,8 @@ const useStyles = makeStyles({
}
}
});
});
const
CourseWareFrame
:
React
.
FC
=
()
=>
{
const
CourseWareFrame
:
React
.
FC
=
()
=>
{
const
classes
=
useStyles
();
const
classes
=
useStyles
();
// `${ENDPOINT}/airclass_ol?token=${this.userToken}`;
const
src
=
endPoint
.
getCourseUrl
();
const
src
=
endPoint
.
getCourseUrl
();
return
(
return
(
<
div
className=
{
classes
.
style1
}
>
<
div
className=
{
classes
.
style1
}
>
...
...
src/components/dialog/room.tsx
View file @
6236ec53
...
@@ -83,8 +83,14 @@ const DialogContainer = () => {
...
@@ -83,8 +83,14 @@ const DialogContainer = () => {
const
onConfirm
=
(
type
:
string
)
=>
{
const
onConfirm
=
(
type
:
string
)
=>
{
if
(
type
===
'
exitRoom
'
)
{
if
(
type
===
'
exitRoom
'
)
{
globalStore
.
removeDialog
();
// debugger
history
.
push
(
'
/
'
);
globalStore
.
showLoading
();
roomStore
.
exitAll
().
then
(()
=>
{
globalStore
.
stopLoading
();
globalStore
.
removeDialog
();
history
.
push
(
'
/
'
);
})
}
}
else
if
(
type
===
'
apply
'
)
{
else
if
(
type
===
'
apply
'
)
{
Promise
.
all
([
Promise
.
all
([
...
@@ -103,16 +109,16 @@ const DialogContainer = () => {
...
@@ -103,16 +109,16 @@ const DialogContainer = () => {
}
}
return
(
return
(
visible
?
visible
?
<
RoomDialog
<
RoomDialog
type=
{
dialog
.
type
}
type=
{
dialog
.
type
}
desc=
{
dialog
.
message
}
desc=
{
dialog
.
message
}
onClose=
{
onClose
}
onClose=
{
onClose
}
onConfirm=
{
onConfirm
}
onConfirm=
{
onConfirm
}
/>
:
/>
:
null
null
)
)
}
}
export
default
React
.
memo
(
DialogContainer
);
export
default
React
.
memo
(
DialogContainer
);
\ No newline at end of file
src/components/member-holder.tsx
View file @
6236ec53
...
@@ -231,7 +231,8 @@ const MemberHolder: React.FC<MemberHolderProps> = ({
...
@@ -231,7 +231,8 @@ const MemberHolder: React.FC<MemberHolderProps> = ({
{
account
?
{
account
?
<
div
className=
"user-profile"
>
<
div
className=
"user-profile"
>
<
span
className=
"account"
>
{
account
}
</
span
>
<
span
className=
"account"
>
{
account
}
</
span
>
{
me
.
uid
===
id
||
me
.
role
===
'
teacher
'
?
{
/*me.uid === id ||*/
}
{
me
.
role
===
'
teacher
'
?
<
span
className=
"media-btn"
>
<
span
className=
"media-btn"
>
<
Link
component=
"button"
onClick=
{
onAudioClick
}
>
{
audio
?
"
静音
"
:
"
开麦
"
}
</
Link
>
<
Link
component=
"button"
onClick=
{
onAudioClick
}
>
{
audio
?
"
静音
"
:
"
开麦
"
}
</
Link
>
{
me
.
role
===
'
teacher
'
?
<
Link
component=
"button"
onClick=
{
onStageUp
}
>
上台
</
Link
>
:
null
}
{
me
.
role
===
'
teacher
'
?
<
Link
component=
"button"
onClick=
{
onStageUp
}
>
上台
</
Link
>
:
null
}
...
...
src/components/nav.tsx
View file @
6236ec53
...
@@ -13,7 +13,9 @@ import { isElectron, platform } from '../utils/platform';
...
@@ -13,7 +13,9 @@ import { isElectron, platform } from '../utils/platform';
import
{
useRoomState
}
from
'
../containers/root-container
'
;
import
{
useRoomState
}
from
'
../containers/root-container
'
;
import
{
roomStore
}
from
'
../stores/room
'
;
import
{
roomStore
}
from
'
../stores/room
'
;
import
{
globalStore
}
from
'
../stores/global
'
;
import
{
globalStore
}
from
'
../stores/global
'
;
import
VoiceOverOffIcon
from
'
@material-ui/icons/VoiceOverOff
'
;
import
RecordVoiceOverIcon
from
'
@material-ui/icons/RecordVoiceOver
'
;
import
RoomToolsBar
from
"
./room-tools-bar
"
;
interface
NavProps
{
interface
NavProps
{
delay
:
string
delay
:
string
network
:
string
network
:
string
...
@@ -41,7 +43,7 @@ export function Nav ({
...
@@ -41,7 +43,7 @@ export function Nav ({
}:
NavProps
)
{
}:
NavProps
)
{
const
{
NavBtn
}
=
usePlatform
();
const
{
NavBtn
}
=
usePlatform
();
const
handleFinish
=
(
evt
:
any
)
=>
{
const
handleFinish
=
(
evt
:
any
)
=>
{
onCardConfirm
(
'
setting
'
);
onCardConfirm
(
'
setting
'
);
}
}
...
@@ -51,7 +53,7 @@ export function Nav ({
...
@@ -51,7 +53,7 @@ export function Nav ({
<
div
className=
{
`nav-container ${isElectron ? 'draggable' : ''}`
}
>
<
div
className=
{
`nav-container ${isElectron ? 'draggable' : ''}`
}
>
<
div
className=
"class-title"
>
<
div
className=
"class-title"
>
<
span
className=
"room-name"
>
{
roomName
}
</
span
>
<
span
className=
"room-name"
>
{
roomName
}
</
span
>
{
role
===
'
teacher
'
?
{
role
===
'
teacher
'
?
<
Button
className=
{
`nav-button ${classState ? "stop" : "start"}`
}
name=
{
classState
?
"
Class end
"
:
"
Class start
"
}
onClick=
{
(
evt
:
any
)
=>
{
<
Button
className=
{
`nav-button ${classState ? "stop" : "start"}`
}
name=
{
classState
?
"
Class end
"
:
"
Class start
"
}
onClick=
{
(
evt
:
any
)
=>
{
handleClick
(
"
classState
"
)
handleClick
(
"
classState
"
)
}
}
/>
:
null
}
}
}
/>
:
null
}
...
@@ -68,18 +70,21 @@ export function Nav ({
...
@@ -68,18 +70,21 @@ export function Nav ({
<
span
className=
"time"
>
{
moment
.
utc
(
time
).
format
(
'
HH:mm:ss
'
)
}
</
span
>
<
span
className=
"time"
>
{
moment
.
utc
(
time
).
format
(
'
HH:mm:ss
'
)
}
</
span
>
</
div
>
</
div
>
<
span
className=
"menu-split"
/>
<
span
className=
"menu-split"
/>
<
div
className=
{
platform
===
'
web
'
?
"
btn-group
"
:
'
electron-btn-group
'
}
>
{
roomStore
.
state
.
me
.
role
==
'
teacher
'
?
<
RoomToolsBar
onClick=
{
handleClick
}
/>
:
null
}
{
/*<div className={platform === 'web' ? "btn-group" : 'electron-btn-group' }>
{platform === 'web' ? <Icon className="icon-setting" onClick={(evt: any) => {
{platform === 'web' ? <Icon className="icon-setting" onClick={(evt: any) => {
handleClick("setting");
handleClick("setting");
}}/> : null}
}}/> : null}
<Icon className="icon-exit" onClick={(evt: any) => {
<Icon className="icon-exit" onClick={(evt: any) => {
handleClick("exit");
handleClick("exit");
}} />
}} />
</
div
>
</div>
*/
}
<
NavBtn
/>
<
NavBtn
/>
</
div
>
</
div
>
</
div
>
</
div
>
{
showSetting
?
{
showSetting
?
<
SettingCard
className=
"internal-card"
<
SettingCard
className=
"internal-card"
handleFinish=
{
handleFinish
}
/>
:
null
handleFinish=
{
handleFinish
}
/>
:
null
}
}
...
@@ -228,7 +233,7 @@ export default function NavContainer() {
...
@@ -228,7 +233,7 @@ export default function NavContainer() {
}
}
return
(
return
(
<
Nav
<
Nav
role=
{
me
.
role
}
role=
{
me
.
role
}
roomName=
{
course
.
roomName
}
roomName=
{
course
.
roomName
}
classState=
{
Boolean
(
course
.
courseState
)
}
classState=
{
Boolean
(
course
.
courseState
)
}
...
@@ -241,4 +246,4 @@ export default function NavContainer() {
...
@@ -241,4 +246,4 @@ export default function NavContainer() {
handleClick=
{
handleClick
}
handleClick=
{
handleClick
}
/>
/>
)
)
}
}
\ No newline at end of file
src/components/room-tools-bar.scss
View file @
6236ec53
.room-tool-box
{
.room-tool-box
{
right
:
10px
;
width
:
46px
;
border
:
1px
solid
#dbe2e5
;
bottom
:
10px
;
cursor
:
pointer
;
display
:
flex
;
display
:
flex
;
z-index
:
9
;
flex-direction
:
row
;
position
:
absolute
;
//background: #fff;
box-shadow
:
0
2px
4px
0
rgba
(
0
,
0
,
0
,.
1
);
box-sizing
:
border-box
;
align-items
:
center
;
line-height
:
42
;
user-select
:
none
;
border-radius
:
6px
;
top
:
10px
;
flex-direction
:
column
;
height
:
90px
;
padding
:
3px
;
background-color
:
rgba
(
51
,
51
,
51
,
0
.4
);
.tool-btn
{
.tool-btn
{
cursor
:
pointer
;
cursor
:
pointer
;
display
:
flex
;
display
:
flex
;
height
:
3
8
px
;
height
:
3
2
px
;
width
:
3
8
px
;
width
:
3
2
px
;
margin
:
2
px
;
margin
:
4
px
;
border-radius
:
4px
;
border-radius
:
4px
;
background
:
#565656
;
//
background: #565656;
box-sizing
:
border-box
;
box-sizing
:
border-box
;
color
:
#eee
;
//
color: #eee;
svg
{
svg
{
width
:
3
8
px
;
width
:
3
0
px
;
height
:
3
8
px
;
height
:
3
0
px
;
display
:
block
;
display
:
block
;
}
}
}
}
.tool-btn
:hover
{
background-color
:
rgba
(
0
,
0
,
0
,
0
.07
);
border-radius
:
4px
;
}
}
}
src/components/room-tools-bar.tsx
View file @
6236ec53
...
@@ -6,9 +6,38 @@ import { VolumeOff, VolumeUp, ImportExport } from '@material-ui/icons';
...
@@ -6,9 +6,38 @@ import { VolumeOff, VolumeUp, ImportExport } from '@material-ui/icons';
import
{
roomStore
}
from
"
../stores/room
"
;
import
{
roomStore
}
from
"
../stores/room
"
;
import
{
useRoomState
}
from
"
../containers/root-container
"
;
import
{
useRoomState
}
from
"
../containers/root-container
"
;
import
'
./room-tools-bar.scss
'
;
import
'
./room-tools-bar.scss
'
;
import
VoiceOverOffIcon
from
"
@material-ui/icons/VoiceOverOff
"
;
import
RecordVoiceOverIcon
from
"
@material-ui/icons/RecordVoiceOver
"
;
import
Category
from
"
@material-ui/icons/Category
"
;
import
ImportContacts
from
"
@material-ui/icons/ImportContacts
"
;
import
SettingsApplicationsIcon
from
'
@material-ui/icons/SettingsApplications
'
;
import
SettingsPowerIcon
from
'
@material-ui/icons/SettingsPower
'
;
import
{
TOOL_TYPE
}
from
"
../utils/types
"
;
type
Props
=
{
// zoomScale: number
// zoomChange: (scale: number) => void
onClick
:
(
type
:
string
)
=>
void
// onClickBoardLock: () => void
};
export
default
function
RoomToolsBar
(
props
:
any
)
{
export
default
function
RoomToolsBar
(
props
:
any
)
{
// export const RoomToolsBar: React.FC<Props> = ({onClick}) => {
const
roomState
=
useRoomState
();
const
roomState
=
useRoomState
();
const
changeTool
=
async
()
=>
{
console
.
log
(
roomStore
.
state
.
course
.
currentTool
);
if
(
roomStore
.
state
.
course
.
currentTool
==
TOOL_TYPE
.
WHITEBOARD
)
{
await
roomStore
.
setCurrentTool
(
TOOL_TYPE
.
COURSE_WARE
)
}
else
{
await
roomStore
.
setCurrentTool
(
TOOL_TYPE
.
WHITEBOARD
)
}
}
const
{
currentTool
}
=
useMemo
(()
=>
{
return
{
currentTool
:
roomStore
.
state
.
course
.
currentTool
}
},
[
roomState
]);
const
{
muteAudio
}
=
useMemo
(()
=>
{
const
{
muteAudio
}
=
useMemo
(()
=>
{
return
{
return
{
muteAudio
:
roomState
.
course
.
muteAudio
muteAudio
:
roomState
.
course
.
muteAudio
...
@@ -25,11 +54,27 @@ export default function RoomToolsBar (props: any) {
...
@@ -25,11 +54,27 @@ export default function RoomToolsBar (props: any) {
const
randomStageUp
=
async
()
=>
{
const
randomStageUp
=
async
()
=>
{
await
roomStore
.
randomStageUp
()
await
roomStore
.
randomStageUp
()
}
}
return
(
return
(
<>
<>
<
div
className=
{
'
room-tool-box
'
}
>
<
div
className=
{
'
room-tool-box
'
}
>
{
muteAudio
?
<
div
className=
"tool-btn"
onClick=
{
audioOn
}
><
VolumeUp
></
VolumeUp
></
div
>
:
<
div
onClick=
{
audioOff
}
className=
"tool-btn"
><
VolumeOff
></
VolumeOff
></
div
>
}
<
div
className=
"tool-btn"
><
ImportExport
onClick=
{
randomStageUp
}
></
ImportExport
></
div
>
{
muteAudio
?
<
div
className=
"tool-btn"
onClick=
{
audioOn
}
><
RecordVoiceOverIcon
/></
div
>
:
<
div
onClick=
{
audioOff
}
className=
"tool-btn"
><
VoiceOverOffIcon
/></
div
>
}
{
currentTool
==
TOOL_TYPE
.
WHITEBOARD
?
<
div
className=
"tool-btn"
onClick=
{
changeTool
}
><
ImportContacts
/></
div
>
:
<
div
onClick=
{
changeTool
}
className=
"tool-btn"
><
Category
/></
div
>
}
<
div
className=
"tool-btn"
onClick=
{
(
evt
:
any
)
=>
{
props
.
onClick
(
"
setting
"
);
}
}
><
SettingsApplicationsIcon
/></
div
>
<
div
className=
"tool-btn"
onClick=
{
(
evt
:
any
)
=>
{
props
.
onClick
(
"
exit
"
);
}
}
><
SettingsPowerIcon
/></
div
>
{
/*<div className="tool-btn"><ImportExport onClick={randomStageUp}></ImportExport></div>*/
}
</
div
>
</
div
>
</>
</>
)
)
...
...
src/components/video-player.scss
View file @
6236ec53
...
@@ -18,7 +18,30 @@
...
@@ -18,7 +18,30 @@
z-index
:
9
;
z-index
:
9
;
}
}
}
}
.menu-close
{
cursor
:
pointer
;
width
:
18px
;
top
:
15px
;
right
:
15px
;
position
:
absolute
;
background-size
:
18px
;
height
:
18px
;
border-radius
:
8px
;
&
:hover
{
background
:
rgba
(
0
,
0
,
0
,
0
.07
);
}
&
:
:
after
{
border-radius
:
8px
;
display
:
block
;
width
:
18px
;
height
:
18px
;
content
:
' '
;
background-position
:
center
;
background-repeat
:
no-repeat
;
background-size
:
18px
;
background-image
:
url('../assets/icon-resource-menu-close.png')
;
}
}
.video-profile
{
.video-profile
{
z-index
:
3
;
z-index
:
3
;
width
:
100%
;
width
:
100%
;
...
...
src/components/video-player.tsx
View file @
6236ec53
...
@@ -4,6 +4,21 @@ import './video-player.scss';
...
@@ -4,6 +4,21 @@ import './video-player.scss';
import
{
AgoraElectronStream
,
StreamType
,
nativeRTCClient
as
nativeClient
}
from
'
../utils/agora-electron-client
'
;
import
{
AgoraElectronStream
,
StreamType
,
nativeRTCClient
as
nativeClient
}
from
'
../utils/agora-electron-client
'
;
import
{
useRoomState
}
from
'
../containers/root-container
'
;
import
{
useRoomState
}
from
'
../containers/root-container
'
;
import
{
platform
}
from
'
../utils/platform
'
;
import
{
platform
}
from
'
../utils/platform
'
;
import
ArrowDownwardIcon
from
'
@material-ui/icons/ArrowDownward
'
;
import
{
makeStyles
}
from
'
@material-ui/core/styles
'
;
const
useStyles
=
makeStyles
({
stageDown
:
{
display
:
'
flex
'
,
width
:
18
,
height
:
24
,
color
:
'
#fff
'
,
lineHeight
:
24
,
opacity
:
.
8
,
cursor
:
'
pointer
'
}
});
const
contentMode
=
0
;
const
contentMode
=
0
;
...
@@ -41,6 +56,7 @@ const VideoPlayer: React.FC<VideoPlayerProps> = ({
...
@@ -41,6 +56,7 @@ const VideoPlayer: React.FC<VideoPlayerProps> = ({
handleClose
,
handleClose
,
close
close
})
=>
{
})
=>
{
const
style
=
useStyles
();
const
loadVideo
=
useRef
<
boolean
>
(
false
);
const
loadVideo
=
useRef
<
boolean
>
(
false
);
const
loadAudio
=
useRef
<
boolean
>
(
false
);
const
loadAudio
=
useRef
<
boolean
>
(
false
);
...
@@ -219,6 +235,12 @@ const onAudioClick = (evt: any) => {
...
@@ -219,6 +235,12 @@ const onAudioClick = (evt: any) => {
handleClick
(
'
audio
'
,
streamID
,
id
);
handleClick
(
'
audio
'
,
streamID
,
id
);
}
}
}
}
const
onStageDownClick
=
(
evt
:
any
)
=>
{
if
(
handleClick
&&
id
)
{
handleClick
(
'
stageDown
'
,
streamID
,
id
);
}
}
const
onVideoClick
=
(
evt
:
any
)
=>
{
const
onVideoClick
=
(
evt
:
any
)
=>
{
if
(
handleClick
&&
id
)
{
if
(
handleClick
&&
id
)
{
...
@@ -242,17 +264,30 @@ return (
...
@@ -242,17 +264,30 @@ return (
account
?
account
?
<
div
className=
"video-profile"
>
<
div
className=
"video-profile"
>
<
span
className=
"account"
>
{
account
}
</
span
>
<
span
className=
"account"
>
{
account
}
</
span
>
{
me
.
uid
===
id
||
me
.
role
===
'
teacher
'
?
{
streamID
<=
0
?
null
:
<
span
className=
"media-btn"
>
<
div
>
<
Icon
onClick=
{
onAudioClick
}
className=
{
audio
?
"
icon-speaker-on
"
:
"
icon-speaker-off
"
}
data=
{
"
audio
"
}
/>
{
<
Icon
onClick=
{
onVideoClick
}
className=
{
video
?
"
icons-camera-unmute-s
"
:
"
icons-camera-mute-s
"
}
data=
{
"
video
"
}
/>
me
.
uid
===
id
||
me
.
role
===
'
teacher
'
</
span
>
:
?
<
span
className=
"media-btn"
>
<
span
className=
"media-btn"
>
{
me
.
role
===
'
teacher
'
&&
me
.
uid
!==
id
?
<
Icon
className=
{
audio
?
"
icon-speaker-on disabled
"
:
"
icon-speaker-off disabled
"
}
data=
{
"
audio
"
}
/>
<
ArrowDownwardIcon
onClick=
{
onStageDownClick
}
className=
{
style
.
stageDown
}
></
ArrowDownwardIcon
>
<
Icon
className=
{
video
?
"
icons-camera-unmute-s disabled
"
:
"
icons-camera-mute-s disabled
"
}
data=
{
"
video
"
}
/>
:
null
}
</
span
>
<
Icon
onClick=
{
onAudioClick
}
className=
{
audio
?
"
icon-speaker-on
"
:
"
icon-speaker-off
"
}
data=
{
"
audio
"
}
/>
<
Icon
onClick=
{
onVideoClick
}
className=
{
video
?
"
icons-camera-unmute-s
"
:
"
icons-camera-mute-s
"
}
data=
{
"
video
"
}
/>
</
span
>
:
<
span
className=
"media-btn"
>
<
Icon
className=
{
audio
?
"
icon-speaker-on disabled
"
:
"
icon-speaker-off disabled
"
}
data=
{
"
audio
"
}
/>
<
Icon
className=
{
video
?
"
icons-camera-unmute-s disabled
"
:
"
icons-camera-mute-s disabled
"
}
data=
{
"
video
"
}
/>
</
span
>
}
</
div
>
}
}
</
div
>
</
div
>
:
null
:
null
}
}
...
...
src/containers/root-container.tsx
View file @
6236ec53
...
@@ -5,6 +5,7 @@ import { WhiteboardState, whiteboard } from '../stores/whiteboard';
...
@@ -5,6 +5,7 @@ import { WhiteboardState, whiteboard } from '../stores/whiteboard';
import
{
useHistory
,
useLocation
}
from
'
react-router-dom
'
;
import
{
useHistory
,
useLocation
}
from
'
react-router-dom
'
;
import
{
resolveMessage
,
resolvePeerMessage
,
resolveChannelAttrs
,
jsonParse
}
from
'
../utils/helper
'
;
import
{
resolveMessage
,
resolvePeerMessage
,
resolveChannelAttrs
,
jsonParse
}
from
'
../utils/helper
'
;
import
GlobalStorage
from
'
../utils/custom-storage
'
;
import
GlobalStorage
from
'
../utils/custom-storage
'
;
import
{
endPoint
}
from
"
../services/agora-end-points
"
;
export
type
IRootProvider
=
{
export
type
IRootProvider
=
{
globalState
:
GlobalState
globalState
:
GlobalState
...
@@ -105,9 +106,17 @@ export const RootProvider: React.FC<any> = ({children}) => {
...
@@ -105,9 +106,17 @@ export const RootProvider: React.FC<any> = ({children}) => {
}).
catch
(
console
.
warn
);
}).
catch
(
console
.
warn
);
});
});
rtmClient
.
on
(
"
AttributesUpdated
"
,
(
attributes
:
object
)
=>
{
rtmClient
.
on
(
"
AttributesUpdated
"
,
(
attributes
:
object
)
=>
{
if
(
Object
.
keys
(
attributes
).
length
==
0
)
{
globalStore
.
showToast
({
type
:
'
rtmClient
'
,
message
:
'
teacher close classroom
'
});
history
.
push
(
'
/
'
);
return
;
}
const
channelAttrs
=
resolveChannelAttrs
(
attributes
);
const
channelAttrs
=
resolveChannelAttrs
(
attributes
);
// console.log('[rtm-client] updated resolved attrs', channelAttrs);
// console.log('[rtm-client] updated resolved attrs', channelAttrs);
//
console.log('[rtm-client] updated origin attributes', attributes);
console
.
log
(
'
[rtm-client] updated origin attributes
'
,
attributes
);
roomStore
.
updateRoomAttrs
(
channelAttrs
)
roomStore
.
updateRoomAttrs
(
channelAttrs
)
});
});
rtmClient
.
on
(
"
MemberJoined
"
,
(
memberId
:
string
)
=>
{
rtmClient
.
on
(
"
MemberJoined
"
,
(
memberId
:
string
)
=>
{
...
@@ -152,6 +161,8 @@ export const RootProvider: React.FC<any> = ({children}) => {
...
@@ -152,6 +161,8 @@ export const RootProvider: React.FC<any> = ({children}) => {
me
:
room
.
me
,
me
:
room
.
me
,
course
:
room
.
course
,
course
:
room
.
course
,
mediaDevice
:
room
.
mediaDevice
,
mediaDevice
:
room
.
mediaDevice
,
cwLink
:
endPoint
.
userToken
,
studentsOrder
:
room
.
studentsOrder
});
});
// WARN: DEBUG ONLY MUST REMOVED IN PRODUCTION
// WARN: DEBUG ONLY MUST REMOVED IN PRODUCTION
//@ts-ignore
//@ts-ignore
...
...
src/hooks/use-streams.ts
View file @
6236ec53
...
@@ -143,17 +143,67 @@ export default function useStream () {
...
@@ -143,17 +143,67 @@ export default function useStream () {
console
.
log
(
100000
,
studentsOrder
);
console
.
log
(
100000
,
studentsOrder
);
console
.
log
(
11111111
,
studentIds
.
toArray
());
console
.
log
(
11111111
,
studentIds
.
toArray
());
studentIds
=
studentIds
.
sort
(
function
(
a
,
b
){
// studentIds = studentIds.sort(function(a, b){
if
(
studentsOrder
.
indexOf
(
+
a
)
<
0
)
{
return
0
}
// if (studentsOrder.indexOf(+a) < 0) {return 0}
if
(
studentsOrder
.
indexOf
(
+
b
)
<
0
)
{
return
0
}
// if (studentsOrder.indexOf(+b) < 0) {return 0}
return
studentsOrder
.
indexOf
(
+
a
)
-
studentsOrder
.
indexOf
(
+
b
);
// return studentsOrder.indexOf(+a) - studentsOrder.indexOf(+b);
});
// });
console
.
log
(
222222
,
studentIds
.
toArray
());
const
sids
:
any
=
[];
for
(
const
ouid
of
studentsOrder
)
{
if
(
ouid
==
0
)
{
sids
.
push
(
0
)
}
else
{
// find in peer
const
uid
=
studentIds
.
find
((
it
:
number
)
=>
`
${
ouid
}
`
==
`
${
it
}
`
);
if
(
uid
)
{
sids
.
push
(
uid
);
}
else
{
// find in channel
const
usr
=
userAttrs
.
get
(
`
${
uid
}
`
)
if
(
usr
)
{
sids
.
push
(
+
usr
.
uid
);
}
else
{
sids
.
push
(
-
1
);
}
}
}
}
console
.
log
(
222222
,
userAttrs
.
toArray
());
console
.
log
(
333333
,
sids
);
// capture all remote streams
// capture all remote streams
for
(
let
studentId
of
studentIds
)
{
for
(
let
studentId
of
/*studentIds*/
sids
)
{
console
.
log
(
'
*****************
'
,
studentId
)
if
(
studentId
==
undefined
)
{
continue
}
if
(
studentId
==
0
)
{
const
_tmpStream
=
{
account
:
'
空闲
'
,
streamID
:
studentId
,
video
:
0
,
audio
:
0
,
local
:
false
,
}
studentStreams
.
push
(
_tmpStream
);
continue
}
if
(
studentId
==
-
1
)
{
const
_tmpStream
=
{
account
:
'
等待中...
'
,
streamID
:
studentId
,
video
:
0
,
audio
:
0
,
local
:
false
,
}
studentStreams
.
push
(
_tmpStream
);
continue
}
if
(
me
.
role
===
'
student
'
&&
+
me
.
uid
==
studentId
)
{
if
(
me
.
role
===
'
student
'
&&
+
me
.
uid
==
studentId
)
{
if
(
myAttr
&&
roomState
.
rtc
.
localStream
)
{
if
(
myAttr
&&
roomState
.
rtc
.
localStream
)
{
console
.
log
(
'
use local stream
'
)
console
.
log
(
'
use local stream
'
)
...
@@ -168,6 +218,7 @@ export default function useStream () {
...
@@ -168,6 +218,7 @@ export default function useStream () {
continue
continue
}
}
}
}
const
studentAttr
=
userAttrs
.
get
(
''
+
studentId
);
const
studentAttr
=
userAttrs
.
get
(
''
+
studentId
);
const
stream
=
roomState
.
rtc
.
remoteStreams
.
get
(
+
studentId
);
const
stream
=
roomState
.
rtc
.
remoteStreams
.
get
(
+
studentId
);
if
(
studentAttr
)
{
if
(
studentAttr
)
{
...
@@ -190,7 +241,7 @@ export default function useStream () {
...
@@ -190,7 +241,7 @@ export default function useStream () {
}
}
}
}
userAttrs
.
forEach
((
v
,
k
)
=>
{
userAttrs
.
forEach
((
v
,
k
)
=>
{
if
(
!
s
tudentI
ds
.
includes
(
+
v
.
uid
))
{
if
(
!
s
i
ds
.
includes
(
+
v
.
uid
))
{
if
(
`
${
v
.
uid
}
`
!=
`
${
teacherUid
}
`
)
{
if
(
`
${
v
.
uid
}
`
!=
`
${
teacherUid
}
`
)
{
const
s
:
any
=
{
const
s
:
any
=
{
streamID
:
+
v
.
uid
,
streamID
:
+
v
.
uid
,
...
@@ -210,7 +261,7 @@ export default function useStream () {
...
@@ -210,7 +261,7 @@ export default function useStream () {
},
[
},
[
course
,
course
,
me
.
uid
,
me
.
uid
,
roomStore
.
state
.
studentsOrder
,
//
roomStore.state.studentsOrder,
roomState
.
rtc
.
users
,
roomState
.
rtc
.
users
,
roomState
.
rtc
.
remoteStreams
,
roomState
.
rtc
.
remoteStreams
,
roomState
.
rtc
.
localStream
roomState
.
rtc
.
localStream
...
...
src/index.scss
View file @
6236ec53
...
@@ -95,7 +95,7 @@ body {
...
@@ -95,7 +95,7 @@ body {
background
:
#F5F7F8
;
background
:
#F5F7F8
;
border-radius
:
8px
0px
0px
8px
;
border-radius
:
8px
0px
0px
8px
;
position
:
relative
;
position
:
relative
;
.cover-placeholder
{
.cover-placeholder
{
display
:
block
;
display
:
block
;
background-repeat
:
no-repeat
;
background-repeat
:
no-repeat
;
...
@@ -288,13 +288,13 @@ body {
...
@@ -288,13 +288,13 @@ body {
@media
screen
and
(
max-width
:
780px
)
{
@media
screen
and
(
max-width
:
780px
)
{
.home-cover-web
{
.home-cover-web
{
min-width
:
780px
;
//
min-width: 780px;
}
}
}
}
@media
screen
and
(
max-height
:
768px
)
{
@media
screen
and
(
max-height
:
768px
)
{
.home-cover-web
{
.home-cover-web
{
min-height
:
768px
;
//
min-height: 768px;
}
}
}
}
...
@@ -322,4 +322,4 @@ body {
...
@@ -322,4 +322,4 @@ body {
}
}
}
}
}
}
}
}
\ No newline at end of file
src/pages/classroom/index.tsx
View file @
6236ec53
...
@@ -213,7 +213,7 @@ export function RoomPage({ children }: any) {
...
@@ -213,7 +213,7 @@ export function RoomPage({ children }: any) {
]);
]);
useEffect
(()
=>
{
useEffect
(()
=>
{
debugger
//
debugger
if
(
!
roomState
.
me
.
uid
||
!
roomState
.
course
.
rid
)
return
;
if
(
!
roomState
.
me
.
uid
||
!
roomState
.
course
.
rid
)
return
;
if
(
classroom
)
{
if
(
classroom
)
{
if
(
platform
===
'
web
'
)
{
if
(
platform
===
'
web
'
)
{
...
@@ -301,7 +301,7 @@ export function RoomPage({ children }: any) {
...
@@ -301,7 +301,7 @@ export function RoomPage({ children }: any) {
})
})
*/
*/
rtc
.
current
=
true
;
rtc
.
current
=
true
;
debugger
//
debugger
// WARN: IF YOU ENABLED APP CERTIFICATE, PLEASE SIGN YOUR TOKEN IN YOUR SERVER SIDE AND OBTAIN IT FROM YOUR OWN TRUSTED SERVER API
// WARN: IF YOU ENABLED APP CERTIFICATE, PLEASE SIGN YOUR TOKEN IN YOUR SERVER SIDE AND OBTAIN IT FROM YOUR OWN TRUSTED SERVER API
console
.
info
(
1.1
,
'
rtc join
'
)
console
.
info
(
1.1
,
'
rtc join
'
)
// if (roomState.me.role == 'teacher') {
// if (roomState.me.role == 'teacher') {
...
@@ -311,7 +311,7 @@ export function RoomPage({ children }: any) {
...
@@ -311,7 +311,7 @@ export function RoomPage({ children }: any) {
uid
:
+
roomState
.
me
.
uid
,
uid
:
+
roomState
.
me
.
uid
,
channel
:
roomState
.
course
.
rid
,
channel
:
roomState
.
course
.
rid
,
token
:
''
,
token
:
''
,
dual
:
isSmallClass
dual
:
true
}).
then
(()
=>
{
}).
then
(()
=>
{
console
.
info
(
2
,
'
rtc join ok
'
)
console
.
info
(
2
,
'
rtc join ok
'
)
roomStore
.
publishMeStream
();
roomStore
.
publishMeStream
();
...
@@ -452,10 +452,11 @@ export function RoomPage({ children }: any) {
...
@@ -452,10 +452,11 @@ export function RoomPage({ children }: any) {
console
.
log
(
1.15
,
'
stagedown?
'
,
222222
);
console
.
log
(
1.15
,
'
stagedown?
'
,
222222
);
roomStore
.
unPublishMeStream
();
roomStore
.
unPublishMeStream
();
}
}
console
.
log
(
1.2
,
studentsOrder
,
'
studentsOrder changed publish stream
'
);
}
}
console
.
log
(
1.2
,
studentsOrder
,
'
studentsOrder changed publish stream
'
);
},
[
studentsOrder
]);
},
[
studentsOrder
]);
...
...
src/pages/classroom/small-class.tsx
View file @
6236ec53
import
React
,
{
useEffect
,
useLayoutEffect
,
useMemo
,
useRef
,
useState
}
from
'
react
'
;
import
React
,
{
useEffect
,
useLayoutEffect
,
useMemo
,
useRef
,
useState
}
from
'
react
'
;
// import VideoMarquee from '../../components/video-marquee';
// import VideoMarquee from '../../components/video-marquee';
import
MediaBoard
from
'
../../components/mediaboard
'
;
import
MediaBoard
from
'
../../components/mediaboard
'
;
import
Roomboard
from
'
../../components/roomboard
'
;
//
import Roomboard from '../../components/roomboard';
import
'
./small-class.scss
'
;
import
'
./small-class.scss
'
;
import
CourseWareFrame
from
"
../../components/courseware-frame
"
;
import
CourseWareFrame
from
"
../../components/courseware-frame
"
;
import
VideoShowList
from
"
../../components/video-stage-list
"
;
import
VideoShowList
from
"
../../components/video-stage-list
"
;
import
{
ToolsSwitcherController
}
from
"
../../components/tools-switcher-controller
"
;
import
{
ToolsSwitcherController
}
from
"
../../components/tools-switcher-controller
"
;
import
{
roomStore
}
from
"
../../stores/room
"
;
import
{
roomStore
}
from
"
../../stores/room
"
;
import
{
TOOL_TYPE
}
from
"
../../utils/types
"
;
import
{
TOOL_TYPE
}
from
"
../../utils/types
"
;
import
{
platform
}
from
"
../../utils/platform
"
;
//
import {platform} from "../../utils/platform";
import
AgoraWebClient
from
"
../../utils/agora-rtc-client
"
;
//
import AgoraWebClient from "../../utils/agora-rtc-client";
import
{
AgoraElectronClient
}
from
"
../../utils/agora-electron-client
"
;
//
import {AgoraElectronClient} from "../../utils/agora-electron-client";
import
{
useRoomState
}
from
"
../../containers/root-container
"
;
import
{
useRoomState
}
from
"
../../containers/root-container
"
;
import
RoomToolsBar
from
"
../../components/room-tools-bar
"
;
//
import RoomToolsBar from "../../components/room-tools-bar";
export
default
function
SmallClass
()
{
export
default
function
SmallClass
()
{
const
[
tool
,
setTool
]
=
useState
(
true
);
const
[
tool
,
setTool
]
=
useState
(
true
);
...
@@ -39,15 +39,15 @@ export default function SmallClass() {
...
@@ -39,15 +39,15 @@ export default function SmallClass() {
{
/*<VideoMarquee />*/
}
{
/*<VideoMarquee />*/
}
<
VideoShowList
/>
<
VideoShowList
/>
<
div
className=
"container"
>
<
div
className=
"container"
>
{
roomStore
.
state
.
me
.
role
==
'
teacher
'
?<
ToolsSwitcherController
onClick=
{
()
=>
{
{
/*{roomStore.state.me.role == 'teacher' ?<ToolsSwitcherController onClick={() => {*/
}
changeTool
();
{
/* changeTool();*/
}
}
}
/>
:
null
}
{
/*}}/> : null}*/
}
{
currentTool
==
TOOL_TYPE
.
WHITEBOARD
{
currentTool
==
TOOL_TYPE
.
WHITEBOARD
?
<
MediaBoard
/>
?
<
MediaBoard
/>
:
<
CourseWareFrame
></
CourseWareFrame
>
}
:
<
CourseWareFrame
></
CourseWareFrame
>
}
{
roomStore
.
state
.
me
.
role
==
'
teacher
'
?
<
RoomToolsBar
/>
:
null
}
{
/*{ roomStore.state.me.role == 'teacher' ? <Roomboard currentActive={'media'} /> : null}*/
}
{
/*{ roomStore.state.me.role == 'teacher' ? <Roomboard currentActive={'media'} /> : null}*/
}
</
div
>
</
div
>
</
div
>
</
div
>
...
...
src/pages/home.tsx
View file @
6236ec53
...
@@ -79,17 +79,70 @@ function HomePage() {
...
@@ -79,17 +79,70 @@ function HomePage() {
setRequired
({...
required
,
yourPass
:
'
missing your password
'
});
setRequired
({...
required
,
yourPass
:
'
missing your password
'
});
return
;
return
;
}
}
///////////////////////////////
/*
session.roomName = "test_01__123";// userInfo["class_id"];
// session.yourName = userInfo["nick_name"];
session.role = `${session.yourName}`==="1"?"teacher":"student";
session.roomType = 1;
const path = roomTypes[session.roomType].path
const payload = {
uid: `${session.yourName}`, // genUid(),
rid: `${session.roomName}`, // `${session.roomType}${MD5(session.roomName)}`,
role: session.role,
roomName: session.roomName,
roomType: session.roomType,
video: 0,
audio: 0,
chat: 1,
account: session.yourName,
token: '',
boardId: '',
linkId: 0,
sharedId: 0,
lockBoard: 0,
}
ref.current = true;
globalStore.showLoading();
roomStore.loginAndJoin(payload).then(() => {
roomStore.updateSessionInfo(payload);
history.push(`/classroom/${path}`);
}).catch((err: any) => {
if (err.reason) {
globalStore.showToast({
type: 'rtmClient',
message: err.reason
})
} else {
globalStore.showToast({
type: 'rtmClient',
message: 'login failure, please checkout ur network'
})
}
console.warn(err);
})
.finally(() => {
ref.current = false;
globalStore.stopLoading();
})
*/
///////////////////////////////
endPoint
.
login
({
username
:
session
.
yourName
,
password
:
session
.
yourPass
}).
then
((
userInfo
:
any
)
=>
{
endPoint
.
login
({
username
:
session
.
yourName
,
password
:
session
.
yourPass
}).
then
((
userInfo
:
any
)
=>
{
console
.
log
(
userInfo
);
console
.
log
(
userInfo
);
session
.
roomName
=
userInfo
[
"
class_id
"
];
session
.
roomName
=
userInfo
[
"
class_id
"
];
// userInfo["class_id"];
session
.
yourName
=
userInfo
[
"
nick_name
"
];
//
session.yourName = userInfo["nick_name"];
session
.
role
=
userInfo
[
"
classRole
"
]
===
"
tea
"
?
"
teacher
"
:
"
student
"
;
session
.
role
=
userInfo
[
"
classRole
"
]
===
"
tea
"
?
"
teacher
"
:
"
student
"
;
session
.
roomType
=
1
;
session
.
roomType
=
1
;
if
(
!
roomTypes
[
session
.
roomType
])
return
;
if
(
!
roomTypes
[
session
.
roomType
])
return
;
const
path
=
roomTypes
[
session
.
roomType
].
path
const
path
=
roomTypes
[
session
.
roomType
].
path
const
payload
=
{
const
payload
=
{
uid
:
`
${
userInfo
[
"
id
"
]}
`
,
// genUid(),
uid
:
userInfo
[
"
classRole
"
]
===
"
tea
"
?
"
100
"
:
`
${
session
.
yourName
.
substr
(
-
2
)}
`
,
//
`${userInfo["id"]}`, // genUid(),
rid
:
`
${
session
.
roomName
}
`
,
// `${session.roomType}${MD5(session.roomName)}`,
rid
:
`
${
session
.
roomName
}
`
,
// `${session.roomType}${MD5(session.roomName)}`,
role
:
session
.
role
,
role
:
session
.
role
,
roomName
:
session
.
roomName
,
roomName
:
session
.
roomName
,
...
@@ -133,6 +186,8 @@ function HomePage() {
...
@@ -133,6 +186,8 @@ function HomePage() {
message
:
err
message
:
err
})
})
});
});
}
}
return
(
return
(
...
...
src/services/agora-end-points.ts
View file @
6236ec53
import
{
AgoraFetch
}
from
"
../utils/fetch
"
;
import
{
AgoraFetch
}
from
"
../utils/fetch
"
;
import
jwt_decode
from
'
jwt-decode
'
;
import
jwt_decode
from
'
jwt-decode
'
;
import
{
roomStore
}
from
"
../stores/room
"
;
const
ENDPOINT
:
string
=
process
.
env
.
REACT_APP_AGORA_ENDPOINT
as
string
;
const
ENDPOINT
:
string
=
process
.
env
.
REACT_APP_AGORA_ENDPOINT
as
string
;
...
@@ -78,6 +79,10 @@ export class EndPoint {
...
@@ -78,6 +79,10 @@ export class EndPoint {
}
}
getCourseUrl
(){
getCourseUrl
(){
if
(
!
this
.
userToken
)
{
this
.
userToken
=
roomStore
.
state
.
cwLink
;
}
console
.
log
(
'
getCourseUrl
'
,
this
.
userToken
)
return
`
${
ENDPOINT
}
/airclass_ol?token=
${
this
.
userToken
}
`
;
return
`
${
ENDPOINT
}
/airclass_ol?token=
${
this
.
userToken
}
`
;
}
}
...
...
src/stores/room.ts
View file @
6236ec53
...
@@ -17,14 +17,14 @@ function canJoin({uid, onlineStatus, roomType, channelCount, role}: { uid: any,
...
@@ -17,14 +17,14 @@ function canJoin({uid, onlineStatus, roomType, channelCount, role}: { uid: any,
permitted
:
true
,
permitted
:
true
,
reason
:
''
reason
:
''
}
}
const
channelCountLimit
=
[
2
,
17
,
17
];
//
const channelCountLimit = [2, 17, 17];
//
let
maximum
=
channelCountLimit
[
roomType
];
//
let maximum = channelCountLimit[roomType];
if
(
channelCount
>=
maximum
)
{
//
if (channelCount >= maximum) {
result
.
permitted
=
false
;
//
result.permitted = false;
result
.
reason
=
'
The number of students and teacher have reached upper limit
'
;
//
result.reason = 'The number of students and teacher have reached upper limit';
return
result
;
//
return result;
}
//
}
const
teacher
=
get
(
onlineStatus
,
'
teacher
'
,
false
);
const
teacher
=
get
(
onlineStatus
,
'
teacher
'
,
false
);
const
totalCount
:
number
=
get
(
onlineStatus
,
'
totalCount
'
,
0
);
const
totalCount
:
number
=
get
(
onlineStatus
,
'
totalCount
'
,
0
);
...
@@ -38,13 +38,13 @@ function canJoin({uid, onlineStatus, roomType, channelCount, role}: { uid: any,
...
@@ -38,13 +38,13 @@ function canJoin({uid, onlineStatus, roomType, channelCount, role}: { uid: any,
}
}
}
}
if
(
role
===
'
student
'
)
{
//
if (role === 'student') {
if
(
totalCount
+
1
>
maximum
)
{
//
if (totalCount+1 > maximum) {
result
.
permitted
=
false
;
//
result.permitted = false;
result
.
reason
=
'
Student have reached upper limit
'
;
//
result.reason = 'Student have reached upper limit';
return
result
;
//
return result;
}
//
}
}
//
}
return
result
;
return
result
;
}
}
...
@@ -124,6 +124,7 @@ export type RoomState = {
...
@@ -124,6 +124,7 @@ export type RoomState = {
mediaDevice
:
MediaDeviceState
mediaDevice
:
MediaDeviceState
messages
:
List
<
ChatMessage
>
messages
:
List
<
ChatMessage
>
studentsOrder
:
number
[]
studentsOrder
:
number
[]
cwLink
:
string
,
}
}
export
type
AgoraMediaStream
=
{
export
type
AgoraMediaStream
=
{
...
@@ -289,212 +290,92 @@ export class RoomStore {
...
@@ -289,212 +290,92 @@ export class RoomStore {
// @ts-ignore
// @ts-ignore
window
[
'
roomStore
'
]
=
this
;
window
[
'
roomStore
'
]
=
this
;
}
}
/*
async stageUpRtc(uid: string) {
async
stageDown
(
uid
:
string
)
{
let store = this._state.rtc.users;
// debugger
let itemsList = store.toList();
//把台上位置变零
const idx = itemsList.indexOf(+uid);
let
studentsOrder
:
any
[]
=
[...
this
.
state
.
studentsOrder
];
if (idx < STAGE_NUM) {
const
uidIndex
=
studentsOrder
.
indexOf
(
+
uid
)
return;
if
(
uidIndex
>
-
1
)
{
}
studentsOrder
.
splice
(
uidIndex
,
1
,
0
);
itemsList = itemsList.insert(0, +uid);
const
data
:
any
=
{};
const downVal = itemsList.get(STAGE_NUM);
data
[
'
studentsOrder
'
]
=
studentsOrder
;
if (downVal != undefined) {
const
downUser
:
AgoraUser
|
undefined
=
this
.
state
.
users
.
get
(
`
${
uid
}
`
);
itemsList = itemsList.splice(STAGE_NUM, 1).splice(idx, 1, downVal);
if
(
downUser
)
{
store = OrderedSet(itemsList)
downUser
.
audio
=
0
;
} else {
downUser
.
video
=
0
;
return ;
data
[
uid
]
=
downUser
}
this.state = {
...this.state,
rtc: {
...this.state.rtc,
users: store,
}
}
await
this
.
rtmClient
.
addOrUpdateChannelAttributes
(
data
);
}
}
this.commit(this.state);
}
}
async stageDownRtc(uid: string) {
async
stageUp
(
uid
:
string
)
{
let store = this._state.rtc.users;
let
studentsOrder
:
any
[]
=
[...
this
.
state
.
studentsOrder
];
console.log(store);
const
data
:
any
=
{};
// let uid = 2;
const
emptyIndex
=
studentsOrder
.
indexOf
(
0
);
// stageNum = 3;
if
(
emptyIndex
>
-
1
)
{
let itemsList = store.toList();
studentsOrder
[
emptyIndex
]
=
+
uid
;
let idx = itemsList.indexOf(+uid);
const
upUser
:
AgoraUser
|
undefined
=
this
.
state
.
users
.
get
(
`
${
uid
}
`
);
if (idx >= STAGE_NUM) {
if
(
upUser
)
{
return;
upUser
.
video
=
1
;
}
upUser
.
audio
=
1
;
let upVal = itemsList.get(STAGE_NUM);
data
[
upUser
.
uid
]
=
upUser
;
let downVal = itemsList.get(idx);
}
if (upVal != undefined && downVal != undefined) {
itemsList = itemsList.splice(STAGE_NUM, 1).splice(idx, 1, upVal).push(downVal)
store = OrderedSet(itemsList)
}
else
{
}
else
{
return
return
}
}
this.state = {
data
[
'
studentsOrder
'
]
=
studentsOrder
;
...this.state,
await
this
.
rtmClient
.
addOrUpdateChannelAttributes
(
data
);
rtc: {
...this.state.rtc,
users: store,
}
}
this.commit(this.state);
}
}
async stageUp1(uid: string) {
async
stageUp3333
(
uid
:
string
)
{
const attrs = await this.rtmClient.getChannelAttrs();
debugger
let studentsOrder: any[] = [];
let
studentsOrder
:
any
[]
=
[...
this
.
state
.
studentsOrder
];
// if ((attrs as any).studentsOrder && (attrs as any).studentsOrder.value) {
// studentsOrder = JSON.parse((attrs as any).studentsOrder.value) || [];
// }
const data: any = {};
const onlineStatus = JSON.parse(attrs)
const target = jsonParse(get(onlineStatus[uid], 'value'));
// 上台需要开启视频
// if (!+target.video) {
target.video = 1;
data[uid] = JSON.stringify(target)
// }
const tmp: [string, AgoraUser][] =[];
const
data
:
any
=
{};
this._state.users.forEach((v, k)=>{
const
emptyIndex
=
studentsOrder
.
indexOf
(
0
);
if (/^[0-9]+$/.test(k)) {
if
(
emptyIndex
>
-
1
)
{
tmp.push([k, v])
studentsOrder
[
emptyIndex
]
=
+
uid
;
const
upUser
:
AgoraUser
|
undefined
=
this
.
state
.
users
.
get
(
`
${
uid
}
`
);
if
(
upUser
)
{
upUser
.
video
=
1
;
upUser
.
audio
=
1
;
data
[
upUser
.
uid
]
=
upUser
;
}
}
else
{
studentsOrder
.
unshift
(
+
uid
);
let
lastUid
=
studentsOrder
[
studentsOrder
.
length
-
1
];
const
lastUser
:
AgoraUser
|
undefined
=
this
.
state
.
users
.
get
(
`
${
lastUid
}
`
);
if
(
lastUser
)
{
lastUser
.
video
=
0
;
lastUser
.
audio
=
0
;
data
[
lastUser
.
uid
]
=
lastUser
;
}
}
})
const uidIdx = tmp.findIndex((o) => {
return `${o[0]}` == `${uid}`
})
const uidObj = tmp[uidIdx]
tmp.splice(uidIdx, 1)
const stageEndObj = tmp[STAGE_NUM - 1]
tmp.splice(STAGE_NUM - 1, 1)
tmp.unshift(uidObj);
tmp.push(stageEndObj)
// 下台关闭音视频
// stageEndObj[1].audio = 0;
// stageEndObj[1].video = 0;
data[stageEndObj[1].uid] = JSON.stringify(stageEndObj[1])
tmp.forEach(o => {
studentsOrder.push(+o[0]);
});
// const queue = {'studentsOrder': JSON.stringify(studentsOrder)};
data['studentsOrder'] = JSON.stringify(studentsOrder)
const aa = await this.rtmClient.addOrUpdateChannelAttributes(data);
console.log(aa)
const users = OrderedMap(tmp);
// this.state = {
const
upUser
:
AgoraUser
|
undefined
=
this
.
state
.
users
.
get
(
`
${
uid
}
`
);
// ...this.state,
if
(
upUser
)
{
// users
upUser
.
video
=
1
;
// }
upUser
.
audio
=
1
;
data
[
upUser
.
uid
]
=
upUser
;
}
// this.commit(this.state);
if
(
!
lastUser
||
!
upUser
)
{
}
return
async stageDown2(uid: string) {
}
const tmp: [string, AgoraUser][] =[];
this._state.users.forEach((v, k)=>{
tmp.push([k, v])
})
console.log(tmp);
const uidIdx = tmp.findIndex((o) => {
return `${o[0]}` == `${uid}`
})
const uidObj = tmp[uidIdx]
const waitUpObj = tmp[STAGE_NUM]
tmp.splice(uidIdx, 1, waitUpObj)
tmp.splice(STAGE_NUM , 1)
tmp.push(uidObj)
const users = OrderedMap(tmp);
this.state = {
...this.state,
users
}
this.commit(this.state);
}
async stageUp2(uid: string) {
const attrs = await this.rtmClient.getChannelAttrs();
let studentsOrder: any[] = [];
// if ((attrs as any).studentsOrder && (attrs as any).studentsOrder.value) {
// studentsOrder = JSON.parse((attrs as any).studentsOrder.value) || [];
// }
const data: any = {};
const onlineStatus = jsonParse(attrs)
let target = jsonParse(get(onlineStatus[uid], 'value'));
if (typeof(target) == 'string') {
target = jsonParse(target)
}
// 上台需要开启视频
// if (!+target.video) {
target.video = 1;
data[uid] = target
// }
const tmp: [string, AgoraUser][] =[];
if
(
studentsOrder
.
length
>
STAGE_NUM
)
{
this._state.users.forEach((v, k)=>{
studentsOrder
.
length
=
STAGE_NUM
if (/^[0-9]+$/.test(k)) {
tmp.push([k, v])
}
}
})
}
const uidIdx = tmp.findIndex((o) => {
return `${o[0]}` == `${uid}`
})
const uidObj = tmp[uidIdx]
tmp.splice(uidIdx, 1)
const stageEndObj = tmp[STAGE_NUM - 1]
tmp.splice(STAGE_NUM - 1, 1)
tmp.unshift(uidObj);
tmp.push(stageEndObj)
// 下台关闭音视频
// stageEndObj[1].audio = 0;
// stageEndObj[1].video = 0;
data[stageEndObj[1].uid] = stageEndObj[1]
tmp.forEach(o => {
studentsOrder.push(+o[0]);
});
// const queue = {'studentsOrder': JSON.stringify(studentsOrder)};
data['studentsOrder'] = studentsOrder
const aa = await this.rtmClient.addOrUpdateChannelAttributes(data);
console.log(aa)
const users = OrderedMap(tmp);
// this.state = {
// ...this.state,
// users
// }
// this.commit(this.state);
}
*/
async
stageDown
(
uid
:
string
)
{}
async
stageUp
(
uid
:
string
)
{
debugger
let
studentsOrder
:
any
[]
=
[...
this
.
state
.
studentsOrder
];
studentsOrder
.
unshift
(
+
uid
);
const
lastUid
=
studentsOrder
[
studentsOrder
.
length
-
1
];
const
lastUser
:
AgoraUser
|
undefined
=
this
.
state
.
users
.
get
(
`
${
lastUid
}
`
);
const
upUser
:
AgoraUser
|
undefined
=
this
.
state
.
users
.
get
(
`
${
uid
}
`
);
if
(
!
lastUser
||
!
upUser
)
{
return
}
lastUser
.
video
=
0
;
lastUser
.
audio
=
0
;
upUser
.
video
=
1
;
upUser
.
audio
=
1
;
studentsOrder
.
length
=
STAGE_NUM
;
const
data
:
any
=
{};
data
[
upUser
.
uid
]
=
upUser
;
data
[
lastUser
.
uid
]
=
lastUser
;
data
[
'
studentsOrder
'
]
=
studentsOrder
;
data
[
'
studentsOrder
'
]
=
studentsOrder
;
await
this
.
rtmClient
.
addOrUpdateChannelAttributes
(
data
);
await
this
.
rtmClient
.
addOrUpdateChannelAttributes
(
data
);
...
@@ -511,6 +392,7 @@ export class RoomStore {
...
@@ -511,6 +392,7 @@ export class RoomStore {
// this.commit(this.state);
// this.commit(this.state);
}
}
async
randomStageUp
()
{
async
randomStageUp
()
{
const
users
=
roomStore
.
state
.
users
;
const
users
=
roomStore
.
state
.
users
;
const
studentsOrder
=
roomStore
.
state
.
studentsOrder
||
[];
const
studentsOrder
=
roomStore
.
state
.
studentsOrder
||
[];
...
@@ -925,8 +807,16 @@ export class RoomStore {
...
@@ -925,8 +807,16 @@ export class RoomStore {
const
channelMemberCount
=
await
this
.
rtmClient
.
getChannelMemberCount
([
rid
]);
const
channelMemberCount
=
await
this
.
rtmClient
.
getChannelMemberCount
([
rid
]);
const
channelCount
=
channelMemberCount
[
rid
];
const
channelCount
=
channelMemberCount
[
rid
];
const
channelMeta
=
await
this
.
rtmClient
.
getChannelAttributeBy
(
rid
);
const
channelMeta
=
await
this
.
rtmClient
.
getChannelAttributeBy
(
rid
);
if
(
payload
.
role
==
'
student
'
&&
!
channelMeta
.
teacher
)
{
throw
{
type
:
'
not_permitted
'
,
reason
:
'
classroom not start yet
'
}
return
}
let
accounts
=
channelMeta
.
accounts
;
let
accounts
=
channelMeta
.
accounts
;
const
onlineStatus
=
await
this
.
rtmClient
.
queryOnlineStatusBy
(
accounts
);
const
onlineStatus
=
await
this
.
rtmClient
.
queryOnlineStatusBy
(
accounts
);
/*
/*
const me = accounts.find((o)=>{return `${payload.uid}` === `${o.uid}`});
const me = accounts.find((o)=>{return `${payload.uid}` === `${o.uid}`});
if (onlineStatus[payload.uid]) {
if (onlineStatus[payload.uid]) {
...
@@ -962,10 +852,24 @@ export class RoomStore {
...
@@ -962,10 +852,24 @@ export class RoomStore {
};
};
let
result
=
pass
===
false
?
canJoin
(
argsJoin
)
:
{
permitted
:
true
,
reason
:
''
};
let
result
=
pass
===
false
?
canJoin
(
argsJoin
)
:
{
permitted
:
true
,
reason
:
''
};
let
studentsOrder
:
number
[]
=
[];
let
studentsOrder
:
number
[]
=
channelMeta
.
studentsOrder
||
[];
if
(
result
.
permitted
)
{
if
(
result
.
permitted
)
{
// studentsOrder = this.state.studentsOrder;
if
(
payload
.
role
==
'
teacher
'
)
{
/*
// studentsOrder = channelMeta.studentsOrder || [];//this.state.studentsOrder;
if
(
studentsOrder
.
length
<
STAGE_NUM
)
{
Array
(
STAGE_NUM
-
studentsOrder
.
length
).
fill
(
0
).
forEach
((
zero
)
=>
{
studentsOrder
.
push
(
zero
)
})
}
}
else
{
//查看有无空闲
if
(
!
studentsOrder
.
includes
(
+
payload
.
uid
))
{
const
emptyIndex
=
studentsOrder
.
indexOf
(
0
);
if
(
emptyIndex
>
-
1
)
{
studentsOrder
.
splice
(
emptyIndex
,
1
,
+
payload
.
uid
);
}
}
/*
if (!studentsOrder.length) {
if (!studentsOrder.length) {
accounts.forEach(a => {
accounts.forEach(a => {
if (!studentsOrder.includes(+a.uid)) {
if (!studentsOrder.includes(+a.uid)) {
...
@@ -998,17 +902,21 @@ export class RoomStore {
...
@@ -998,17 +902,21 @@ export class RoomStore {
}
}
}
}
*/
*/
let
onlineMe
=
accounts
.
find
((
it
:
any
)
=>
`
${
it
.
uid
}
`
==
`
${
payload
.
uid
}
`
);
if
(
onlineMe
)
{
console
.
log
(
'
login accounts
'
,
accounts
)
payload
.
video
=
onlineMe
.
video
;
let
onlineMe
=
accounts
.
find
((
it
:
any
)
=>
`
${
it
.
uid
}
`
==
`
${
payload
.
uid
}
`
);
payload
.
audio
=
onlineMe
.
audio
;
if
(
onlineMe
)
{
}
else
{
payload
.
video
=
onlineMe
.
video
;
if
(
channelMeta
.
studentsOrder
&&
channelMeta
.
studentsOrder
.
includes
(
+
payload
.
uid
))
{
payload
.
audio
=
onlineMe
.
audio
;
payload
.
video
=
1
;
}
else
{
payload
.
audio
=
1
;
if
(
studentsOrder
&&
studentsOrder
.
includes
(
+
payload
.
uid
))
{
payload
.
video
=
1
;
payload
.
audio
=
1
;
}
}
}
}
}
console
.
log
(
'
login payload
'
,
payload
)
console
.
log
(
'
login studentsOrder
'
,
studentsOrder
)
let
res
=
await
this
.
rtmClient
.
join
(
rid
).
then
(
async
r
=>
{
let
res
=
await
this
.
rtmClient
.
join
(
rid
).
then
(
async
r
=>
{
this
.
state
=
{
this
.
state
=
{
...
@@ -1020,7 +928,7 @@ export class RoomStore {
...
@@ -1020,7 +928,7 @@ export class RoomStore {
}
}
const
grantBoard
=
role
===
'
teacher
'
?
1
:
0
;
const
grantBoard
=
role
===
'
teacher
'
?
1
:
0
;
console
.
log
(
"
>>>>>>>>>>#room:
"
,
grantBoard
);
console
.
log
(
"
>>>>>>>>>>#room:
"
,
grantBoard
);
await
this
.
updateMe
({...
payload
,
grantBoard
});
await
this
.
updateMe
({...
payload
,
grantBoard
}
,
studentsOrder
);
this
.
commit
(
this
.
state
);
this
.
commit
(
this
.
state
);
});
});
// this.state = {
// this.state = {
...
@@ -1163,7 +1071,7 @@ export class RoomStore {
...
@@ -1163,7 +1071,7 @@ export class RoomStore {
await
this
.
rtmClient
.
addOrUpdateChannelAttributes
(
data
);
await
this
.
rtmClient
.
addOrUpdateChannelAttributes
(
data
);
}
}
async
updateMe
(
user
:
any
)
{
async
updateMe
(
user
:
any
,
studentsOrder
:
number
[]
=
[]
)
{
const
{
role
,
uid
,
account
,
rid
,
video
,
audio
,
chat
,
boardId
,
linkId
,
sharedId
,
muteChat
,
muteAudio
,
grantBoard
}
=
user
;
const
{
role
,
uid
,
account
,
rid
,
video
,
audio
,
chat
,
boardId
,
linkId
,
sharedId
,
muteChat
,
muteAudio
,
grantBoard
}
=
user
;
const
key
=
role
===
'
teacher
'
?
'
teacher
'
:
uid
;
const
key
=
role
===
'
teacher
'
?
'
teacher
'
:
uid
;
const
me
=
this
.
state
.
me
;
const
me
=
this
.
state
.
me
;
...
@@ -1216,17 +1124,17 @@ export class RoomStore {
...
@@ -1216,17 +1124,17 @@ export class RoomStore {
}
}
const
data
:
any
=
{};
const
data
:
any
=
{};
data
[
key
]
=
attrs
;
data
[
key
]
=
attrs
;
//
if (studentsOrder && studentsOrder.length) {
if
(
studentsOrder
&&
studentsOrder
.
length
)
{
//
data['studentsOrder'] = studentsOrder;
data
[
'
studentsOrder
'
]
=
studentsOrder
;
//
}
}
console
.
log
(
'
update me
'
,
data
);
console
.
log
(
'
update me
'
,
data
);
await
this
.
rtmClient
.
addOrUpdateChannelAttributes
(
data
);
await
this
.
rtmClient
.
addOrUpdateChannelAttributes
(
data
);
// let res = await this.rtmClient.updateChannelAttrsByKey(key, attrs);
// let res = await this.rtmClient.updateChannelAttrsByKey(key, attrs);
// return res;
// return res;
}
}
async
syncStageStudent
(
accounts
:
any
[],
studentsOrder
:
number
[])
{
async
syncStageStudent
__
(
accounts
:
any
[],
studentsOrder
:
number
[])
{
debugger
//
debugger
let
needUpdate
=
false
;
let
needUpdate
=
false
;
const
data
:
any
=
{};
const
data
:
any
=
{};
const
accData
:
any
=
{};
const
accData
:
any
=
{};
...
@@ -1236,14 +1144,14 @@ export class RoomStore {
...
@@ -1236,14 +1144,14 @@ export class RoomStore {
}
}
})
})
// 学生在台上并且退出了
const
accIds
:
any
[]
=
Object
.
keys
(
accData
).
map
(
uid
=>
+
uid
);
const
accIds
:
any
[]
=
Object
.
keys
(
accData
).
map
(
uid
=>
+
uid
);
if
(
!
accIds
.
length
)
{
if
(
!
accIds
.
length
)
{
return
return
}
}
// 学生在台上并且退出了
const
exitUserIds
=
studentsOrder
.
filter
(
uid
=>
{
const
exitUserIds
=
studentsOrder
.
filter
(
uid
=>
{
return
!
accIds
.
includes
(
uid
);
return
!
accIds
.
includes
(
uid
)
&&
uid
!=
0
;
});
});
if
(
exitUserIds
.
length
)
{
if
(
exitUserIds
.
length
)
{
exitUserIds
.
forEach
(
uid
=>
{
exitUserIds
.
forEach
(
uid
=>
{
...
@@ -1281,7 +1189,7 @@ export class RoomStore {
...
@@ -1281,7 +1189,7 @@ export class RoomStore {
}
}
if
(
studentsOrder
.
length
<
STAGE_NUM
)
{
if
(
studentsOrder
.
length
<
STAGE_NUM
)
{
const
newUid
=
accIds
.
find
(
uid
=>
{
const
newUid
=
accIds
.
find
(
uid
=>
{
return
!
studentsOrder
.
includes
(
+
uid
);
return
!
studentsOrder
.
includes
(
+
uid
)
;
});
});
const
newStudents
=
accData
[
newUid
];
const
newStudents
=
accData
[
newUid
];
if
(
newStudents
)
{
if
(
newStudents
)
{
...
@@ -1297,6 +1205,122 @@ export class RoomStore {
...
@@ -1297,6 +1205,122 @@ export class RoomStore {
}
}
}
}
}
}
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
;
}
}
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
}
// 学生在台上并且退出了
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
}
})
}
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
;
// }
}
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
)
needUpdate
=
true
;
// }
}
}
}
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
;
// }
}
}
}
for
(
const
uid
of
Object
.
keys
(
accData
))
{
if
(
!
studentsOrder
.
includes
(
+
uid
))
{
const
ud
=
{...
accData
[
uid
]};
ud
.
video
=
0
;
ud
.
audio
=
1
;
data
[
uid
]
=
ud
}
}
if
(
needUpdate
)
{
if
(
needUpdate
)
{
data
[
'
studentsOrder
'
]
=
studentsOrder
;
data
[
'
studentsOrder
'
]
=
studentsOrder
;
// await this.rtmClient.addOrUpdateChannelAttributes(data);
// await this.rtmClient.addOrUpdateChannelAttributes(data);
...
@@ -1306,8 +1330,8 @@ export class RoomStore {
...
@@ -1306,8 +1330,8 @@ export class RoomStore {
async
updateRoomAttrs
({
teacher
,
accounts
,
room
,
studentsOrder
}:
{
teacher
:
any
,
accounts
:
any
,
room
:
any
,
studentsOrder
:
number
[]})
{
async
updateRoomAttrs
({
teacher
,
accounts
,
room
,
studentsOrder
}:
{
teacher
:
any
,
accounts
:
any
,
room
:
any
,
studentsOrder
:
number
[]})
{
console
.
log
(
"
[agora-board], room:
"
,
teacher
,
accounts
,
room
,
studentsOrder
);
console
.
log
(
"
[agora-board], room:
"
,
teacher
,
accounts
,
room
,
studentsOrder
);
const
exitUserIds
=
[];
const
users
=
accounts
.
reduce
((
acc
:
OrderedMap
<
string
,
AgoraUser
>
,
it
:
any
)
=>
{
const
users
:
OrderedMap
<
string
,
AgoraUser
>
=
accounts
.
reduce
((
acc
:
OrderedMap
<
string
,
AgoraUser
>
,
it
:
any
)
=>
{
return
acc
.
set
(
it
.
uid
,
{
return
acc
.
set
(
it
.
uid
,
{
role
:
it
.
role
,
role
:
it
.
role
,
account
:
it
.
account
,
account
:
it
.
account
,
...
@@ -1341,7 +1365,15 @@ export class RoomStore {
...
@@ -1341,7 +1365,15 @@ export class RoomStore {
})
})
}
}
*/
*/
console
.
log
(
'
users 4
'
,
users
.
toArray
());
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
;
const
me
=
this
.
state
.
me
;
if
(
users
.
get
(
me
.
uid
))
{
if
(
users
.
get
(
me
.
uid
))
{
...
@@ -1364,13 +1396,13 @@ export class RoomStore {
...
@@ -1364,13 +1396,13 @@ export class RoomStore {
lockBoard
:
room
.
lock_board
,
lockBoard
:
room
.
lock_board
,
})
})
//教师维护学生顺序,仅保留STAGE_NUM个,并更新到频道属性
//教师维护学生顺序,仅保留STAGE_NUM个,并更新到频道属性
const
newInfo
:
any
=
await
this
.
syncStageStudent
(
JSON
.
parse
(
JSON
.
stringify
(
accounts
)),
[...
studentsOrder
]);
/*
const newInfo: any = await this.syncStageStudent(JSON.parse(JSON.stringify(accounts)), [...studentsOrder]);
console.log('newInfo', newInfo)
console.log('newInfo', newInfo)
debugger
//
debugger
if (newInfo) {
if (newInfo) {
newStudentsOrder = newInfo['studentsOrder'];
newStudentsOrder = newInfo['studentsOrder'];
await this.rtmClient.addOrUpdateChannelAttributes(newInfo);
await this.rtmClient.addOrUpdateChannelAttributes(newInfo);
}
}
*/
}
}
const
newClassState
:
ClassState
=
{}
as
ClassState
;
const
newClassState
:
ClassState
=
{}
as
ClassState
;
...
@@ -1431,16 +1463,45 @@ export class RoomStore {
...
@@ -1431,16 +1463,45 @@ export class RoomStore {
async
exitAll
()
{
async
exitAll
()
{
console
.
log
(
'
exitAll
'
)
console
.
log
(
'
exitAll
'
)
if
(
this
.
state
.
me
.
role
==
'
teacher
'
)
{
await
this
.
rtmClient
.
clearChannelAttributes
()
}
try
{
try
{
await
this
.
rtmClient
.
exit
();
if
(
this
.
state
.
me
.
role
==
'
teacher
'
)
{
await
this
.
rtcClient
.
exit
();
await
this
.
rtmClient
.
clearChannelAttributes
()
}
else
{
await
this
.
rtmClient
.
clearChannelAttributesByKeys
([
`
${
this
.
state
.
me
.
uid
}
`
]);
}
await
this
.
rtmClient
.
logout
();
const
webClient
=
roomStore
.
rtcClient
as
AgoraWebClient
;
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
"
);
await
roomStore
.
rtmClient
.
logout
();
console
.
log
(
"
[agora-web] remove event listener
"
);
webClient
.
exit
().
then
(()
=>
{
console
.
log
(
"
[agora-web] do remove event listener
"
);
}).
catch
(
console
.
warn
)
.
finally
(()
=>
{
roomStore
.
removeLocalStream
();
});
// await this.rtcClient.exit();
GlobalStorage
.
clear
(
'
agora_room
'
);
}
catch
(
err
)
{
}
catch
(
err
)
{
console
.
warn
(
err
);
// debugger
console
.
warn
(
'
exitAll
'
,
err
);
}
finally
{
}
finally
{
GlobalStorage
.
clear
(
'
agora_room
'
);
this
.
state
=
{}
as
RoomState
;
this
.
state
=
{}
as
RoomState
;
this
.
state
=
{
this
.
state
=
{
...
this
.
defaultState
...
this
.
defaultState
...
...
src/utils/agora-rtm-client.ts
View file @
6236ec53
...
@@ -98,9 +98,12 @@ export default class AgoraRTMClient {
...
@@ -98,9 +98,12 @@ export default class AgoraRTMClient {
this
.
_logged
=
true
;
this
.
_logged
=
true
;
return
return
}
}
async
clearChannelAttributesByKeys
(
uids
:
string
[])
{
await
this
.
_client
.
deleteChannelAttributesByKeys
(
this
.
_currentChannelName
,
uids
,
{
enableNotificationToChannelMembers
:
true
});
}
async
clearChannelAttributes
()
{
async
clearChannelAttributes
()
{
await
this
.
_client
.
clearChannelAttributes
(
this
.
_currentChannelName
);
await
this
.
_client
.
clearChannelAttributes
(
this
.
_currentChannelName
,
{
enableNotificationToChannelMembers
:
true
}
);
}
}
async
logout
()
{
async
logout
()
{
...
@@ -155,7 +158,11 @@ export default class AgoraRTMClient {
...
@@ -155,7 +158,11 @@ export default class AgoraRTMClient {
this
.
destroyChannel
(
channel
);
this
.
destroyChannel
(
channel
);
}
}
}
}
async
leaveChannel
()
{
// await this._client.clearLocalUserAttributes();
await
this
.
leave
(
this
.
_currentChannelName
);
await
this
.
logout
();
}
async
exit
()
{
async
exit
()
{
await
this
.
deleteChannelAttributesByKey
();
await
this
.
deleteChannelAttributesByKey
();
await
this
.
leave
(
this
.
_currentChannelName
);
await
this
.
leave
(
this
.
_currentChannelName
);
...
...
src/utils/consts.ts
View file @
6236ec53
export
const
STAGE_NUM
:
number
=
1
;
export
const
STAGE_NUM
:
number
=
6
;
src/utils/helper.ts
View file @
6236ec53
...
@@ -256,6 +256,7 @@ export function resolveChannelAttrs(json: object) {
...
@@ -256,6 +256,7 @@ export function resolveChannelAttrs(json: object) {
let
students
:
any
[]
=
[];
let
students
:
any
[]
=
[];
for
(
let
key
of
Object
.
keys
(
json
))
{
for
(
let
key
of
Object
.
keys
(
json
))
{
if
(
key
===
'
teacher
'
)
continue
;
if
(
key
===
'
teacher
'
)
continue
;
if
(
!
/^
[
0-9
]
+$/
.
test
(
key
))
continue
;
const
student
=
jsonParse
(
_
.
get
(
json
,
`
${
key
}
.value`
));
const
student
=
jsonParse
(
_
.
get
(
json
,
`
${
key
}
.value`
));
if
(
student
&&
Object
.
keys
(
student
).
length
)
{
if
(
student
&&
Object
.
keys
(
student
).
length
)
{
student
.
uid
=
key
;
student
.
uid
=
key
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment