WhiteBoardApe.js 15.7 KB
// //////////////////////////////////////////////////////////////////////////////
//
//  Copyright (C) 2016-present  All Rights Reserved.
//  Licensed under the Apache License, Version 2.0 (the "License");
//  http://www.apache.org/licenses/LICENSE-2.0
//
//  Github Home: https://github.com/AlexWang1987
//  Author: AlexWang
//  Date: 2016-08-26 17:36:20
//  QQ Email: 1669499355@qq.com
//  Last Modified time: 2016-09-21 14:06:12
//  Description: LiveClass-WhiteBoardApe
//
// //////////////////////////////////////////////////////////////////////////////

import Ape from './Ape';
import ApeConsts from './ApeConsts';
import pdu from 'pdus';
import Loger from 'Loger';
import MessageTypes from 'MessageTypes';
import { Zlib } from 'zlibjs/bin/zlib.min';
import UTF8 from 'utf-8';
import GlobalConfig from 'GlobalConfig';
import EngineUtils from 'EngineUtils';

let loger = Loger.getLoger('WhiteBoardApe');

let itemIdx = 0;//table插入新数据的计数id,目前用时间戳
const TYPE_BIGHT = 0;//任意线段
const TYPE_LINE = 1;//直线
const TYPE_RECT = 2;//矩形
const TYPE_CIRCLE = 3;//圆形
const TYPE_TEXT = 4;//文本

class WhiteBoardApe extends Ape {
    constructor() {
        super(
            ApeConsts.WHITEBOARD_SESSION_ID,
            ApeConsts.WHITEBOARD_SESSION_NAME,
            ApeConsts.WHITEBOARD_SESSION_TAG
        );
        // properties
        this.annoInfos = {};//储存所有的标注数据
        this.insertHistory = [];//添加的白板记录,用于撤回操作
        // 白板延迟
        // this._apeDelayed = true;

        //Ape Models
        this.registerKey(this._session_id, this._session_name, this._session_tag, new ArrayBuffer);
        this.registerObj(pdu.RCPDU_REG_REGISTER_TABLE, ApeConsts.WHITEBOARD_OBJ_TABLE_ID,
            ApeConsts.WHITEBOARD_OBJ_TABLE_NAME, ApeConsts.WHITEBOARD_OBJ_TABLE_TAG, 0, new ArrayBuffer);

        // ape listeners
        this.on(pdu.RCPDU_SESSION_JOIN_RESPONSE, this._joinSessionHandler.bind(this));
        //this.on(pdu.RCPDU_CONFERENCE_SEND_DATA_REQUEST, this.whiteboardMsgComingHandler.bind(this));//这个是课堂消息类型,flash里在使用这里不再使用,各个模块的消息由模块自己来处理
    }

    _joinSessionHandler(_data) {
        loger.log("RCPDU_SESSION_JOIN_RESPONSE");
        this.insertHistory = [];
    }

    /////////////发送数据操作//////////////////////////////////////////////////////
    // 添加标注,发送信息
    sendInsetAnnotaion(_param) {
        if (_param == null || EngineUtils.isEmptyObject(_param)) {
            loger.log('sendInsetAnnotaion失败,参数错误');
            this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_APE_INTERFACE_PARAM_WRONG);
            return;
        }

        itemIdx = EngineUtils.creatSoleNumberFromTimestamp();
        let whiteBoardModelPdu = this.packPdu(_param, itemIdx);
        if (whiteBoardModelPdu == null) {
            loger.log('sendInsetAnnotaion失败,参数错误');
            this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_APE_INTERFACE_PARAM_WRONG);
            return;
        }
        //console.log(whiteBoardModelPdu);

        //储存记录,用于返回上一步操作
        this.insertHistory.push(whiteBoardModelPdu);

        let tableItemPdu = new pdu['RCRegistryTableItemPdu'];
        tableItemPdu.itemIdx = itemIdx;//直接用时间戳作为id
        tableItemPdu.registerObjId = ApeConsts.WHITEBOARD_OBJ_TABLE_ID;
        tableItemPdu.owner = 0;//收到flash的是这个值,不清楚先写固定
        tableItemPdu.itemData = whiteBoardModelPdu.toArrayBuffer();

        //insert
        let tableInsertItemPdu = new pdu['RCRegistryTableInsertItemPdu'];
        //optional RCPduType_E type = 1 [default = RCPDU_REG_TABLE_UPDATE_PDU];
        //repeated RCRegistryTableItemPdu items = 2;
        tableInsertItemPdu.type = pdu.RCPDU_REG_TABLE_INSERT_PDU;//
        tableInsertItemPdu.items.push(tableItemPdu);

        let updateObjPdu = new pdu['RCRegistryUpdateObjPdu'];
        updateObjPdu.objId = ApeConsts.WHITEBOARD_OBJ_TABLE_ID;
        updateObjPdu.subType = tableInsertItemPdu.type;
        updateObjPdu.userData = tableInsertItemPdu.toArrayBuffer();

        //同步
        let adapterItemPdu = new pdu['RCAdapterItemPdu'];
        adapterItemPdu.type = pdu.RCPDU_REG_UPDATE_OBJ;
        adapterItemPdu.itemData = updateObjPdu.toArrayBuffer();

        let adapterPdu = new pdu['RCAdapterPdu'];
        adapterPdu.type = pdu.RCPDU_REG_ADAPTER;
        adapterPdu.item.push(adapterItemPdu);

        loger.log("添加白板数据=====itemIdx=" + tableItemPdu.itemIdx);
        this.sendUniform(adapterPdu, true);
    }

    //撤销上一步
    sendGotoPrev() {
        loger.log("白板返回上一步");
        if (this.insertHistory == null || this.insertHistory.length < 1) {
            loger.warn("无法继续上一步操作,已经没有可以撤销的数据");
            return;
        }
        //loger.log(this.insertHistory);
        this.sendDeleteAnnotaion(this.insertHistory.pop());
    }

    //删除当前页码的所有标注
    sendDeleteCurPageAnnotation(_param) {
        for (let key in this.annoInfos) {
            let item = this.annoInfos[key];
            if (item && item.parentId == GlobalConfig.activeDocId && item.curPageNo == GlobalConfig.activeDocCurPage) {
                loger.log("sendDeleteCurPageAnnotation 删除当前页面上的标注", key);
                this.sendDeleteAnnotaion({"itemIdx": key});
            }
        }
    }

    //删除所有标注
    sendDeleteAllAnnotation(_param) {
        for (let key in this.annoInfos) {
            this.sendDeleteAnnotaion({"itemIdx": key});
        }
    }

    //删除标注,发送信息
    sendDeleteAnnotaion(_param) {
        if (_param == null) {
            loger.warn("要删除的数据不存在");
            return;
        }
        //{"itemIdx":itemIdx}
        let tableDeleteItemPdu = new pdu['RCRegistryTableDeleteItemPdu'];
        //optional RCPduType_E type = 1 [default = RCPDU_REG_TABLE_DELETE_PDU];
        // repeated uint32 item_idx = 2;
        tableDeleteItemPdu.type = pdu.RCPDU_REG_TABLE_DELETE_PDU;//
        tableDeleteItemPdu.itemIdx = parseInt(_param.itemIdx);//这里需要设置要删除的数据的itemIdx,每条数据的这个id都不一样

        let updateObjPdu = new pdu['RCRegistryUpdateObjPdu'];
        updateObjPdu.objId = ApeConsts.WHITEBOARD_OBJ_TABLE_ID;
        updateObjPdu.subType = tableDeleteItemPdu.type;
        updateObjPdu.userData = tableDeleteItemPdu.toArrayBuffer();

        //同步
        let adapterItemPdu = new pdu['RCAdapterItemPdu'];
        adapterItemPdu.type = pdu.RCPDU_REG_UPDATE_OBJ;
        adapterItemPdu.itemData = updateObjPdu.toArrayBuffer();

        let adapterPdu = new pdu['RCAdapterPdu'];
        adapterPdu.type = pdu.RCPDU_REG_ADAPTER;
        adapterPdu.item.push(adapterItemPdu);

        loger.log("白板发送删除数据=============" + tableDeleteItemPdu.itemIdx);
        this.sendUniform(adapterPdu, true);
    }


    //更新标注
    sendUpdaterAnnotaion(_param) {
        if (_param == null || EngineUtils.isEmptyObject(_param)) {
            loger.log('sendUpdaterAnnotaion失败,参数错误');
            this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_APE_INTERFACE_PARAM_WRONG);
            return;
        }
        itemIdx = _param.itemIdx;
        let whiteBoardModelPdu = this.packPdu(_param, itemIdx);
        //console.log(whiteBoardModelPdu);

        if (whiteBoardModelPdu == null) {
            loger.log('sendInsetAnnotaion失败,参数错误');
            this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_APE_INTERFACE_PARAM_WRONG);
            return;
        }

        let tableItemPdu = new pdu['RCRegistryTableItemPdu'];
        tableItemPdu.itemIdx = itemIdx;
        tableItemPdu.owner = 0;//收到flash的是这个值,不清楚先写固定
        tableItemPdu.registerObjId = ApeConsts.WHITEBOARD_OBJ_TABLE_ID;
        tableItemPdu.itemData = whiteBoardModelPdu.toArrayBuffer();


        //updater
        let whiteBoardUpdateItem = new pdu['RCRegistryTableUpdateItemPdu'];
        //optional RCPduType_E type = 1 [default = RCPDU_REG_TABLE_UPDATE_PDU];
        //repeated RCRegistryTableItemPdu items = 2;
        whiteBoardUpdateItem.type = pdu.RCPDU_REG_TABLE_UPDATE_PDU;//
        whiteBoardUpdateItem.items.push(tableItemPdu);


        let updateObjPdu = new pdu['RCRegistryUpdateObjPdu'];
        updateObjPdu.objId = ApeConsts.WHITEBOARD_OBJ_TABLE_ID;
        updateObjPdu.subType = whiteBoardUpdateItem.type;
        updateObjPdu.userData = whiteBoardUpdateItem.toArrayBuffer();

        //同步
        let adapterItemPdu = new pdu['RCAdapterItemPdu'];
        adapterItemPdu.type = pdu.RCPDU_REG_UPDATE_OBJ;
        adapterItemPdu.itemData = updateObjPdu.toArrayBuffer();

        let adapterPdu = new pdu['RCAdapterPdu'];
        adapterPdu.type = pdu.RCPDU_REG_ADAPTER;
        adapterPdu.item.push(adapterItemPdu);

        loger.log("白板发送更新数据===============22");
        this.sendUniform(adapterPdu, true);
    }

    /////收到消息处理/////////////////////////////////////////////////////////////////////////////////
    tableInsertHandler(owner, itemIdx, itemData) {
        let whiteBoardModel = this.unPackPdu(owner, itemIdx, itemData);
        loger.log('tableInsertHandler');
        loger.log(whiteBoardModel);
        if (whiteBoardModel) {
            if (GlobalConfig.activeDocId == whiteBoardModel.parentId && GlobalConfig.activeDocCurPage == whiteBoardModel.curPageNo) {
                loger.log('WHITEBOARD_ANNOTAION_INSERT 显示到界面上', whiteBoardModel);
                //this._emit(MessageTypes.WHITEBOARD_ANNOTAION_INSERT,whiteBoardModel);
                this.insertAandShowAnnotaion(whiteBoardModel);
            }
        }
    }

    tableUpdateHandler(owner, itemIdx, itemData) {
        let whiteBoardModel = this.unPackPdu(owner, itemIdx, itemData);
        loger.log('tableUpdateHandler');
        loger.log(whiteBoardModel);
        if (whiteBoardModel && whiteBoardModel.parentId == GlobalConfig.activeDocId && whiteBoardModel.curPageNo == GlobalConfig.activeDocCurPage) {
            this.updateAandShowAnnotaion();
        }
    }

    tableDeleteHandler(object_id, tableDeleteData) {
        // console.log("白板收到数据,tableDeleteHandler  object_id="+object_id);//((18<< 16) + 1)=1179649
        loger.log('tableDeleteHandler', object_id, tableDeleteData);//["tableDeleteHandler",1179649,{"type":231,"itemIdx":[1486301768]}]
        if (tableDeleteData && tableDeleteData.itemIdx) {
            let len = tableDeleteData.itemIdx.length;
            let itemIdxs = tableDeleteData.itemIdx;
            for (let i = 0; i < len; i++) {
                if (this.annoInfos[itemIdxs[i]]) {
                    loger.log("删除白板数据:", itemIdxs[i]);
                    //this._emit(MessageTypes.WHITEBOARD_ANNOTAION_DELETE,{ "itemIdx":itemIdxs[i]});
                    delete this.annoInfos[itemIdxs[i]];
                }
            }
        }
        this.updateAandShowAnnotaion();
    }

    //文档更新,白板也要更新
    docUpdateHandler(_data) {
        loger.log("白板收到文档更新的消息docUpdateHandler");
        loger.log(_data);

        //如果切换了文档或翻页,清除之前的添加步骤记录
        if (_data.action == ApeConsts.DOC_ACTION_SWITCH_DOC || _data.action == ApeConsts.DOC_ACTION_SWITCH_PAGE) {
            this.insertHistory = [];
        }
        this.updateAandShowAnnotaion();
    }

    //删除白板数据
    docDeleteHandler(_parentId) {
        loger.log("白板收到文档删除的消息docDeleteHandler", _parentId);
        for (let key in this.annoInfos) {
            let item = this.annoInfos[key];
            if (item && item.parentId == _parentId) {
                loger.log("文档删除,白板数据也删除,itemIdx:" + key, "_parentId:", _parentId);
                this.sendDeleteAnnotaion({"itemIdx": key});
            }
        }
    }

    //增量添加标注
    insertAandShowAnnotaion(_item) {
        let annotaionItems = [_item];
        var updateObj = {
            "isFresh": false,
            "annotaionItems": annotaionItems
        };
        loger.log("WHITEBOARD_ANNOTATION_UPDATE", annotaionItems.length);
        this._emit(MessageTypes.WHITEBOARD_ANNOTATION_UPDATE, updateObj);
    }

    //整体更新并且显示标注
    updateAandShowAnnotaion() {
        let annotaionItems = [];
        for (let key in this.annoInfos) {
            let item = this.annoInfos[key];
            if (item && item.parentId == GlobalConfig.activeDocId && item.curPageNo == GlobalConfig.activeDocCurPage) {
                annotaionItems.push(item);
                loger.log("显示和文档对应的白板数据docUpdateHandler itemIdx:", item.itemIdx, "doc itemIdx:", GlobalConfig.activeDocId, "curPageNo:", GlobalConfig.activeDocCurPage);
            } else {
                //loger.log("不显示白板数据docUpdateHandler",item);
            }
        }
        var updateObj = {
            "isFresh": true,
            "annotaionItems": annotaionItems
        };
        loger.log("WHITEBOARD_ANNOTATION_UPDATE", annotaionItems.length);
        this._emit(MessageTypes.WHITEBOARD_ANNOTATION_UPDATE, updateObj);
    }

    ///////白板数据的封包和解包/////////////////////////////////////////
    packPdu(_param, _itemIdx) {
        //验证坐标点集合数组是否合法
        if (_param.pointGroup == null || _param.pointGroup.length < 1) {
            this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_APE_INTERFACE_PARAM_WRONG);
            return null;
        }
        //判断type类型,根据type设置不同的参数
        let whiteBoardModelPdu = new pdu['RCWhiteBoardDataModelPdu'];
        switch (_param.type) {
            case TYPE_BIGHT:
                break;
            case TYPE_LINE:
                break;
            case TYPE_RECT:
                break;
            case TYPE_CIRCLE:
                whiteBoardModelPdu.radius = parseInt(_param.radius);
                break;
            case TYPE_TEXT:
                whiteBoardModelPdu.fontSize = parseInt(_param.fontSize);
                whiteBoardModelPdu.fontName = _param.fontName || null;
                whiteBoardModelPdu.text = _param.text || null;
                break;
            default:
                //其它类型不做处理
                return null;
                break;
        }
        //下面4个是必须的参数
        whiteBoardModelPdu.type = _param.type;
        whiteBoardModelPdu.itemIdx = _itemIdx;
        whiteBoardModelPdu.initiator = GlobalConfig.nodeId;

        /* whiteBoardModelPdu.parentId=_param.parentId||0;
         whiteBoardModelPdu.curPage=_param.curPage||1;*/

        whiteBoardModelPdu.parentId = GlobalConfig.activeDocId;//当前激活的文档id
        whiteBoardModelPdu.curPageNo = GlobalConfig.activeDocCurPage;//当前激活的文档页码

        whiteBoardModelPdu.pointGroup = EngineUtils.arrayToJsonString(_param.pointGroup);
        whiteBoardModelPdu.color = _param.color || "#000000";

        return whiteBoardModelPdu;
    }

    unPackPdu(owner, itemIdx, itemData) {
        try {
            loger.log("白板收到数据===unPackPdu ");
            let whiteBoardModelPdu = pdu['RCWhiteBoardDataModelPdu'].decode(itemData);
            //console.log(whiteBoardModelPdu);
            //loger.log(whiteBoardModelPdu);
            let _pointGroup = EngineUtils.arrayFromJsonString(whiteBoardModelPdu.pointGroup);
            whiteBoardModelPdu.pointGroup = _pointGroup;
            this.annoInfos[itemIdx] = whiteBoardModelPdu;
            return whiteBoardModelPdu;
        } catch (err) {
            loger.log("unPackPdu Pdu解析错误,itemIdx=" + itemIdx + "  err:" + err.message);
        }
        return null;
    }

}

export default WhiteBoardApe;