UNPKG

agora-edu-core

Version:

Core APIs for building an online classroom

420 lines (408 loc) 16 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.CloudDriveStore = 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 _mobx = require("mobx"); var _index = require("../../../../configs/index"); var _error = require("../../../../utils/error"); var _type = require("./type"); var _base = require("../base"); var _utils = require("./utils"); var _axios = _interopRequireDefault(require("axios")); var _struct = require("./struct"); var _agoraRteSdk = require("agora-rte-sdk"); var _dec, _dec2, _dec3, _dec4, _dec5, _class, _descriptor, _descriptor2; function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; } function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; } function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; } function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; } function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; } function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } 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."); } /** * `CloudDriveStore` 类提供云盘相关能力。 */ /** @en * The `CloudDriveStore` class provides abilities related the cloud drive. */ let CloudDriveStore = exports.CloudDriveStore = (_dec = _mobx.action.bound, _dec2 = _mobx.action.bound, _dec3 = _mobx.action.bound, _dec4 = _mobx.action.bound, _dec5 = _mobx.action.bound, _class = class CloudDriveStore extends _base.EduStoreBase { constructor() { super(...arguments); /** * 云盘个人资源文件列表 */ /** @en * Personal resources */ _initializerDefineProperty(this, "personalResources", _descriptor, this); /** * 云盘资源上传进度 */ /** @en * Progresses of resources */ _initializerDefineProperty(this, "uploadProgress", _descriptor2, this); this._checkpoints = new Map(); } /** * 取消上传资源 * * @param resourceUuid 资源 ID **/ /** @en * Cancels uploading the file * * @param resourceUuid The resource ID */ async cancelUpload(resourceUuid) { const checkpoint = this._checkpoints.get(resourceUuid); if (checkpoint) { switch (checkpoint.type) { case _type.UploadType.COMMON_XHR: const { checkPoint: cancelTokenSource } = checkpoint; if (cancelTokenSource) { cancelTokenSource.cancel('Cancled'); this.uploadProgress.delete(resourceUuid); } break; } } else { _error.EduErrorCenter.shared.handleThrowableError(_error.AGEduErrorCode.EDU_ERR_UPLOAD_FAILED_NO_CHECKPOINT, new Error(`get upload checkpoint failed when cancel upload`)); } } /** * 重新上传资源 * * @param resourceUuid 资源 ID **/ /** @en * Retries uploading the file * @param resourceUuid The resource ID */ retryUpload(resourceUuid) { const checkpoint = this._checkpoints.get(resourceUuid); if (checkpoint) { const { file, ext, contentType, conversion } = checkpoint; this.uploadPersonalResource(file, resourceUuid, ext, contentType, conversion); } else { _error.EduErrorCenter.shared.handleThrowableError(_error.AGEduErrorCode.EDU_ERR_UPLOAD_FAILED_NO_CHECKPOINT, new Error(`get upload checkpoint failed when retry upload`)); } } /** * 获取个人云盘资源 * @param options 分页参数 * @returns 云盘资源分页信息 **/ /** @en * Gets all personal resources * @param options The paging option * @returns Cloud disk resource page information */ async fetchPersonalResources(options) { let data = { list: [], total: 0 }; try { const { userUuid } = _index.EduClassroomConfig.shared.sessionInfo; data = await this.classroomStore.api.fetchPersonalResources(userUuid, { pageSize: options.pageSize, pageNo: options.pageNo, resourceName: options.resourceName }); } catch (e) { return _error.EduErrorCenter.shared.handleThrowableError(_error.AGEduErrorCode.EDU_ERR_CLOUD_FETCH_PERSONAL_RESOURCE_FAIL, e); } return data; } _initProgress(progress) { this.uploadProgress.set(progress.resourceUuid, progress); } /** * @internal */ /** @en * @internal */ async _updateProgress(resourceUuid, progressValue, status) { const progress = this.uploadProgress.get(resourceUuid); if (progress) { if (progressValue) { progress.progress = progressValue; if (progressValue === 1) { progress.status = _type.CloudDriveResourceUploadStatus.Success; } } if (status) progress.status = status; } } async _putFile(file, progressUuid, ossConfig) { const { preSignedUrl, fileUrl } = ossConfig; const cancelTokenSource = _axios.default.CancelToken.source(); try { await _axios.default.put(preSignedUrl, file, { cancelToken: cancelTokenSource.token, headers: { 'Content-Type': ossConfig.contentType }, onUploadProgress: progressEvent => { const checkpoint = this._checkpoints.get(progressUuid); if (!checkpoint.checkPoint) this._checkpoints.set(progressUuid, _objectSpread(_objectSpread({}, checkpoint), {}, { checkPoint: cancelTokenSource })); const percentCompleted = progressEvent.loaded / progressEvent.total; (0, _mobx.runInAction)(() => { this._updateProgress(progressUuid, percentCompleted); }); } }); this._checkpoints.delete(progressUuid); } catch (e) { if (e.message === 'Cancled') { this._updateProgress(progressUuid, undefined, _type.CloudDriveResourceUploadStatus.Canceled); return ''; } else { this._updateProgress(progressUuid, undefined, _type.CloudDriveResourceUploadStatus.Failed); _error.EduErrorCenter.shared.handleThrowableError(_error.AGEduErrorCode.EDU_ERR_UPLOAD_AWS_FAIL, new Error(`upload to oss error`)); } } return fileUrl; } /** * 将已上传的资源文件映射为云盘内的一个文件 * @param resourceUuid 资源 UUID * @param resourceInfo 资源信息 */ /** @en * Create a record that maps to the uploaded resource file * @param resourceUuid Resource UUID * @param resourceInfo Resource Info */ async addPersonalResource(resourceUuid, resourceInfo) { const { sessionInfo } = _index.EduClassroomConfig.shared; const { userUuid } = sessionInfo; return await this.classroomStore.api.addCloudDriveFile(resourceUuid, userUuid, resourceInfo); } /** * 更新云盘文件信息 * @param resourceUuid * @param resourceInfo * @returns */ /** @en * Updates the cloud drive file info * @param resourceUuid * @param resourceInfo * @returns */ async updatePersonalResource(resourceUuid, resourceInfo) { const { sessionInfo } = _index.EduClassroomConfig.shared; const { userUuid } = sessionInfo; return await this.classroomStore.api.updateCloudDriveFile(resourceUuid, userUuid, resourceInfo); } /** * 上传资源到云盘,上传后需要调用 addPersonalResource 方法创建一条资源对应的课件记录即可在云盘中使用。 * @param file 资源文件对象 * @param progressUuid 上传 UUID * @param ext 资源扩展名 * @param contentType static: 静态, dynamic:动态 * @param conversion 转换选项 * @returns 上传成功后的文件信息 **/ /** @en * Uploads a file to personal resources, addPersonalResource is required to call after uploading, which creates a record that will show in cloud drive. * @param file The file * @param progressUuid Progress UUID * @param ext Extension name of the resource * @param contentType static or dynamic * @param conversion conversion options * @returns Information about the uploaded file */ async uploadPersonalResource(file, progressUuid, ext, contentType, conversion) { try { const { sessionInfo: { userUuid } } = _index.EduClassroomConfig.shared; const { name: resourceName, size } = file; // step 1. fetch sts token for futher operations const uploadData = { resourceUuid: progressUuid, userUuid, resourceName, contentType, ext, size, updateTime: 0 }; // presignedUrls body const progress = new _struct.CloudDriveUploadingProgress(uploadData); this._initProgress(progress); if (!this._checkpoints.get(progressUuid)) { this._checkpoints.set(progressUuid, { type: _type.UploadType.COMMON_XHR, file, contentType, ext, conversion }); } // step 1. fetch sts token for futher operations const data = await this.classroomStore.api.fetchFileUploadSts({ userUuid, resourceName, contentType, ext, size, conversion }); // step 2. begin upload by vendor // aws const { accessKeyId, accessKeySecret, bucketName, ossEndpoint, securityToken, ossKey, resourceUuid, //only available for aws for now preSignedUrl, url: fileUrl } = data[0]; const url = await this._putFile(file, progressUuid, { accessKeyId, accessKeySecret, bucketName, ossEndpoint, securityToken, ossKey, preSignedUrl, fileUrl, contentType }); // step 3. done uploading, binding if (url) { await this.classroomStore.api.addCloudDriveFile(resourceUuid, userUuid, { resourceName, ext, size: file.size, url, conversion }); } return url ? { ext, resourceName, resourceUuid, url } : {}; } catch (e) { _error.EduErrorCenter.shared.handleThrowableError(_error.AGEduErrorCode.EDU_ERR_UPLOAD_FAIL, e); } } /** * 移除个人资源 * @param resourceUuids 资源 ID **/ /** @en * Removes files from personal resources * @param resourceUuids The resource IDs */ async removePersonalResources(resourceUuids) { try { const { sessionInfo } = _index.EduClassroomConfig.shared; const { userUuid } = sessionInfo; await this.classroomStore.api.removeMaterials(resourceUuids, userUuid); for (const uuid of resourceUuids) { this.personalResources.delete(uuid); } } catch (e) { return _error.EduErrorCenter.shared.handleThrowableError(_error.AGEduErrorCode.EDU_ERR_CLOUD_REMOVE_PERSONAL_RESOURCE_FAIL, e); } } /** * 计算资源文件 UUID * @param resource * @returns 资源文件 UUID */ /** @en * Figure out a UUID for the resource file * @param resource * @returns Resource file UUID */ calcResourceUuid(resource) { return _utils.CloudDriveUtils.calcResourceUuid(resource); } /** * @internal */ /** @en * @internal */ onInstall() {} /** * @internal */ /** @en * @internal */ onDestroy() {} }, _descriptor = _applyDecoratedDescriptor(_class.prototype, "personalResources", [_mobx.observable], { configurable: true, enumerable: true, writable: true, initializer: function () { return new Map(); } }), _descriptor2 = _applyDecoratedDescriptor(_class.prototype, "uploadProgress", [_mobx.observable], { configurable: true, enumerable: true, writable: true, initializer: function () { return new Map(); } }), _applyDecoratedDescriptor(_class.prototype, "cancelUpload", [_dec], Object.getOwnPropertyDescriptor(_class.prototype, "cancelUpload"), _class.prototype), _applyDecoratedDescriptor(_class.prototype, "retryUpload", [_dec2], Object.getOwnPropertyDescriptor(_class.prototype, "retryUpload"), _class.prototype), _applyDecoratedDescriptor(_class.prototype, "fetchPersonalResources", [_dec3], Object.getOwnPropertyDescriptor(_class.prototype, "fetchPersonalResources"), _class.prototype), _applyDecoratedDescriptor(_class.prototype, "_initProgress", [_dec4], Object.getOwnPropertyDescriptor(_class.prototype, "_initProgress"), _class.prototype), _applyDecoratedDescriptor(_class.prototype, "_updateProgress", [_dec5], Object.getOwnPropertyDescriptor(_class.prototype, "_updateProgress"), _class.prototype), _applyDecoratedDescriptor(_class.prototype, "addPersonalResource", [_agoraRteSdk.bound], Object.getOwnPropertyDescriptor(_class.prototype, "addPersonalResource"), _class.prototype), _applyDecoratedDescriptor(_class.prototype, "updatePersonalResource", [_agoraRteSdk.bound], Object.getOwnPropertyDescriptor(_class.prototype, "updatePersonalResource"), _class.prototype), _applyDecoratedDescriptor(_class.prototype, "uploadPersonalResource", [_agoraRteSdk.bound], Object.getOwnPropertyDescriptor(_class.prototype, "uploadPersonalResource"), _class.prototype), _applyDecoratedDescriptor(_class.prototype, "removePersonalResources", [_agoraRteSdk.bound], Object.getOwnPropertyDescriptor(_class.prototype, "removePersonalResources"), _class.prototype), _applyDecoratedDescriptor(_class.prototype, "calcResourceUuid", [_agoraRteSdk.bound], Object.getOwnPropertyDescriptor(_class.prototype, "calcResourceUuid"), _class.prototype), _class);