MessageViewPresenter.ts 13 KB
import { ConfigManager } from "simba-config-manager";
import { DeepReadonly } from "simba-utils";
import { PlotManager, ReadonlyPlot, richNodesToCocosString, SentenceMediaContent, SentenceTextContent, SentenceType } from "../../../avg/AVG";
import { RoleType } from "../../../avg/EditorEnums";
import { Presenter } from "../../../common/classbase/PresenterBase";
import { GameTextData } from "../../../common/gameplay/gamedata/GameTextData";
import { UIManager } from "../../../common/gameplay/managers/UIManager";
import { relationLevelConfig } from "../../../config/RelationLevelConfig";
import { role } from "../../../config/Role";
import { DirectionType, GuideLocation, GuideOperationType, GuideState, PlotSceneType } from "../../Enums";
import GameDotMgr from "../../GameDotMgr";
import { GameModelManager } from "../../model/GameModelManager";
import { MessageSceneModel } from "../../model/MessageSceneModel";
import { RegPresenter } from "../PresenterCCViewFactory";
import { AlertDialogViewProps } from "../view/type/AlertDialogView";
import { MessageView, MessageViewProps, MessageViewType } from "../view/type/MessageView";
import AlertDialogViewPresenter from "./AlertDialogViewPresenter";
import { ChatListViewPresenter } from "./ChatListViewPresenter";
import GuideViewPresenter, { GuideViewParamModel } from "./GuideViewPresenter";
import { PhoneCallViewPresenter } from "./PhoneCallViewPresenter";
import PlotStopViewPresenter from "./PlotStopViewPresenter";

function getSentenceText(content: DeepReadonly<SentenceTextContent> | DeepReadonly<SentenceMediaContent>) {
    let text = ""
    switch (content.type) {
        case SentenceType.TEXT:
            text = richNodesToCocosString(content.value);
            const CHAR_LIMIT: number = 15;
            // text = '<color=#000000>亲,你说不说?</color>,<color=#000000>111</color>';
            // text = '亲,你说不说?亲,你说不说?亲,你说不说?';
            const regex = /<color=#[0-9A-Za-z]{6,6}>/g;
            let str = text.replace(regex, '');
            let textStr = str.replace(/<\/color>/g, '');
            text = textStr.length > CHAR_LIMIT ? textStr.slice(0, CHAR_LIMIT - 3) + "..." : textStr;
            break;
        case SentenceType.AUDIO:
            text = "[Voice]";
            break;
        case SentenceType.IMAGE:
            text = "[Image]";
            break;
        case SentenceType.VIDEO:
            text = "[Video]";
            break;
    }
    return text;
}

function getPlotString(plot?: ReadonlyPlot) {
    if (plot) {
        let text = "";
        let sentence = plot.sentences[0];
        if (sentence.content) {
            if (sentence.content.type === SentenceType.SELECT) {
                let select = PlotManager.getPlotSelection(plot.id);
                if (select !== undefined) {
                    let option = sentence.content.value[select];
                    if (option.content) {
                        if (option.content.type === SentenceType.EMPTY) {
                            console.error("TODO handle empty plots in message");
                        } else {
                            text = getSentenceText(option.content);
                        }
                    } else {
                        text = option.summary;
                    }
                }
            } else {
                if (sentence.content.type === SentenceType.EMPTY) {
                    console.error("TODO handle empty plots in message");
                } else {
                    text = getSentenceText(sentence.content);
                }
            }
        }
        return text;
    }
    return GameModelManager.getLanguageTxt(GameTextData.TEXT_NEW_CHAT_MSG_VALUE);
}

@RegPresenter(MessageViewType)
export default class MessageViewPresenter extends Presenter<undefined, MessageView> {
    static uuid = "MessageViewPresenter";
    private _scenesActive: { [key: number]: boolean } = {};
    private _currPlotHasMsg = false;

    private _isCheckingPhoneCall: boolean = false;
    private _viewProps: MessageViewProps;

    onOpen() {
        super.onOpen(undefined);
        this.initViewProps();
        this.checkScenesActive();
        this.setViewProps();
        this._disposable.add(GameModelManager.MessageSceneChanged.on(() => {
            if (!this._currPlotHasMsg && !this._view.isHidden && !this._isInBackground) {
                this.checkScenesActive();
                this.setViewProps();
            }
        }));
        this._disposable.add(PlotManager.PlotStartEvent.on(() => {
            if (this._currPlotHasMsg && !this._view.isHidden && !this._isInBackground) {
                this.checkScenesActive();
                this.setViewProps();
            }
        }));
        // this._disposable.add(GameModelManager.CheckMsgGuide.on(this.checkGuideItem));
        this._disposable.add(GameModelManager.ShowPlotBlocked.on(this.onShowPlotBlocked));
        this._disposable.add(GameModelManager.PlotBlockedChanged.on(this.onShowPlotBlocked));
        this._disposable.add(GameModelManager.ForceClickMsgItem.on(this.onForceClickItem));
        this._disposable.add(GameModelManager.RefreshAllStatus.on(this.onRefreshAllStatus));


        this._isCheckingPhoneCall = false;
        this.checkPhoneCall();
    }

    onForceClickItem = (id: number) => {
        console.log("MessageViewPresenter onForceClickItem id = ", id);
        if (!this._viewProps.items || 0 === this._viewProps.items.length) {
            return;
        }
        let c = id + "";
        let i = this._viewProps.items.findIndex((v) => v.key === c);
        if ((-1) !== i) {
            this.onItemClick(c);
        }
    }

    onShow() {
        super.onShow();
        this.checkScenesActive();
        this.setViewProps();
        this.checkPhoneCall();
        // this.checkGuideItem();
    }

    initViewProps() {
        this._viewProps = {
            items: [],
            onItemClick: this.onItemClick,
            PlotStopTipBtnCallback: this.PlotStopTipBtnCallback,
            isShowPlotStopTipBtn: false,
        }
    }

    async checkPhoneCall() {
        if (this._isCheckingPhoneCall) {
            return;
        }
        this._isCheckingPhoneCall = true
        if (PlotManager.getCurrentPlots()[0].plotSceneType === PlotSceneType.PhoneCall) {
            await UIManager.pushPresenter(PhoneCallViewPresenter, undefined);
        }
        this._isCheckingPhoneCall = false;
    }

    onEnterForeground() {
        super.onEnterForeground();
        this.checkScenesActive();
        this.setViewProps();
        this.checkPhoneCall();
    }

    private checkScenesActive = () => {
        this._currPlotHasMsg = false;
        this._scenesActive = GameModelManager.getMessageScenesModel().reduce((pv, v) => (pv[v.id] = this.checkSceneActive(v), pv), {});
    }

    private checkSceneActive = (model: MessageSceneModel) => {
        let ret = PlotManager.getCurrentPlots().findIndex(v => v.plotSceneType === PlotSceneType.Message && v.plotSceneTypeId === model.id) >= 0;
        if (ret) this._currPlotHasMsg = true;
        return ret;
    }

    private setViewProps() {
        let items = GameModelManager.getMessageScenesModel().map(
            v => {
                let roleConfig = ConfigManager.getConfig(role, v.config.roles[0]);
                let isMajor = roleConfig.RoleType === RoleType.Role_Major;
                let roleData = GameModelManager.getRoleData(v.config.roles[0]);
                let data = roleData!.getRoleLikeLevel();
                let nameSpr = GameModelManager.getRoleData(v.config.roles[0])!.getNameIcon();
                if (v.config.roles[0] === 3) {
                    nameSpr = "/textures/name_icon/laoda";
                }
                return {
                    key: v.id + "", icons: [GameModelManager.getRoleData(v.config.roles[0])!.getHeadIcon()],
                    title: GameModelManager.getConfigLanguageTxt(v.config.title),
                    lastMsg: getPlotString(v.lastPlot),
                    redDot: this._scenesActive[v.id],
                    isShowGrace: isMajor,
                    level: isMajor ? data.level : undefined,
                    roleId: v.config.roles[0],
                    addGraceClickCallBack: this.addGraceClickCallBack,
                    isShowAddGrace: isMajor && data.level !== data.maxLevel,
                    nameSpr: nameSpr
                }
            }
        );
        //对列表进行排序,有红点的(新对话消息)排在最前面,也就是置顶
        items.sort((a, b) => {
            if (a.redDot) {
                return -1;
            }
            if (b.redDot) {
                return 1;
            }
            return 0;
        });
        this._viewProps = { // 暂每条只有一个头像,群聊显示单独头像,以后可能群聊显示多人头像
            items: items,
            onItemClick: this.onItemClick,
            isShowPlotStopTipBtn: GameModelManager.checkIsPlotBlocked(),
            PlotStopTipBtnCallback: this.PlotStopTipBtnCallback,
        }
        this.view.setProps(this._viewProps);
    }

    PlotStopTipBtnCallback = () => {
        UIManager.pushPresenter(PlotStopViewPresenter, undefined);
    }

    addGraceClickCallBack = (roleId: number) => {
        // GameDotMgr.getInstance().dotClickUI("click_grace");
        let r = GameModelManager.getRoleData(roleId);
        if (!r || r!.getConfig().RoleType !== RoleType.Role_Major) {
            return;
        }
        let l = r.getRoleLikeLevel();
        let m: number = -1;
        let t = ConfigManager.getAllConfig(relationLevelConfig);
        for (let id in t) {
            let c = t[id];
            m = m < c.id ? c.id : m;
            //暂时修改最大等级为10
            m = 10;
        }
        if (m <= l.level) {
            UIManager.showToast(GameModelManager.getLanguageTxt(GameTextData.GAME_TEXT_GRACE_LEVEL_MAX_VALUE));
            return;
        }
        else {
            // UIManager.showToast(StringUtils.format(GameModelManager.getLanguageTxt(GameTextData.GAME_TEXT_GRACE_TIP_ROLE), r.getRoleName(), l.level));
            let temp: AlertDialogViewProps =
            {
                dataptr: { roleId: roleId },
                titlecontent: "提升好感度",
                content: `当前与${r.getRoleName()}好感度等级为${l.level},观看视频提升好感度等级!`,
                ishasad: true,
                istwobtn: true,
                adconfig: "inject_fruit",
                // items: [],
                hasBanner: false,
                callback: (type, ret: boolean, param: any) => {
                    if (ret) {
                        if (type === "video") {
                            let rid = param.roleId;
                            let role = GameModelManager.getRoleData(rid);
                            if (role) {
                                role.addRoleLike(1000);
                                this.setViewProps();
                            }
                        } else {
                            UIManager.showToast("只能通过观看视频提升好感度等级!");
                        }
                    }
                }
            };
            UIManager.pushPresenter(AlertDialogViewPresenter, temp);
        }
    }

    private onItemClick = (key: string) => {
        // console.log("item click", key);
        GameModelManager.setGuideMsgItemRecord(key, GuideState.Complete);
        let sceneModel = GameModelManager.getMessageSceneModel(parseInt(key));
        if (!sceneModel) { console.error("message scene model not found ", key); return; }
        let isNew = PlotManager.getCurrentPlots().findIndex(v => v.plotSceneType === PlotSceneType.Message && v.plotSceneTypeId === sceneModel!.id) !== (-1);
        if (isNew || sceneModel.firstPlot.sentences[0].roleId == 3) {
            GameDotMgr.getInstance().dotClickUI("click_chat_card" + sceneModel.id);
        }
        UIManager.pushPresenter(ChatListViewPresenter, sceneModel);
    }

    checkGuideItem = () => {
        let k = GameModelManager.getMsgItemGuideKey();
        if (k && "" !== k) {
            let node = this._view.getItemNode(k);
            if (node) {
                let wp = node.convertToWorldSpaceAR(cc.v2(0, 0));
                let m: GuideViewParamModel = {
                    x: wp.x,
                    y: wp.y,
                    w: node.width,
                    h: node.height,
                    d: DirectionType.DOWM,
                    call: () => {
                        this.onItemClick(k);
                    }
                }
                UIManager.pushPresenter(GuideViewPresenter, m);
                GameDotMgr.getInstance().dotGuide(GuideOperationType.Show, GuideLocation.MsgItem);
            }
        }
    }

    onShowPlotBlocked = () => {
        this._viewProps.isShowPlotStopTipBtn = GameModelManager.checkIsPlotBlocked();
        this.view.updateProps(this._viewProps);
    }

    onRefreshAllStatus = () => {
        this.initViewProps();
        this.checkScenesActive();
        this.setViewProps();
        this._isCheckingPhoneCall = false;
        this.checkPhoneCall();
    }
}