agora-edu-core
Version:
Core APIs for building an online classroom
625 lines (602 loc) • 22.3 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.GroupStore = void 0;
require("core-js/modules/esnext.map.delete-all.js");
require("core-js/modules/esnext.map.every.js");
require("core-js/modules/esnext.map.filter.js");
require("core-js/modules/esnext.map.find.js");
require("core-js/modules/esnext.map.find-key.js");
require("core-js/modules/esnext.map.includes.js");
require("core-js/modules/esnext.map.key-of.js");
require("core-js/modules/esnext.map.map-keys.js");
require("core-js/modules/esnext.map.map-values.js");
require("core-js/modules/esnext.map.merge.js");
require("core-js/modules/esnext.map.reduce.js");
require("core-js/modules/esnext.map.some.js");
require("core-js/modules/esnext.map.update.js");
var _agoraRteSdk = require("agora-rte-sdk");
var _cloneDeep = _interopRequireDefault(require("lodash/cloneDeep"));
var _startsWith = _interopRequireDefault(require("lodash/startsWith"));
var _get = _interopRequireDefault(require("lodash/get"));
var _mobx = require("mobx");
var _configs = require("../../../../configs");
var _eventCenter = require("../../../../event-center");
var _type = require("../../../../type");
var _error = require("../../../../utils/error");
var _base = require("../base");
var _type2 = require("./type");
var _dec, _dec2, _dec3, _dec4, _class, _class2, _descriptor, _descriptor2, _descriptor3, _GroupStore;
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
function _initializerDefineProperty(e, i, r, l) { r && Object.defineProperty(e, i, { enumerable: r.enumerable, configurable: r.configurable, writable: r.writable, value: r.initializer ? r.initializer.call(l) : void 0 }); }
function _applyDecoratedDescriptor(i, e, r, n, l) { var a = {}; return Object.keys(n).forEach(function (i) { a[i] = n[i]; }), a.enumerable = !!a.enumerable, a.configurable = !!a.configurable, ("value" in a || a.initializer) && (a.writable = !0), a = r.slice().reverse().reduce(function (r, n) { return n(i, e, r) || r; }, a), l && void 0 !== a.initializer && (a.value = a.initializer ? a.initializer.call(l) : void 0, a.initializer = void 0), void 0 === a.initializer ? (Object.defineProperty(i, e, a), null) : a; }
function _initializerWarningHelper(r, e) { throw Error("Decorating class property failed. Please ensure that transform-class-properties is enabled and runs after the decorators transform."); }
/**
* `GroupStore` 类提供分组讨论功能相关的能力。
*/
/** @en
* The `GroupStore` class provides abilities related to breakout rooms.
*/
let GroupStore = exports.GroupStore = (_dec = _agoraRteSdk.Log.attach({
proxyMethods: false
}), _dec2 = _mobx.action.bound, _dec3 = _mobx.action.bound, _dec4 = _mobx.action.bound, _dec(_class = (_class2 = (_GroupStore = class GroupStore extends _base.EduStoreBase {
constructor(...args) {
super(...args);
this._currentGroupUuid = void 0;
this._inviting = false;
this._disposers = [];
_initializerDefineProperty(this, "_operationQueue", _descriptor, this);
/**
* 分组状态
*/
/** @en
* The current state of grouping
*/
_initializerDefineProperty(this, "state", _descriptor2, this);
/**
* 分组详情
*/
/** @en
* Details of groups
*/
_initializerDefineProperty(this, "groupDetails", _descriptor3, this);
}
/** Methods */
_handleRoomPropertiesChange(changedRoomProperties, roomProperties, operator, cause) {
changedRoomProperties.forEach(key => {
if (key === 'groups') {
const groups = (0, _get.default)(roomProperties, 'groups', {});
const processes = (0, _get.default)(roomProperties, 'processes', {});
const progress = this._getProgress(processes);
this._setDetails(groups.details || {}, progress);
this.state = groups.state;
this._checkSubRoom();
}
if (key === 'processes') {
const groups = (0, _get.default)(roomProperties, 'groups', {});
const processes = (0, _get.default)(roomProperties, 'processes', {});
const progress = this._getProgress(processes);
this._setDetails(groups.details || {}, progress);
this.state = groups.state;
}
});
if (cause) {
const {
cmd,
data
} = cause;
// Emit event when local user is invited by teacher
if (cmd === 501 && (0, _startsWith.default)(data.processUuid, GroupStore.CMD_PROCESS_PREFIX)) {
const groupUuid = data.processUuid.substring(GroupStore.CMD_PROCESS_PREFIX.length);
const progress = data.addProgress || [];
const accepted = data.addAccepted || [];
const actionType = data.actionType;
const removeProgress = data.removeProgress || [];
const {
userUuid: localUuid
} = _configs.EduClassroomConfig.shared.sessionInfo;
const invitedLocal = progress.find(({
userUuid
}) => userUuid === localUuid);
if (invitedLocal) {
_eventCenter.EduEventCenter.shared.emitClasroomEvents(_type.AgoraEduClassroomEvent.InvitedToGroup, invitedLocal.payload);
}
// accepted
if (actionType === 2 && accepted.length) {
_eventCenter.EduEventCenter.shared.emitClasroomEvents(_type.AgoraEduClassroomEvent.AcceptedToGroup, {
groupUuid,
accepted
});
}
// reject invitation
if ((actionType === 3 || actionType === 7) && removeProgress.length) {
const inviting = this._inviting;
this._inviting = false;
_eventCenter.EduEventCenter.shared.emitClasroomEvents(_type.AgoraEduClassroomEvent.RejectedToGroup, {
groupUuid,
removeProgress,
inviting
});
}
}
// user in out
if (cmd === 11 && data.actionType === 4) {
const groups = data.changeGroups || [];
groups.forEach(({
groupUuid,
addUsers,
removeUsers
}) => {
if (addUsers.length) {
_eventCenter.EduEventCenter.shared.emitClasroomEvents(_type.AgoraEduClassroomEvent.UserJoinGroup, {
groupUuid,
users: addUsers.map(({
userUuid
}) => userUuid)
});
}
if (removeUsers.length) {
_eventCenter.EduEventCenter.shared.emitClasroomEvents(_type.AgoraEduClassroomEvent.UserLeaveGroup, {
groupUuid,
users: removeUsers.map(({
userUuid
}) => userUuid)
});
}
});
}
}
}
_getProgress(processes) {
const progress = Object.keys(processes).reduce((prev, k) => {
if (k.startsWith(GroupStore.CMD_PROCESS_PREFIX)) {
const groupUuid = k.substring(GroupStore.CMD_PROCESS_PREFIX.length);
const users = processes[k].progress.map(({
userUuid
}) => userUuid);
prev.set(groupUuid, users);
}
return prev;
}, new Map());
return progress;
}
_setDetails(details, progress) {
const newGroupDetails = new Map();
const cloneDetails = (0, _cloneDeep.default)(details);
Object.entries(cloneDetails).forEach(([groupUuid, groupDetail]) => {
if (progress.has(groupUuid)) {
var _progress$get;
const notJoinedUsers = ((_progress$get = progress.get(groupUuid)) === null || _progress$get === void 0 ? void 0 : _progress$get.map(userUuid => ({
userUuid,
notJoined: true
}))) || [];
groupDetail.users.unshift(...notJoinedUsers);
}
newGroupDetails.set(groupUuid, groupDetail);
});
this.groupDetails = newGroupDetails;
}
_checkSubRoom() {
const {
userUuid: localUuid
} = _configs.EduClassroomConfig.shared.sessionInfo;
let lastGroupUuid = '';
for (const [groupUuid, group] of this.groupDetails.entries()) {
const local = group.users.find(({
userUuid,
notJoined
}) => userUuid === localUuid && !notJoined);
if (local) {
this.logger.info('found user has joined sub room', groupUuid);
lastGroupUuid = groupUuid;
break;
}
}
if (lastGroupUuid) {
if (this._currentGroupUuid && lastGroupUuid !== this._currentGroupUuid) {
this.logger.info(`user move into group ${lastGroupUuid}, from group ${this._currentGroupUuid}`);
this._operationQueue.push({
fromGroupUuid: this._currentGroupUuid,
toGroupUuid: lastGroupUuid,
type: _type2.OperationType.Move
});
} else if (!this._currentGroupUuid) {
this.logger.info(`user join group ${lastGroupUuid}`);
this._operationQueue.push({
toGroupUuid: lastGroupUuid,
type: _type2.OperationType.Join
});
}
} else {
if (this._currentGroupUuid) {
this.logger.info(`user leave group ${this._currentGroupUuid}`);
this._operationQueue.push({
fromGroupUuid: this._currentGroupUuid,
type: _type2.OperationType.Leave
});
}
}
setTimeout(this._run);
}
/**
* 新建小组
* @param groupDetail 分组配置
**/
/** @en
* Creates a group
* @param groupDetail the grouping options
*/
async addGroups(groupDetails, inProgress = true) {
const roomUuid = _configs.EduClassroomConfig.shared.sessionInfo.roomUuid;
await this.api.addGroup(roomUuid, {
groups: groupDetails,
inProgress: inProgress
});
}
/**
* 移除小组
* @param groups 小组 ID 列表
**/
/** @en
* Removes groups
* @param groups A list of group IDs
*/
async removeGroups(groups) {
const roomUuid = _configs.EduClassroomConfig.shared.sessionInfo.roomUuid;
await this.api.removeGroup(roomUuid, {
removeGroupUuids: groups
});
}
/**
* 更新分组配置
* @param groups 分组配置数组
**/
/** @en
* Updates the grouping options
* @param groups An array of the grouping options
*/
async updateGroupInfo(groups) {
const roomUuid = _configs.EduClassroomConfig.shared.sessionInfo.roomUuid;
await this.api.updateGroupInfo(roomUuid, {
groups
});
}
/**
* 开启分组讨论
* @param groupDetails 分组配置数组
**/
/** @en
* Starts the breakout session
* @param groupDetails An array of the grouping options
*/
async startGroup(groupDetails, syncBoardScenes) {
const roomUuid = _configs.EduClassroomConfig.shared.sessionInfo.roomUuid;
await this.api.updateGroupState(roomUuid, {
groups: groupDetails,
inProgress: true,
syncBoardScenes
}, _type2.GroupState.OPEN);
}
/**
* 结束分组讨论
**/
/** @en
* Stops the breakout session
*/
async stopGroup() {
const roomUuid = _configs.EduClassroomConfig.shared.sessionInfo.roomUuid;
await this.api.updateGroupState(roomUuid, {
groups: []
}, _type2.GroupState.CLOSE);
}
/**
* 更新小组成员列表
* @param patches 更新配置
* @param sendInvitation 是否发送邀请
**/
/** @en
* Updates the grouping options
* @param patches The update options
* @param sendInvitation Whether to send an invitation
*/
async updateGroupUsers(patches, sendInvitation = false) {
const roomUuid = _configs.EduClassroomConfig.shared.sessionInfo.roomUuid;
await this.api.updateGroupUsers(roomUuid, {
groups: patches,
inProgress: sendInvitation
});
if (sendInvitation) {
this._inviting = true;
}
}
/**
* 将用户从小组中移除
* @param fromGroupUuid 组 ID
* @param users 用户 ID 列表
**/
/** @en
* Removes users from a group
* @param fromGroupUuid The group ID
* @param users A list of user IDs
*
*/
async removeGroupUsers(fromGroupUuid, users) {
const roomUuid = _configs.EduClassroomConfig.shared.sessionInfo.roomUuid;
const fromGroup = {
groupUuid: fromGroupUuid,
removeUsers: users
};
await this.api.updateGroupUsers(roomUuid, {
groups: [fromGroup],
inProgress: false
});
}
/**
*
* 将用户从某小组移入另一小组
* @param fromGroupUuid 原组 ID
* @param toGroupUuid 目标组 ID
* @param users 用户 ID 列表
**/
/** @en
* Moves users from a group to another group
* @param fromGroupUuid The ID of the group from which the users are
* @param toGroupUuid The ID of the group to which the users are moved
* @param users A list of user IDs
*/
async moveUsersToGroup(fromGroupUuid, toGroupUuid, users) {
const roomUuid = _configs.EduClassroomConfig.shared.sessionInfo.roomUuid;
const fromGroup = {
groupUuid: fromGroupUuid,
removeUsers: users
};
const toGroup = {
groupUuid: toGroupUuid,
addUsers: users
};
const groups = [fromGroup, toGroup];
await this.api.updateGroupUsers(roomUuid, {
groups,
inProgress: false
});
}
/**
*
* 接受加入小组的邀请
* @param groupUuid 组 ID
*
**/
/** @en
* Accepts the invitation of joining a group
* @param groupUuid The group ID
*/
async acceptGroupInvite(groupUuid) {
const roomUuid = _configs.EduClassroomConfig.shared.sessionInfo.roomUuid;
await this.api.acceptGroupInvite(roomUuid, groupUuid, this._currentGroupUuid ? {
leaveGroupUuids: [this._currentGroupUuid]
} : undefined);
}
/**
*
* 拒绝加入小组的邀请
* @param groupUuid 组 ID
**/
/** @en
* Rejects the invitation of joining a group
* @param groupUuid The group ID
*
*/
async rejectGroupInvite(groupUuid) {
const roomUuid = _configs.EduClassroomConfig.shared.sessionInfo.roomUuid;
await this.api.rejectGroupInvite(roomUuid, groupUuid);
}
/**
*
* 进入子房间
* @param groupUuid 组 ID
**/
/** @en
* Joins a group
* @param groupUuid The group ID
*/
joinSubRoom(groupUuid) {
this._currentGroupUuid = groupUuid;
_eventCenter.EduEventCenter.shared.emitClasroomEvents(_type.AgoraEduClassroomEvent.JoinSubRoom);
}
/**
*
* 用户主动从某房间移动至另一房间
* @param fromGroupUuid 原组 ID
* @param toGroupUuid 目标组 ID
*
**/
/** @en
* A user moves from a group to another group
* @param fromGroupUuid The ID of the group from which the user is
* @param toGroupUuid The ID of the group to which the user moves
*/
moveIntoSubRoom(fromGroupUuid, toGroupUuid) {
this._currentGroupUuid = toGroupUuid;
_eventCenter.EduEventCenter.shared.emitClasroomEvents(_type.AgoraEduClassroomEvent.MoveToOtherGroup, {
fromGroupUuid,
toGroupUuid
});
}
/**
* 离开小组
**/
/** @en
* Leaves the group
*/
leaveSubRoom() {
if (this._currentGroupUuid) {
this._currentGroupUuid = undefined;
_eventCenter.EduEventCenter.shared.emitClasroomEvents(_type.AgoraEduClassroomEvent.LeaveSubRoom);
}
}
/**
*
* 发送全体消息
* @param messageText 消息
*
**/
/** @en
* Sends a broadcast message
* @param messageText The message text
*/
broadcastMessage(messageText) {
const roomUuid = _configs.EduClassroomConfig.shared.sessionInfo.roomUuid;
try {
this.api.broadcastHxChatMessage(roomUuid, {
range: _type2.BroadcastMessageRange.All,
type: _type2.BroadcastMessageType.Text,
msg: messageText
});
} catch (e) {
_error.EduErrorCenter.shared.handleThrowableError(_error.AGEduErrorCode.EDU_ERR_GROUP_BROADCAST_FAIL, e);
}
}
/**
* 执行队列任务
* @returns
*/
async _run() {
const operation = this._operationQueue.pop();
if (!operation) {
return;
}
this.logger.info(`handle group operation`, (0, _mobx.toJS)(operation));
switch (operation.type) {
case _type2.OperationType.Join:
this.joinSubRoom(operation.toGroupUuid);
break;
case _type2.OperationType.Leave:
this.leaveSubRoom();
break;
case _type2.OperationType.Move:
this.moveIntoSubRoom(operation.fromGroupUuid, operation.toGroupUuid);
break;
}
}
/**
* @internal
* @deprecated
*
* 是否发送邀请
**/
/** @en
* @internal
* @deprecated
*
* Whether to send an invitation
*/
get inviting() {
return this._inviting;
}
/**
* 当前所在小组
*
**/
/** @en
* The current group
*/
get currentSubRoom() {
return this._currentGroupUuid;
}
/**
*
* 用户所在组 ID 映射关系
**/
/** @en
* The mapping relation between the group ID and the user ID
*/
get groupUuidByUserUuid() {
const map = new Map();
this.groupDetails.forEach((group, groupUuid) => {
group.users.forEach(({
userUuid,
notJoined
}) => {
if (!notJoined) {
map.set(userUuid, groupUuid);
}
});
});
return map;
}
/**
*
* 返回 userUuid 组成的 map 数据
**/
/** @en
* The map data by userUuid
*/
get userByUuid() {
const map = new Map();
this.groupDetails.forEach(group => {
group.users.forEach(user => {
map.set(user.userUuid, user);
});
});
return map;
}
//others
_addEventHandlers(scene) {
scene.on(_agoraRteSdk.AgoraRteEventType.RoomPropertyUpdated, this._handleRoomPropertiesChange);
}
_removeEventHandlers(scene) {
scene.off(_agoraRteSdk.AgoraRteEventType.RoomPropertyUpdated, this._handleRoomPropertiesChange);
}
/**
* @internal
*/
/** @en
* @internal
*/
onInstall() {
this._disposers.push((0, _mobx.computed)(() => this.classroomStore.connectionStore.mainRoomScene).observe(({
newValue,
oldValue
}) => {
if (oldValue) {
this._removeEventHandlers(oldValue);
}
if (newValue) {
//bind events
this._addEventHandlers(newValue);
}
}));
}
/**
* @internal
*/
/** @en
* @internal
*/
onDestroy() {
this._disposers.forEach(d => d());
this._disposers = [];
}
}, _GroupStore.MAX_GROUP_COUNT = 20, _GroupStore.MIN_GROUP_COUNT = 2, _GroupStore.MAX_PER_GROUP_PERSON = 15, _GroupStore.CMD_PROCESS_PREFIX = 'groups-', _GroupStore), _descriptor = _applyDecoratedDescriptor(_class2.prototype, "_operationQueue", [_mobx.observable], {
configurable: true,
enumerable: true,
writable: true,
initializer: function () {
return [];
}
}), _descriptor2 = _applyDecoratedDescriptor(_class2.prototype, "state", [_mobx.observable], {
configurable: true,
enumerable: true,
writable: true,
initializer: function () {
return _type2.GroupState.CLOSE;
}
}), _descriptor3 = _applyDecoratedDescriptor(_class2.prototype, "groupDetails", [_mobx.observable], {
configurable: true,
enumerable: true,
writable: true,
initializer: function () {
return new Map();
}
}), _applyDecoratedDescriptor(_class2.prototype, "_handleRoomPropertiesChange", [_dec2], Object.getOwnPropertyDescriptor(_class2.prototype, "_handleRoomPropertiesChange"), _class2.prototype), _applyDecoratedDescriptor(_class2.prototype, "_setDetails", [_dec3], Object.getOwnPropertyDescriptor(_class2.prototype, "_setDetails"), _class2.prototype), _applyDecoratedDescriptor(_class2.prototype, "addGroups", [_agoraRteSdk.bound], Object.getOwnPropertyDescriptor(_class2.prototype, "addGroups"), _class2.prototype), _applyDecoratedDescriptor(_class2.prototype, "removeGroups", [_agoraRteSdk.bound], Object.getOwnPropertyDescriptor(_class2.prototype, "removeGroups"), _class2.prototype), _applyDecoratedDescriptor(_class2.prototype, "updateGroupInfo", [_agoraRteSdk.bound], Object.getOwnPropertyDescriptor(_class2.prototype, "updateGroupInfo"), _class2.prototype), _applyDecoratedDescriptor(_class2.prototype, "startGroup", [_agoraRteSdk.bound], Object.getOwnPropertyDescriptor(_class2.prototype, "startGroup"), _class2.prototype), _applyDecoratedDescriptor(_class2.prototype, "stopGroup", [_agoraRteSdk.bound], Object.getOwnPropertyDescriptor(_class2.prototype, "stopGroup"), _class2.prototype), _applyDecoratedDescriptor(_class2.prototype, "updateGroupUsers", [_agoraRteSdk.bound], Object.getOwnPropertyDescriptor(_class2.prototype, "updateGroupUsers"), _class2.prototype), _applyDecoratedDescriptor(_class2.prototype, "removeGroupUsers", [_agoraRteSdk.bound], Object.getOwnPropertyDescriptor(_class2.prototype, "removeGroupUsers"), _class2.prototype), _applyDecoratedDescriptor(_class2.prototype, "moveUsersToGroup", [_agoraRteSdk.bound], Object.getOwnPropertyDescriptor(_class2.prototype, "moveUsersToGroup"), _class2.prototype), _applyDecoratedDescriptor(_class2.prototype, "acceptGroupInvite", [_agoraRteSdk.bound], Object.getOwnPropertyDescriptor(_class2.prototype, "acceptGroupInvite"), _class2.prototype), _applyDecoratedDescriptor(_class2.prototype, "rejectGroupInvite", [_agoraRteSdk.bound], Object.getOwnPropertyDescriptor(_class2.prototype, "rejectGroupInvite"), _class2.prototype), _applyDecoratedDescriptor(_class2.prototype, "joinSubRoom", [_agoraRteSdk.bound], Object.getOwnPropertyDescriptor(_class2.prototype, "joinSubRoom"), _class2.prototype), _applyDecoratedDescriptor(_class2.prototype, "moveIntoSubRoom", [_agoraRteSdk.bound], Object.getOwnPropertyDescriptor(_class2.prototype, "moveIntoSubRoom"), _class2.prototype), _applyDecoratedDescriptor(_class2.prototype, "leaveSubRoom", [_agoraRteSdk.bound], Object.getOwnPropertyDescriptor(_class2.prototype, "leaveSubRoom"), _class2.prototype), _applyDecoratedDescriptor(_class2.prototype, "broadcastMessage", [_agoraRteSdk.bound], Object.getOwnPropertyDescriptor(_class2.prototype, "broadcastMessage"), _class2.prototype), _applyDecoratedDescriptor(_class2.prototype, "_run", [_dec4], Object.getOwnPropertyDescriptor(_class2.prototype, "_run"), _class2.prototype), _applyDecoratedDescriptor(_class2.prototype, "groupUuidByUserUuid", [_mobx.computed], Object.getOwnPropertyDescriptor(_class2.prototype, "groupUuidByUserUuid"), _class2.prototype), _applyDecoratedDescriptor(_class2.prototype, "userByUuid", [_mobx.computed], Object.getOwnPropertyDescriptor(_class2.prototype, "userByUuid"), _class2.prototype), _class2)) || _class);