package com.yidianling.im.helper import android.annotation.SuppressLint import android.content.Context import android.support.v4.content.ContextCompat import android.support.v7.app.AppCompatActivity import android.text.TextUtils import android.view.View import com.ydl.webview.H5Params import com.ydl.webview.NewH5Activity import com.ydl.ydlcommon.data.http.BaseAPIResponse import com.ydl.ydlcommon.data.http.BaseResponse import com.ydl.ydlcommon.data.http.RxUtils.applySchedulers import com.ydl.ydlcommon.data.http.UpLoadLogUtils.upLoadLog import com.ydl.ydlcommon.modular.ModularServiceManager import com.ydl.ydlcommon.ui.LoadingDialogFragment import com.ydl.ydlcommon.ui.LoadingDialogFragment.Companion.newInstance import com.ydl.ydlcommon.utils.NetworkParamsUtils import com.ydl.ydlcommon.utils.UserInfoCache import com.ydl.ydlcommon.utils.remind.HttpErrorUtils.Companion.handleError import com.ydl.ydlcommon.view.dialog.CommonDialog import com.yidianling.common.tools.LogUtil import com.yidianling.common.tools.ToastUtil import com.yidianling.im.R import com.yidianling.im.api.bean.IMExpertBuild import com.yidianling.im.bean.DoctorAssistantRespDtoBean import com.yidianling.im.bean.GetExpert import com.yidianling.im.bean.UserTypeBean import com.yidianling.im.bridge.P2PCustomActionHandlerImpl import com.yidianling.im.config.constants.ImConstants import com.yidianling.im.http.ImRetrofitApi.Companion.getImJavaApi import com.yidianling.im.http.ImRetrofitApi.Companion.getImRetrofitApi import com.yidianling.im.router.ImIn import com.yidianling.im.router.ImIn.isLogin import com.yidianling.im.session.SessionHelper import com.yidianling.im.ui.page.fragment.bean.ChatItemBean import com.yidianling.uikit.business.session.fragment.YDLMessageFragment import com.yidianling.uikit.business.session.helper.ChatStatusCacheHelper import com.yidianling.uikit.custom.bridge.ActionHandlerStorage import com.yidianling.uikit.custom.bridge.IP2PCustomActionHandler import com.yidianling.uikit.custom.http.ServiceImpl.Companion.instance import com.yidianling.uikit.custom.http.response.ChatStatusBean import com.yidianling.uikit.custom.http.response.RecommendExpertBean import com.yidianling.uikit.custom.widget.TitleBarBottom import com.yidianling.user.api.service.IUserService import io.reactivex.android.schedulers.AndroidSchedulers import io.reactivex.schedulers.Schedulers import retrofit2.HttpException import java.net.URLEncoder /** * 私聊页面相关接口封装 */ object IMChatUtil { private var loadingDialog: LoadingDialogFragment? = null private const val USER_TYPE_EXPERT=2//专家 private const val USER_TYPE_ASSISTANT=3//助理 private const val USER_TYPE_USER=1//用户 /** * 接口数据请求完成回调 */ interface ChatDataRequestListener { fun onSuccess(expertInfo: IMExpertBuild) } /** * 客服专用 */ fun startKefuChat(context: AppCompatActivity?) { SessionHelper.startP2PSession( context, -1, ImConstants.KEFUXIAOYI, null, P2PCustomActionHandlerImpl(ImConstants.KEFUXIAOYI, "客服小壹", ImConstants.KEFUXIAOYI) ) } /** * 私聊列表进入,后置数据请求 * * @param context * @param chatItemBean */ fun startChat(context: AppCompatActivity?, chatItemBean: ChatItemBean) { SessionHelper.startP2PSession( context, chatItemBean.utype, chatItemBean.toUid.toString(), null, P2PCustomActionHandlerImpl(chatItemBean) ) } /** * 非私聊列表进入,前置数据请求 * * @param context * @param toUid * @param isFromQingShu 用于判断是否从倾诉流程跳转私聊:1:是 其他:不是 从倾述流程跳转私聊,需要发送自定义消息 */ @SuppressLint("CheckResult") fun startChat(context: AppCompatActivity, toUid: String, isFromQingShu: Int) { if (!isLogin(context, true)) { return } if (loadingDialog == null) { loadingDialog = newInstance(null) } if (context.supportFragmentManager != null && !context.isDestroyed) { loadingDialog?.show(context.supportFragmentManager, null) } getImJavaApi().getUserType(toUid) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe({ res: BaseResponse<UserTypeBean> -> if (res.code == 200 && res.data != null) { if (res.data!!.chatEvent) { //和助理私聊需要打开常用语弹窗 ChatStatusCacheHelper.setStatusCache( "chatEvent", res.data!!.chatEvent ) } if (res.data!!.collectEvent) { //和助理私聊需要打开信息采集弹窗 ChatStatusCacheHelper.setStatusCache( "collectEvent", res.data!!.collectEvent ) } if (TextUtils.equals(res.data!!.userType, USER_TYPE_EXPERT.toString())) { //专家 //在uid用户类型确定为专家的情况下,根据uid调用接口判断是进入专家私聊还是助理私聊 getImJavaApi().getChatUid(toUid) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe({ resp: BaseAPIResponse<DoctorAssistantRespDtoBean> -> val bean = resp.data val toUid = bean.chatUid prepareChatData(context, toUid, object : ChatDataRequestListener { override fun onSuccess(expertInfo: IMExpertBuild) { startChatSession(toUid, expertInfo, isFromQingShu, context) } }) }) { t: Throwable? -> handleError(context, t!!) } } else { prepareAssistantChatData(context, toUid, object : ChatDataRequestListener { override fun onSuccess(expertInfo: IMExpertBuild) { startChatSession(toUid, expertInfo, isFromQingShu, context) } }) } } else { if (loadingDialog != null && loadingDialog!!.isVisible) { loadingDialog?.dismissAllowingStateLoss() } ToastUtil.toastShort(res.msg) } }, { throwable: Throwable? -> if (loadingDialog != null && loadingDialog!!.isVisible) { loadingDialog?.dismissAllowingStateLoss() } handleError(context, throwable!!) } ) } fun startChatCloseReplaceChat(context: AppCompatActivity, toUid: String) { if (!isLogin(context, true)) { return } if (loadingDialog == null) { loadingDialog = newInstance(null) } if (context.supportFragmentManager != null && !context.isDestroyed) { loadingDialog?.show(context.supportFragmentManager, null) } prepareChatData(context, toUid, object : ChatDataRequestListener { override fun onSuccess(expertInfo: IMExpertBuild) { startChatSession(toUid, expertInfo, 0, context) } }) } /** * 开启聊天会话 */ private fun startChatSession( toUid: String, expertInfo: IMExpertBuild, isFromQingShu: Int, context: AppCompatActivity ) { val p2PCustomActionHandlerImpl = P2PCustomActionHandlerImpl(toUid, expertInfo) p2PCustomActionHandlerImpl.isFromQingShu = isFromQingShu SessionHelper.startP2PSession( context, expertInfo.shareData.user_type, toUid, null, p2PCustomActionHandlerImpl ) } //====================准备私聊数据==================== /** * 初始化聊天数据 */ fun prepareChatData( context: AppCompatActivity, toUid: String, listener: ChatDataRequestListener ) { if (!isLogin(context, true)) { return } val dis = getImJavaApi().getUserType(toUid) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe({ res: BaseResponse<UserTypeBean> -> if (res.code == 200 && res.data != null) { if (res.data!!.chatEvent) { //和助理私聊需要打开常用语弹窗 ChatStatusCacheHelper.setStatusCache("chatEvent", res.data!!.chatEvent) } if (res.data!!.collectEvent) { //和助理私聊需要打开信息采集弹窗 ChatStatusCacheHelper.setStatusCache( "collectEvent", res.data!!.collectEvent ) } if (TextUtils.equals(res.data!!.userType, "2")) { //接口返回值是专家,java接口 prepareExpertChatData(context, toUid, listener) } else { //非专家 php接口 prepareAssistantChatData(context, toUid, listener) } } else { if (loadingDialog != null && loadingDialog!!.isVisible) { loadingDialog?.dismissAllowingStateLoss() } ToastUtil.toastShort(res.msg) } }, { throwable: Throwable? -> if (loadingDialog != null && loadingDialog!!.isVisible) { loadingDialog?.dismissAllowingStateLoss() } handleError(context, throwable!!) } ) } /** * 专家私聊数据请求 */ fun prepareExpertChatData( context: AppCompatActivity, toUid: String?, listener: ChatDataRequestListener ) { val disposable = getImJavaApi().getPersonalChat(toUid!!) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe({ resp: BaseResponse<IMExpertBuild> -> if (null != loadingDialog && loadingDialog?.isVisible!!) { loadingDialog?.dismissAllowingStateLoss() } if (resp.code == 200) { val expert = resp.data UserInfoCache.getInstance().saveYDLUser( expert.shareData.toUid, expert.shareData.doctorName, expert.shareData.cover ) listener.onSuccess(expert) } else { upLoadLog("consult/get-expert", resp.code, resp.msg) if (resp.code == ImConstants.HTTP_CODE_UNLOGIN) { ImIn.loginByOneKeyLogin(context,true) ToastUtil.toastShort(resp.msg) } else if (resp.code == ImConstants.SILENCED_CODE) { //禁言 showSilencedDialog(context, resp.data.tips, resp.data.url) } else { ToastUtil.toastShort(resp.msg) } } } ) { throwable: Throwable -> if (null != loadingDialog && loadingDialog!!.isVisible) { loadingDialog?.dismissAllowingStateLoss() } handleError(context, throwable) if (throwable is HttpException) { upLoadLog("consult/get-expert", throwable.code(), throwable.message!!) } } } /** * 助理私聊数据请求 */ fun prepareAssistantChatData( context: AppCompatActivity, toUid: String, listener: ChatDataRequestListener ) { val cmd = GetExpert(toUid.toInt(), 0) val disposable = getImRetrofitApi().getExpert(NetworkParamsUtils.getMaps(cmd)) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe({ resp: BaseResponse<IMExpertBuild> -> if (null != loadingDialog && loadingDialog!!.isVisible) { loadingDialog?.dismissAllowingStateLoss() } if (resp.code == 0) { val expert = resp.data UserInfoCache.getInstance().saveYDLUser( expert.shareData.toUid, expert.shareData.doctorName, expert.shareData.cover ) listener.onSuccess(expert) } else { upLoadLog("consult/get-expert", resp.code, resp.msg) if (resp.code == ImConstants.HTTP_CODE_UNLOGIN) { ImIn.loginByOneKeyLogin(context,true) ToastUtil.toastShort(resp.msg) } else if (resp.code == ImConstants.SILENCED_CODE) { //禁言 showSilencedDialog(context, resp.data.tips, resp.data.url) } else { ToastUtil.toastShort(resp.msg) } } } ) { throwable: Throwable -> if (null != loadingDialog && loadingDialog?.isVisible!!) { loadingDialog?.dismissAllowingStateLoss() } handleError(context, throwable) if (throwable is HttpException) { upLoadLog("consult/get-expert", throwable.code(), throwable.message!!) } } } //====================私聊页面 初始化操作==================== /** * 初始化在线状态接口 * * 只有专家显示在线、离线标识,其他用户Type隐藏在线、离线标识 */ fun initChatOnlineState( tb: TitleBarBottom, context: Context, toUid: String, messageFragment: YDLMessageFragment ) { val actionHandler = ActionHandlerStorage.getL(toUid) //获取私聊对方在线状态 if (null != actionHandler) { val docInfo = actionHandler.info docInfo.doctorBriefInfoFeedbackRate if (null != docInfo && (ImConstants.KEFUXIAOYI == docInfo.toUid || "4108805" == docInfo.toUid)) { //小壹客服 不显示是否在线 tb.setmMinTitleVisiable(View.GONE) } else { //对方是用户,自己是助理 if (actionHandler.userType == USER_TYPE_USER && ModularServiceManager.provide(IUserService::class.java) .getUserInfo()?.user_type == USER_TYPE_ASSISTANT ) { tb.setTitleTextRightIcon(R.drawable.user_info_icon) { messageFragment.showUserInfoDialog() } } if (actionHandler.userType == USER_TYPE_EXPERT) { // 专家 tb.setmMinTitleVisiable(View.VISIBLE) // 调取接口获取专家状态 val dis = instance .getDoctorChatStatus(actionHandler.info.toUid.toLong()) .compose(applySchedulers()) .subscribe( { chatStatusBean: BaseAPIResponse<ChatStatusBean> -> if (actionHandler != null) { val status = chatStatusBean.data.status actionHandler.setDoctorStatus(status) actionHandler.setDoctorBusyNum(chatStatusBean.data.busyTotal) //1.在线,2.离线,3.忙碌 4咨询中, 5倾述中 6咨询前准备 if (status == 2) { //离线 tb.setMinTitleText("离线") tb.setMinTitleColor( ContextCompat.getColor( context, R.color.platform_color_666666 ) ) tb.setMinTitleDrawable( ContextCompat.getDrawable( context, R.drawable.im_background_chat_top_status_off_line ) ) } else if (status == 4 || status == 5) { //服务中 tb.setMinTitleText("服务中") tb.setMinTitleColor( ContextCompat.getColor( context, R.color.platform_color_666666 ) ) tb.setMinTitleDrawable( ContextCompat.getDrawable( context, R.drawable.im_background_chat_top_status_online_server ) ) } else { //在线 1,3,6.. tb.setMinTitleText("在线") tb.setMinTitleColor( ContextCompat.getColor( context, R.color.platform_color_666666 ) ) tb.setMinTitleDrawable( ContextCompat.getDrawable( context, R.drawable.im_background_chat_top_status_online ) ) } initSystemMessage( chatStatusBean.data.promptRule, status, toUid, actionHandler ) } } ) { throwable: Throwable -> LogUtil.i("getDoctorChatStatus throwable:$throwable") } } else if (actionHandler.userType == USER_TYPE_ASSISTANT) { // 助理 tb.setmMinTitleVisiable(View.GONE) // 调取接口获取助理状态 instance.getAssistantChatStatus( actionHandler.info.toUid.toLong() ) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe({ res: BaseAPIResponse<Int> -> if (actionHandler != null) { if (res.data == 1) { //在线 /*tb.setMinTitleText("在线") tb.setMinTitleColor(context.resources.getColor(R.color.platform_color_666666)) tb.setMinTitleDrawable(context.resources.getDrawable(R.drawable.im_background_chat_top_status_online))*/ } else { //离线 /* tb.setMinTitleText("离线") tb.setMinTitleColor(context.resources.getColor(R.color.platform_color_666666)) tb.setMinTitleDrawable(context.resources.getDrawable(R.drawable.im_background_chat_top_status_off_line))*/ } } } ) { throwable: Throwable? -> } } else { tb.setmMinTitleVisiable(View.GONE) } } } } // promptRule 判断是否推荐专家 4,5直接不走文本提示和推荐逻辑,1,3不走推荐逻辑 //初始化 根据专家在线状态来发送提示消息或者推荐消息 private fun initSystemMessage( promptRule: Int, status: Int, toUid: String, actionHandler: IP2PCustomActionHandler ) { if (!(promptRule == 4 || promptRule == 5)) { val showExpertList = !(promptRule == 1 || promptRule == 3) if (actionHandler.userType == USER_TYPE_EXPERT && status == 2) { //当该专家离线时 sendRecommendExpertListMessage(1, showExpertList, toUid, actionHandler) } else if (actionHandler.userType == USER_TYPE_EXPERT&& status >= 3) { //当该专家忙碌时 sendRecommendExpertListMessage(2, showExpertList, toUid, actionHandler) } } } /** * 发送推荐专家列表 */ @SuppressLint("CheckResult") fun sendRecommendExpertListMessage( type: Int, showExpertList: Boolean, toUid: String, actionHandler: IP2PCustomActionHandler ) { // 调取接口获取推荐专家列表 instance.getRecommendExpertList( actionHandler.info.toUid.toLong(), URLEncoder.encode(actionHandler.info.tag1), 3 ) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe({ res: BaseAPIResponse<ArrayList<RecommendExpertBean>> -> //发送推荐专家列表消息 actionHandler.sendRecommendExpertListMessage(toUid, res.data, type, showExpertList) }, { throwable: Throwable -> ToastUtil.toastShort(throwable.toString()) }) } //====================展示提示==================== fun showSilencedDialog(context: Context, tips: String?, url: String?) { CommonDialog.create(context) .setMessage(tips) .setCancelAble(false) .setLeftOnclick( context.getString(R.string.im_details) ) { val realUrl = if (TextUtils.isEmpty(url)) ImConstants.HELP_URL else url!! val params = H5Params(realUrl, "") NewH5Activity.start(context, params) } .setRightClick(context.getString(R.string.im_approval), null) .show() } }