feat:初步搭建房间内公聊

This commit is contained in:
max
2024-05-08 19:52:16 +08:00
parent 7fd10e1222
commit 376fbdaeb2
13 changed files with 1258 additions and 23 deletions

View File

@@ -0,0 +1,106 @@
package com.chwl.app.avroom.adapter;
import android.content.Context;
import android.graphics.Color;
import android.view.Gravity;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.TextView;
import androidx.core.content.ContextCompat;
import com.chwl.app.R;
import com.chwl.app.ui.widget.XRecyclerView.ScaleTransitionPagerTitleView;
import com.chwl.app.ui.widget.magicindicator.buildins.UIUtil;
import com.chwl.app.ui.widget.magicindicator.buildins.commonnavigator.abs.CommonNavigatorAdapter;
import com.chwl.app.ui.widget.magicindicator.buildins.commonnavigator.abs.IPagerIndicator;
import com.chwl.app.ui.widget.magicindicator.buildins.commonnavigator.abs.IPagerTitleView;
import com.chwl.app.ui.widget.magicindicator.buildins.commonnavigator.indicators.GradientLineRoundPagerIndicator;
import com.chwl.app.ui.widget.magicindicator.buildins.commonnavigator.indicators.LinePagerIndicator;
import java.util.List;
public class RoomMessageIndicatorAdapter extends CommonNavigatorAdapter {
private final Context mContext;
private final List<? extends CharSequence> mTitleList;
private int textSize = 14;
private float minScale = 1f;
private boolean showIndicator = true;
private OnItemSelectListener mOnItemSelectListener;
public RoomMessageIndicatorAdapter(Context context, List<? extends CharSequence> charSequences) {
this.mContext = context;
this.mTitleList = charSequences;
}
@Override
public int getCount() {
return mTitleList == null ? 0 : mTitleList.size();
}
@Override
public IPagerTitleView getTitleView(Context context, final int i) {
ScaleTransitionPagerTitleView scaleTransitionPagerTitleView = new ScaleTransitionPagerTitleView(context, true);
scaleTransitionPagerTitleView.setNormalColor(ContextCompat.getColor(context, R.color.color_4D415E));
scaleTransitionPagerTitleView.setSelectedColor(ContextCompat.getColor(context, R.color.color_FFFFFF));
scaleTransitionPagerTitleView.setMinScale(minScale);
scaleTransitionPagerTitleView.setTextSize(textSize);
int padding = UIUtil.dip2px(context, 13);
scaleTransitionPagerTitleView.setPadding(padding, 0, padding, 0);
scaleTransitionPagerTitleView.setText(mTitleList.get(i));
scaleTransitionPagerTitleView.setOnClickListener(view -> {
if (mOnItemSelectListener != null) {
mOnItemSelectListener.onItemSelect(i, scaleTransitionPagerTitleView);
}
});
return scaleTransitionPagerTitleView;
}
@Override
public IPagerIndicator getIndicator(Context context) {
LinePagerIndicator indicator = new LinePagerIndicator(context);
indicator.setMode(LinePagerIndicator.MODE_EXACTLY);
indicator.setLineHeight(UIUtil.dip2px(mContext, 1.5));
indicator.setRoundRadius(UIUtil.dip2px(mContext, 1));
indicator.setLineWidth(UIUtil.dip2px(mContext, 8));
indicator.setColors(context.getResources().getColor(R.color.color_10ECD6));
FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
// lp.bottomMargin = mBottomMargin;
indicator.setLayoutParams(lp);
return indicator;
}
public int getTextSize() {
return textSize;
}
public void setTextSize(int textSize) {
this.textSize = textSize;
}
public float getMinScale() {
return minScale;
}
public void setMinScale(float minScale) {
this.minScale = minScale;
}
public boolean isShowIndicator() {
return showIndicator;
}
public void setShowIndicator(boolean showIndicator) {
this.showIndicator = showIndicator;
}
public void setOnItemSelectListener(OnItemSelectListener onItemSelectListener) {
mOnItemSelectListener = onItemSelectListener;
}
public interface OnItemSelectListener {
void onItemSelect(int position, TextView view);
}
}

View File

@@ -14,23 +14,21 @@ import android.text.TextUtils
import android.view.KeyEvent import android.view.KeyEvent
import android.view.MotionEvent import android.view.MotionEvent
import android.view.View import android.view.View
import android.view.ViewGroup
import android.view.ViewStub import android.view.ViewStub
import android.widget.EditText import android.widget.EditText
import android.widget.ImageView import android.widget.ImageView
import android.widget.RelativeLayout import android.widget.RelativeLayout
import android.widget.TextView
import androidx.annotation.CallSuper import androidx.annotation.CallSuper
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.lifecycle.LifecycleOwner import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.withResumed import androidx.lifecycle.withResumed
import com.netease.nim.uikit.common.antispam.AntiSpamEvent import androidx.recyclerview.widget.RecyclerView
import com.netease.nimlib.sdk.StatusCode import androidx.viewpager2.widget.ViewPager2
import com.netease.nimlib.sdk.chatroom.ChatRoomMessageBuilder import androidx.viewpager2.widget.ViewPager2.OnPageChangeCallback
import com.netease.nimlib.sdk.chatroom.model.ChatRoomKickOutEvent import com.chad.library.adapter.base.BaseViewHolder
import com.netease.nimlib.sdk.chatroom.model.ChatRoomMessage
import com.orhanobut.logger.Logger
import com.tbruyelle.rxpermissions2.RxPermissions
import com.trello.rxlifecycle3.android.FragmentEvent
import com.chwl.app.R import com.chwl.app.R
import com.chwl.app.avroom.BottomViewListenerWrapper import com.chwl.app.avroom.BottomViewListenerWrapper
import com.chwl.app.avroom.SoftKeyBoardListener import com.chwl.app.avroom.SoftKeyBoardListener
@@ -38,10 +36,12 @@ import com.chwl.app.avroom.SoftKeyBoardListener.OnSoftKeyBoardChangeListener
import com.chwl.app.avroom.activity.RoomInviteActivity import com.chwl.app.avroom.activity.RoomInviteActivity
import com.chwl.app.avroom.activity.RoomTitleEditActivity import com.chwl.app.avroom.activity.RoomTitleEditActivity
import com.chwl.app.avroom.adapter.OnMicroItemClickListener import com.chwl.app.avroom.adapter.OnMicroItemClickListener
import com.chwl.app.avroom.adapter.RoomMessageIndicatorAdapter
import com.chwl.app.avroom.dialog.AttentionHintDialog import com.chwl.app.avroom.dialog.AttentionHintDialog
import com.chwl.app.avroom.dialog.DatingVipRuleDialog import com.chwl.app.avroom.dialog.DatingVipRuleDialog
import com.chwl.app.avroom.dialog.RoomOperationDialog import com.chwl.app.avroom.dialog.RoomOperationDialog
import com.chwl.app.avroom.presenter.BaseRoomPresenter import com.chwl.app.avroom.presenter.BaseRoomPresenter
import com.chwl.app.avroom.public_chat.PublicChatRoomMessageWidget
import com.chwl.app.avroom.room_album.RoomAlbumModel import com.chwl.app.avroom.room_album.RoomAlbumModel
import com.chwl.app.avroom.view.IBaseRoomView import com.chwl.app.avroom.view.IBaseRoomView
import com.chwl.app.avroom.widget.BottomView import com.chwl.app.avroom.widget.BottomView
@@ -52,21 +52,24 @@ import com.chwl.app.base.BaseMvpFragment
import com.chwl.app.event.OpenRoomIntroEvent import com.chwl.app.event.OpenRoomIntroEvent
import com.chwl.app.friend.view.SelectFriendActivity import com.chwl.app.friend.view.SelectFriendActivity
import com.chwl.app.home.adapter.RoomActAdapter import com.chwl.app.home.adapter.RoomActAdapter
import com.chwl.app.music.widget.MusicPlayerView
import com.chwl.app.room_chat.activity.RoomMsgActivity
import com.chwl.app.ui.user.adapter.UserInfoIndicatorAdapter
import com.chwl.app.ui.widget.ButtonItem import com.chwl.app.ui.widget.ButtonItem
import com.chwl.app.ui.widget.GiftDialog import com.chwl.app.ui.widget.GiftDialog
import com.chwl.app.ui.widget.GiftDialog.OnGiftDialogBtnClickListener import com.chwl.app.ui.widget.GiftDialog.OnGiftDialogBtnClickListener
import com.chwl.app.ui.widget.GiftDialog.SenGiftCallback import com.chwl.app.ui.widget.GiftDialog.SenGiftCallback
import com.chwl.app.ui.widget.UserInfoDialog import com.chwl.app.ui.widget.UserInfoDialog
import com.chwl.app.ui.widget.dynamicface.DynamicFaceDialog import com.chwl.app.ui.widget.dynamicface.DynamicFaceDialog
import com.chwl.app.ui.widget.magicindicator.MagicIndicator
import com.chwl.app.ui.widget.magicindicator.buildins.UIUtil import com.chwl.app.ui.widget.magicindicator.buildins.UIUtil
import com.chwl.app.ui.widget.magicindicator.buildins.commonnavigator.CommonNavigator
import com.chwl.app.ui.widget.rollviewpager.RollPagerView import com.chwl.app.ui.widget.rollviewpager.RollPagerView
import com.chwl.app.ui.widget.rollviewpager.Util import com.chwl.app.ui.widget.rollviewpager.Util
import com.chwl.app.ui.widget.rollviewpager.hintview.ColorPointHintView import com.chwl.app.ui.widget.rollviewpager.hintview.ColorPointHintView
import com.chwl.app.utils.KeyBoardUtils import com.chwl.app.utils.KeyBoardUtils
import com.chwl.app.music.widget.MusicPlayerView
import com.chwl.app.room_chat.activity.RoomMsgActivity
import com.chwl.core.XConstants
import com.chwl.core.Constants import com.chwl.core.Constants
import com.chwl.core.XConstants
import com.chwl.core.auth.AuthModel import com.chwl.core.auth.AuthModel
import com.chwl.core.bean.RoomMicInfo import com.chwl.core.bean.RoomMicInfo
import com.chwl.core.gift.GiftModel import com.chwl.core.gift.GiftModel
@@ -104,6 +107,14 @@ import com.chwl.library.common.util.LimitClickUtils
import com.chwl.library.net.rxnet.utils.RxNetWorkUtils import com.chwl.library.net.rxnet.utils.RxNetWorkUtils
import com.chwl.library.rxbus.RxBus import com.chwl.library.rxbus.RxBus
import com.chwl.library.utils.* import com.chwl.library.utils.*
import com.netease.nim.uikit.common.antispam.AntiSpamEvent
import com.netease.nimlib.sdk.StatusCode
import com.netease.nimlib.sdk.chatroom.ChatRoomMessageBuilder
import com.netease.nimlib.sdk.chatroom.model.ChatRoomKickOutEvent
import com.netease.nimlib.sdk.chatroom.model.ChatRoomMessage
import com.orhanobut.logger.Logger
import com.tbruyelle.rxpermissions2.RxPermissions
import com.trello.rxlifecycle3.android.FragmentEvent
import io.reactivex.android.schedulers.AndroidSchedulers import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.Disposable import io.reactivex.disposables.Disposable
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@@ -125,6 +136,7 @@ open class BaseRoomFragment<V : IBaseRoomView?, P : BaseRoomPresenter<V>?> :
RoomView { RoomView {
private var myUid: Long = 0 private var myUid: Long = 0
protected lateinit var messageView: MessageView protected lateinit var messageView: MessageView
protected var publicChatMessageWidget: PublicChatRoomMessageWidget? = null
protected lateinit var bottomView: BottomView protected lateinit var bottomView: BottomView
protected lateinit var inputLayout: RelativeLayout protected lateinit var inputLayout: RelativeLayout
protected lateinit var inputEdit: EditText protected lateinit var inputEdit: EditText
@@ -172,7 +184,8 @@ open class BaseRoomFragment<V : IBaseRoomView?, P : BaseRoomPresenter<V>?> :
@CallSuper @CallSuper
override fun onFindViews() { override fun onFindViews() {
messageView = mView.findViewById(R.id.message_view) initMessageView()
// messageView = mView.findViewById(R.id.message_view)
bottomView = mView.findViewById(R.id.bottom_view) bottomView = mView.findViewById(R.id.bottom_view)
inputLayout = mView.findViewById(R.id.input_layout) inputLayout = mView.findViewById(R.id.input_layout)
inputEdit = mView.findViewById(R.id.input_edit) inputEdit = mView.findViewById(R.id.input_edit)
@@ -204,6 +217,75 @@ open class BaseRoomFragment<V : IBaseRoomView?, P : BaseRoomPresenter<V>?> :
}) })
} }
private fun initMessageView() {
messageView = MessageView(context)
publicChatMessageWidget = PublicChatRoomMessageWidget(requireContext())
val tabList: MutableList<String> = java.util.ArrayList(2)
tabList.add(getString(R.string.room))
tabList.add(getString(R.string.public_chat))
val messagePager = mView.findViewById<ViewPager2>(R.id.message_pager)
val messageIndicator = mView.findViewById<MagicIndicator>(R.id.message_indicator)
messagePager.offscreenPageLimit = tabList.size
messagePager.adapter = object : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
override fun onCreateViewHolder(
parent: ViewGroup,
viewType: Int
): RecyclerView.ViewHolder {
val view = if (viewType == 0) {
messageView
} else {
publicChatMessageWidget
}
view?.layoutParams = ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT
)
return BaseViewHolder(view)
}
override fun getItemCount(): Int {
return tabList.size
}
override fun getItemViewType(position: Int): Int {
return position
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
}
}
val commonNavigator = CommonNavigator(context)
commonNavigator.setTitleWrapContent(false)
val magicIndicatorAdapter = RoomMessageIndicatorAdapter(context, tabList)
magicIndicatorAdapter.setOnItemSelectListener { position: Int, view: TextView? ->
messagePager.currentItem = position
}
commonNavigator.adapter = magicIndicatorAdapter
messageIndicator.navigator = commonNavigator
messagePager.registerOnPageChangeCallback(object : OnPageChangeCallback() {
override fun onPageScrolled(
position: Int,
positionOffset: Float,
positionOffsetPixels: Int
) {
messageIndicator.onPageScrolled(
position,
positionOffset,
positionOffsetPixels
)
}
override fun onPageSelected(position: Int) {
messageIndicator.onPageSelected(position)
}
override fun onPageScrollStateChanged(state: Int) {
messageIndicator.onPageScrollStateChanged(state)
}
})
}
@CallSuper @CallSuper
override fun onSetListener() { override fun onSetListener() {
bottomView.setMagicBtnEnable(true) bottomView.setMagicBtnEnable(true)
@@ -815,7 +897,13 @@ open class BaseRoomFragment<V : IBaseRoomView?, P : BaseRoomPresenter<V>?> :
} }
}) })
val buttonItem4 = val buttonItem4 =
ButtonItem(ResUtil.getString(R.string.up_mic)) { toUpMicroPhone(micPosition, currentUid.toString() + "", false) } ButtonItem(ResUtil.getString(R.string.up_mic)) {
toUpMicroPhone(
micPosition,
currentUid.toString() + "",
false
)
}
//別問為什麽ui調整了順序 //別問為什麽ui調整了順序
//禁用超管的上麥和抱TA上麥 //禁用超管的上麥和抱TA上麥
if (!SuperAdminUtil.isSuperAdmin()) { if (!SuperAdminUtil.isSuperAdmin()) {
@@ -1236,6 +1324,9 @@ open class BaseRoomFragment<V : IBaseRoomView?, P : BaseRoomPresenter<V>?> :
open fun initWidget() { open fun initWidget() {
publicChatMessageWidget?.let {
registerWidget(PublicChatRoomMessageWidget::class.java.simpleName, it)
}
} }
@Subscribe(threadMode = ThreadMode.MAIN) @Subscribe(threadMode = ThreadMode.MAIN)

View File

@@ -0,0 +1,851 @@
package com.chwl.app.avroom.public_chat;
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.text.Spannable;
import android.text.TextUtils;
import android.text.method.LinkMovementMethod;
import android.text.style.ForegroundColorSpan;
import android.util.AttributeSet;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.content.ContextCompat;
import androidx.core.content.res.ResourcesCompat;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.recyclerview.widget.SimpleItemAnimator;
import com.chwl.app.R;
import com.chwl.app.UIHelper;
import com.chwl.app.avroom.activity.AVRoomActivity;
import com.chwl.app.avroom.dialog.PKResultDialog;
import com.chwl.app.avroom.widget.OnMsgLongClickListener;
import com.chwl.app.avroom.widget.TemplateMessageAdapter;
import com.chwl.app.common.widget.OriginalDrawStatusClickSpan;
import com.chwl.app.ui.utils.ImageLoadUtils;
import com.chwl.app.ui.widget.DividerItemDecoration;
import com.chwl.app.ui.widget.MyItemAnimator;
import com.chwl.app.ui.widget.RecyclerViewNoViewpagerScroll;
import com.chwl.app.ui.widget.magicindicator.buildins.UIUtil;
import com.chwl.app.utils.RegexUtil;
import com.chwl.core.DemoCache;
import com.chwl.core.XConstants;
import com.chwl.core.auth.AuthModel;
import com.chwl.core.bean.attachmsg.RoomQueueMsgAttachment;
import com.chwl.core.decoration.car.bean.CarInfo;
import com.chwl.core.helper.ImHelperUtils;
import com.chwl.core.home.event.FollowRoomEvent;
import com.chwl.core.home.model.CollectionRoomModel;
import com.chwl.core.im.custom.bean.AuctionAttachment;
import com.chwl.core.im.custom.bean.CustomAttachment;
import com.chwl.core.im.custom.bean.MonsterHuntingResultAttachment;
import com.chwl.core.im.custom.bean.MonsterStatusAttachment;
import com.chwl.core.im.custom.bean.RoomBoxPrizeAttachment;
import com.chwl.core.im.custom.bean.RoomFollowOwnerAttachment2;
import com.chwl.core.im.custom.bean.RoomTipAttachment;
import com.chwl.core.im.custom.bean.TarotAttachment;
import com.chwl.core.im.custom.bean.WelcomeAttachment;
import com.chwl.core.level.UserLevelResourceType;
import com.chwl.core.manager.AvRoomDataManager;
import com.chwl.core.manager.IMNetEaseManager;
import com.chwl.core.monsterhunting.bean.MonsterDataBean;
import com.chwl.core.monsterhunting.bean.MonsterHuntingResult;
import com.chwl.core.noble.NobleUtil;
import com.chwl.core.praise.PraiseModel;
import com.chwl.core.room.bean.RoomInfo;
import com.chwl.core.room.bean.WelcomeInfo;
import com.chwl.core.room.model.AvRoomModel;
import com.chwl.core.room.pk.attachment.RoomPkAttachment;
import com.chwl.core.user.UserModel;
import com.chwl.core.user.bean.UserInfo;
import com.chwl.core.utils.ExtensionUtil;
import com.chwl.library.common.util.Utils;
import com.chwl.library.utils.JavaUtil;
import com.chwl.library.utils.ListUtils;
import com.chwl.library.utils.ResUtil;
import com.chwl.library.utils.SingleToastUtil;
import com.chwl.library.utils.SizeUtils;
import com.example.lib_utils.UiUtils;
import com.netease.nim.uikit.business.uinfo.UserInfoHelper;
import com.netease.nim.uikit.common.util.log.LogUtil;
import com.netease.nim.uikit.common.util.sys.ScreenUtil;
import com.netease.nimlib.sdk.chatroom.model.ChatRoomMessage;
import com.netease.nimlib.sdk.chatroom.model.ChatRoomMessageExtension;
import com.netease.nimlib.sdk.chatroom.model.ChatRoomNotificationAttachment;
import com.netease.nimlib.sdk.msg.attachment.MsgAttachment;
import com.netease.nimlib.sdk.msg.constant.MsgTypeEnum;
import com.netease.nimlib.sdk.msg.constant.NotificationType;
import org.greenrobot.eventbus.EventBus;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import io.reactivex.Single;
import io.reactivex.SingleSource;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.functions.Consumer;
import io.reactivex.functions.Function;
import com.chwl.app.avroom.widget.MessageView.SpannableBuilder;
/**
* 直播間消息界面
*
* @author xiaoyu
*/
public class PublicChatMessageView extends FrameLayout {
private static final String TAG = "PublicChatMessageView";
private final static int MAX_MESSAGE_SIZE = 2000;//公屏最多展示條數
private final static int BLOCK_MAX_MESSAGE_SIZE = MAX_MESSAGE_SIZE * 3 / 2;//在查看消息停住的時候 最多消息條數.
private static final int LOAD_MESSAGE_COUNT = 10;
private final int textColor = 0x80ffffff;
private final List<ChatRoomMessage> atMessages = new ArrayList<>();
private final List<ChatRoomMessage> chatRoomMessages = new LinkedList<>();
private RecyclerView messageListView;
private TextView tvBottomTip;
private TextView tvAtTip;
private MessageAdapter mMessageAdapter;
private LinearLayoutManager layoutManger;
private int paddingWidth;
private int paddingHeight;
private int whiteColor;
private int greyColor;
private int roomTipNickColor;
private int roomTipColor;
private int roomBlueColor;
private int badgeWidth;
private int badgeHeight;
private int sysIconHeight;
private int smallFace;
private int bigFace;
private int expLevelWidth;
private int expLevelHeight;
private int giftLength;
private volatile boolean needAutoScroll = true;//是否自動滾動到底部
private Consumer<String> clickConsumer;
private OnClick onClick;
private OnMsgLongClickListener onLongClickListener;
private TemplateMessageAdapter templateMessageAdapter;
public PublicChatMessageView(Context context) {
this(context, null);
}
public PublicChatMessageView(Context context, AttributeSet attr) {
this(context, attr, 0);
}
public PublicChatMessageView(Context context, AttributeSet attr, int i) {
super(context, attr, i);
init(context);
}
public void setOnLongClickListener(OnMsgLongClickListener onLongClickListener) {
this.onLongClickListener = onLongClickListener;
}
public void setClickConsumer(Consumer<String> clickConsumer) {
this.clickConsumer = clickConsumer;
}
public void setOnClick(OnClick onClick) {
this.onClick = onClick;
}
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
}
@SuppressLint("ClickableViewAccessibility")
private void init(Context context) {
whiteColor = ContextCompat.getColor(context, R.color.white);
greyColor = ContextCompat.getColor(context, R.color.white_transparent_50);
roomTipNickColor = ContextCompat.getColor(context, R.color.color_FEE057);
roomTipColor = ContextCompat.getColor(context, R.color.color_FEE057);
roomBlueColor = ContextCompat.getColor(context, R.color.color_00EAFF);
paddingWidth = Utils.dip2px(context, 11);
paddingHeight = Utils.dip2px(context, 6);
badgeWidth = Utils.dip2px(context, 15);
badgeHeight = Utils.dip2px(context, 15);
sysIconHeight = Utils.dip2px(context, 14);
smallFace = Utils.dip2px(context, 22);
bigFace = Utils.dip2px(context, 30);
//經驗等級圖片後臺已經更換尺寸了公屏同步下尺寸是36:18
expLevelHeight = Utils.dip2px(context, 18);
expLevelWidth = expLevelHeight * 36 / 18;//expLevelHeight * 114 / 45
giftLength = Utils.dip2px(context, 35);
// 內容區域
layoutManger = new LinearLayoutManager(context, RecyclerView.VERTICAL, false);
LayoutParams params = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
messageListView = new RecyclerViewNoViewpagerScroll(context);
messageListView.setLayoutParams(params);
messageListView.setFadingEdgeLength(60);
messageListView.setVerticalFadingEdgeEnabled(true);
messageListView.setOverScrollMode(OVER_SCROLL_NEVER);
messageListView.setHorizontalScrollBarEnabled(false);
addView(messageListView);
messageListView.setLayoutManager(layoutManger);
messageListView.addItemDecoration(new DividerItemDecoration(context, layoutManger.getOrientation(), 16, R.color.transparent));
mMessageAdapter = new MessageAdapter(getContext());
mMessageAdapter.setData(chatRoomMessages);
messageListView.setAdapter(mMessageAdapter);
messageListView.setItemAnimator(new MyItemAnimator());
messageListView.getItemAnimator().setAddDuration(0);
messageListView.getItemAnimator().setChangeDuration(0);
messageListView.getItemAnimator().setMoveDuration(0);
messageListView.getItemAnimator().setRemoveDuration(0);
((SimpleItemAnimator) messageListView.getItemAnimator()).setSupportsChangeAnimations(false);
if (AvRoomDataManager.get().isOpenGame()) {
messageListView.setOnTouchListener((v, event) -> {
if (messageListView.getScrollState() == RecyclerView.SCROLL_STATE_IDLE
&& event.getAction() == MotionEvent.ACTION_UP) {
ViewGroup.LayoutParams layoutParams = getLayoutParams();
int bigHeight = ScreenUtil.dip2px(200);
int littleHeight = ScreenUtil.dip2px(80);
layoutParams.height = layoutParams.height == littleHeight ? bigHeight : littleHeight;
setLayoutParams(layoutParams);
}
return false;
});
}
// 底部有新消息
tvBottomTip = new TextView(context);
LayoutParams params1 = new LayoutParams(
Utils.dip2px(context, 115F), Utils.dip2px(context, 27));
params1.gravity = Gravity.BOTTOM;
params1.leftMargin = UIUtil.getScreenWidth(context) / 2 - UIUtil.dip2px(context, 115 / 2);
tvBottomTip.setBackgroundResource(R.drawable.bg_messge_view_bottom_tip);
tvBottomTip.setGravity(Gravity.CENTER);
tvBottomTip.setText(context.getString(R.string.message_view_bottom_tip));
tvBottomTip.setTextColor(context.getResources().getColor(R.color.appColor));
tvBottomTip.setLayoutParams(params1);
tvBottomTip.setVisibility(GONE);
tvBottomTip.setOnClickListener(v -> {
tvBottomTip.setVisibility(GONE);
needAutoScroll = true;
messageListView.smoothScrollToPosition(mMessageAdapter.getItemCount() - 1);
});
addView(tvBottomTip);
//有人@我
tvAtTip = new TextView(context);
LayoutParams params2 = new LayoutParams(
Utils.dip2px(context, 115F), Utils.dip2px(context, 27));
params2.gravity = Gravity.BOTTOM;
params2.leftMargin = UIUtil.getScreenWidth(context) / 2 - UIUtil.dip2px(context, 115 / 2);
tvAtTip.setBackgroundResource(R.drawable.bg_messge_view_bottom_tip);
tvAtTip.setGravity(Gravity.CENTER);
tvAtTip.setText(context.getString(R.string.message_view_bottom_tip));
tvAtTip.setTextColor(context.getResources().getColor(R.color.color_FD85C9));
tvAtTip.setLayoutParams(params2);
tvAtTip.setVisibility(GONE);
tvAtTip.setOnClickListener(v -> {
if (!atMessages.isEmpty()) {
int scrollIndex = chatRoomMessages.indexOf(atMessages.remove(0));
if (scrollIndex != -1 && scrollIndex < mMessageAdapter.getItemCount()) {
messageListView.smoothScrollToPosition(scrollIndex);
}
}
needAutoScroll = false;
checkShowAtTip();
});
addView(tvAtTip);
messageListView.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
}
@Override
public void onScrollStateChanged(final RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
if (newState == RecyclerView.SCROLL_STATE_DRAGGING) {
// Logger.e(TAG, "onScrollStateChanged: SCROLL_STATE_DRAGGING");
needAutoScroll = false;
}
if (newState == RecyclerView.SCROLL_STATE_IDLE) {
// Logger.e(TAG, "onScrollStateChanged: SCROLL_STATE_IDLE");
int lastVisibleItemPosition = layoutManger.findLastVisibleItemPosition();
if (lastVisibleItemPosition == RecyclerView.NO_POSITION) {
// Logger.e(TAG, "lastCompletelyVisibleItemPosition : RecyclerView.NO_POSITION");
needAutoScroll = true;
} else if (!atMessages.isEmpty() && atMessages.remove(chatRoomMessages.get(lastVisibleItemPosition))) {
checkShowAtTip();
}
// Log.e(TAG, "lastVisibleItemPosition:" + lastVisibleItemPosition
// + " mMessageAdapter.getItemCount()-1:" + (recyclerView.getAdapter().getItemCount()-1)
// + " dis:"+ (lastVisibleItemPosition-(recyclerView.getAdapter().getItemCount()-1)));
if (lastVisibleItemPosition >= recyclerView.getAdapter().getItemCount() - 3) {
//最後一個顯示出來了
// Logger.e(TAG, ResUtil.getString(R.string.avroom_widget_messageview_01));
needAutoScroll = true;
tvBottomTip.setVisibility(GONE);
keepSizeUnderLimit();
} else {
// Logger.e(TAG, ResUtil.getString(R.string.avroom_widget_messageview_02));
// needAutoScroll = false;
}
}
}
});
}
private TemplateMessageAdapter getTemplateMessageAdapter() {
if (templateMessageAdapter == null) {
templateMessageAdapter = new TemplateMessageAdapter(uid -> {
if (clickConsumer != null) {
Single.just(String.valueOf(uid)).subscribe(clickConsumer);
}
});
}
return templateMessageAdapter;
}
public void onCurrentRoomReceiveNewMsg(List<ChatRoomMessage> messages) {
if (messages == null) return;
if (messages.size() == 1) {
addMessages(messages.get(0));
} else {
addHistoryMessages(messages);
}
}
/**
* 添加公屏消息請使用 {@link AvRoomDataManager#addChatRoomMessage(ChatRoomMessage)}
*/
private void addMessages(ChatRoomMessage msg) {
if (msg == null) return;
chatRoomMessages.add(msg);
//通知adapter 刷新
mMessageAdapter.notifyItemInserted(mMessageAdapter.getItemCount() - 1);
showTipsOrScrollToBottom();
checkAtMe(msg, false);
}
public void addMessages(List<ChatRoomMessage> messages) {
if (messages == null) return;
chatRoomMessages.addAll(messages);
//通知adapter 刷新
mMessageAdapter.notifyItemInserted(mMessageAdapter.getItemCount() - 1);
showTipsOrScrollToBottom();
for (ChatRoomMessage message : messages) {
checkAtMe(message, true);
}
}
public void addHistoryMessages(List<ChatRoomMessage> messages) {
chatRoomMessages.addAll(chatRoomMessages.size() > 0 ? 1 : 0, messages);
mMessageAdapter.notifyDataSetChanged();
messageListView.scrollToPosition(mMessageAdapter.getItemCount() - 1);
for (ChatRoomMessage message : messages) {
checkAtMe(message, true);
}
}
private void keepSizeUnderLimit() {
while (chatRoomMessages.size() > MAX_MESSAGE_SIZE) {
Log.i("keepSizeUnderLimit", "size" + chatRoomMessages.size());
ChatRoomMessage message = chatRoomMessages.remove(0);
if (atMessages.remove(message)) {
checkShowAtTip();
}
mMessageAdapter.notifyItemRemoved(0);
}
}
private void checkShowAtTip() {
tvAtTip.setText(getContext().getString(R.string.message_at_tip, atMessages.size()));
tvAtTip.setVisibility(atMessages.size() == 0 ? GONE : VISIBLE);
}
private void checkAtMe(ChatRoomMessage msg, boolean history) {
if (msg.getMsgType() != MsgTypeEnum.text) return;
List<String> atUids = ExtensionUtil.getListExtension(msg, UserInfo.AT_UIDS);
List<String> atNames = ExtensionUtil.getListExtension(msg, UserInfo.AT_NAMES);
if (!ListUtils.isListEmpty(atUids) && !ListUtils.isListEmpty(atNames)) {
for (int i = 0; i < atUids.size(); i++) {
String uid = atUids.get(i);
// 只有當被 @ 人的數組中包含自己的時候才會去變色
if (Objects.equals(uid, String.valueOf(AuthModel.get().getCurrentUid()))) {
Map<String, Long> atMap = DemoCache.readAtMsgUuid();
if (atMap == null || !atMap.containsKey(msg.getUuid())) {
if (!atMessages.contains(msg) && (!needAutoScroll || history)) {
atMessages.add(msg);
checkShowAtTip();
}
DemoCache.saveAtMsgUuid(msg.getUuid());
}
}
}
}
}
private void showTipsOrScrollToBottom() {
if (!needAutoScroll) {
tvBottomTip.setVisibility(VISIBLE);
//超過某值後自動滾動下去
if (mMessageAdapter.getItemCount() > BLOCK_MAX_MESSAGE_SIZE) {
messageListView.smoothScrollToPosition(mMessageAdapter.getItemCount() - 1);
}
return;
}
messageListView.smoothScrollToPosition(mMessageAdapter.getItemCount() - 1);
}
public void release() {
}
public void clear() {
if (mMessageAdapter != null) {
chatRoomMessages.clear();
mMessageAdapter.notifyDataSetChanged();
}
if (tvBottomTip != null) {
needAutoScroll = true;
tvBottomTip.setVisibility(GONE);
}
}
public interface OnClick {
/**
* 點擊關註
*
* @param position
*/
void onFollowClick(int position);
void onJoinMiniWorldClick(int position);
/**
* 公屏查看公告
*/
void onShowRoomIntroduction();
}
private class MessageAdapter extends RecyclerView.Adapter<MessageAdapter.MessageViewHolder> implements OnClickListener {
private Context mContext;
private List<ChatRoomMessage> data;
public MessageAdapter(Context mContext) {
this.mContext = mContext;
}
public void setData(List<ChatRoomMessage> data) {
this.data = data;
}
@Override
public int getItemViewType(int position) {
ChatRoomMessage chatRoomMessage = data.get(position);
if (chatRoomMessage.getMsgType() == MsgTypeEnum.custom) {
MsgAttachment attachment = chatRoomMessage.getAttachment();
if (attachment instanceof CustomAttachment) {
if (((CustomAttachment) attachment).getFirst() == CustomAttachment.CUSTOM_MSG_ROOM_ALBUM) {
return CustomAttachment.CUSTOM_MSG_ROOM_ALBUM;
}
}
}
return super.getItemViewType(position);
}
@Override
public MessageViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return new MessageViewHolder(LayoutInflater.from(parent.getContext())
.inflate(R.layout.list_item_chatrrom_msg, parent, false));
}
@Override
public void onBindViewHolder(MessageViewHolder holder, int position) {
convert(holder, data.get(position));
}
@Override
public int getItemCount() {
return data.size();
}
protected void convert(MessageViewHolder baseViewHolder, ChatRoomMessage chatRoomMessage) {
if (chatRoomMessage == null) return;
TextView tvContent = baseViewHolder.tvContent;
tvContent.setLineSpacing(0, 1);
tvContent.setTextColor(Color.WHITE);
tvContent.setOnClickListener(this);
tvContent.setOnLongClickListener(null);
tvContent.setTag(chatRoomMessage);
tvContent.setGravity(Gravity.START | Gravity.CENTER_VERTICAL);
if (UiUtils.INSTANCE.isRtl(tvContent.getContext())) {
tvContent.setTextDirection(View.TEXT_DIRECTION_RTL);
}
clearBackground(tvContent);
try {
if (chatRoomMessage.getMsgType() == MsgTypeEnum.tip) {
String contentText = chatRoomMessage.getContent();
// 房間通告
tvContent.setTextColor(ContextCompat.getColor(mContext, R.color.color_92F9E8));
tvContent.setText(chatRoomMessage.getContent());
tvContent.setBackgroundResource(R.drawable.shape_room_message_tip_bg);
} else if (chatRoomMessage.getMsgType() == MsgTypeEnum.text) {
setMsgText(chatRoomMessage, tvContent);
setVIPMessageBackground(chatRoomMessage, tvContent);
} else if (chatRoomMessage.getMsgType() == MsgTypeEnum.notification) {
// 加上勛章
setMsgNotification(chatRoomMessage, tvContent, baseViewHolder.getAdapterPosition());
setVIPMessageBackground(chatRoomMessage, tvContent);
} else if (chatRoomMessage.getMsgType() == MsgTypeEnum.custom) {
CustomAttachment attachment = (CustomAttachment) chatRoomMessage.getAttachment();
int first = attachment.getFirst();
int second = attachment.getSecond();
if (first == CustomAttachment.CUSTOM_MSG_HEADER_TYPE_AUCTION) {
setMsgAuction(chatRoomMessage, tvContent, attachment);
} else {
tvContent.setTextColor(Color.WHITE);
tvContent.setText(tvContent.getResources().getText(R.string.not_support_message_tip));
}
}
} catch (UnsupportedOperationException e) {
e.printStackTrace();
clearBackground(tvContent);
tvContent.setTextColor(Color.WHITE);
tvContent.setText(tvContent.getResources().getText(R.string.not_support_message_tip));
}
}
private void clearBackground(TextView textView) {
// 清除文字
textView.setText("");
// 清除聊天氣泡
textView.setBackgroundResource(R.drawable.shape_room_message_bg);
textView.setPadding(paddingWidth, paddingHeight, paddingWidth, paddingHeight);
}
public void setVIPMessageBackground(ChatRoomMessage chatRoomMessage, View view) {
String androidBubbleUrl = NobleUtil.getResource(UserInfo.BUBBLE_URL_ANDROID, chatRoomMessage);
if (TextUtils.isEmpty(androidBubbleUrl)) return;
view.setPadding(paddingWidth, ScreenUtil.dip2px(10), paddingWidth, ScreenUtil.dip2px(10));
ImageLoadUtils.loadNinePatchBg(view, androidBubbleUrl);
}
/**
* {badge}{level}xxx: 文字內容
*
* @param chatRoomMessage -
* @param tvContent -
*/
private void setMsgText(ChatRoomMessage chatRoomMessage, TextView tvContent) {
ChatRoomMessageExtension extension = chatRoomMessage.getChatRoomMessageExtension();
SpannableBuilder text = new SpannableBuilder(tvContent);
addCommonTag(chatRoomMessage, text, tvContent);
String nickName = extension == null ? ResUtil.getString(R.string.avroom_widget_messageview_0116) : RegexUtil.getPrintableString(extension.getSenderNick());
text.append(nickName, new ForegroundColorSpan(greyColor))
.append(": " + chatRoomMessage.getContent(), new ForegroundColorSpan(getResources().getColor(R.color.white)));
List<String> atUids = ExtensionUtil.getListExtension(chatRoomMessage, UserInfo.AT_UIDS);
List<String> atNames = ExtensionUtil.getListExtension(chatRoomMessage, UserInfo.AT_NAMES);
if (!ListUtils.isListEmpty(atUids) && !ListUtils.isListEmpty(atNames)) {
for (int i = 0; i < atUids.size(); i++) {
String name = atNames.get(i);
String uid = atUids.get(i);
// 只有當被 @ 人的數組中包含自己的時候才會去變色
if (Objects.equals(uid, String.valueOf(AuthModel.get().getCurrentUid()))) {
Pattern pattern = Pattern.compile(Pattern.quote(name));
Matcher matcher = pattern.matcher(text.build().toString());
while (matcher.find()) {
int start = matcher.start();
int end = matcher.end();
text.build().setSpan(new ForegroundColorSpan(getContext().getResources().getColor(R.color.color_FD85C9)),
start, end, Spannable.SPAN_INCLUSIVE_INCLUSIVE);
}
}
}
}
if (Objects.equals(chatRoomMessage.getFromAccount(), String.valueOf(AuthModel.get().getCurrentUid()))) {
tvContent.setOnLongClickListener(null);
} else {
tvContent.setOnLongClickListener(v -> {
if (onLongClickListener != null) {
onLongClickListener.onLongClick(v, chatRoomMessage.getFromAccount(), nickName);
}
return true;
});
}
tvContent.setText(text.build());
}
private void addCommonTag(ChatRoomMessage chatRoomMessage, @NonNull SpannableBuilder builder, TextView tvContent) {
ChatRoomMessageExtension extension = chatRoomMessage.getChatRoomMessageExtension();
String userLevel = NobleUtil.getLevel(UserLevelResourceType.EXPER_URL, chatRoomMessage);
boolean isOfficial = NobleUtil.getIsOfficial(UserInfo.IS_OFFICIAL, chatRoomMessage);
String vipIcon = NobleUtil.getResource(UserInfo.VIP_ICON, chatRoomMessage);
builder.append(vipIcon, expLevelHeight)
.append(isOfficial ? ResourcesCompat.getDrawable(getResources(),
R.mipmap.ic_user_official_13dp, null) : null,
badgeWidth, badgeHeight)
.append(getNewUserDrawable(chatRoomMessage), badgeWidth, badgeHeight)
.append(AvRoomDataManager.get().isSuperAdmin(chatRoomMessage.getFromAccount()) ? ResourcesCompat.getDrawable(getResources(),
R.drawable.ic_room_super_admin, null) : null,
SizeUtils.dp2px(tvContent.getContext(), 23), expLevelHeight);
// 官方主播認證
String tvOfficialMask = NobleUtil.getLevel(UserInfo.OAC_NAME, chatRoomMessage).trim();
String ivOfficialMask = NobleUtil.getLevel(UserInfo.OAC_ICON, chatRoomMessage);
if (!TextUtils.isEmpty(tvOfficialMask) && !TextUtils.isEmpty(ivOfficialMask) && extension != null) { // extension != null 表示自己
builder.appendBgAndContent(ivOfficialMask, tvOfficialMask);
} else if (!TextUtils.isEmpty(ivOfficialMask)) {
builder.append(ivOfficialMask, SizeUtils.dp2px(tvContent.getContext(), 62), expLevelHeight);
}
//等級
builder.append(userLevel, expLevelHeight);
//銘牌
String tvNamePlate = NobleUtil.getNamePlate(UserInfo.NAMEPLATE_WORD, chatRoomMessage).trim();
String ivNamePlate = NobleUtil.getNamePlate(UserInfo.NAMEPLATE_PIC, chatRoomMessage);
if (!TextUtils.isEmpty(tvNamePlate) && !TextUtils.isEmpty(ivNamePlate)) { // extension != null 表示自己
builder.appendBgAndContent(ivNamePlate, tvNamePlate);
} else if (!TextUtils.isEmpty(ivNamePlate)) {
builder.append(ivNamePlate, expLevelHeight);
}
}
/**
* 暫時已拋棄
*
* @param chatRoomMessage -
* @param tvContent -
* @param attachment -
*/
private void setMsgAuction(ChatRoomMessage chatRoomMessage, TextView tvContent, CustomAttachment attachment) {
String senderNick = chatRoomMessage.getChatRoomMessageExtension().getSenderNick();
senderNick = senderNick == null ? "" : senderNick;
AuctionAttachment auctionAttachment = (AuctionAttachment) attachment;
SpannableBuilder builder = new SpannableBuilder(tvContent);
if (attachment.getSecond() == CustomAttachment.CUSTOM_MSG_SUB_TYPE_AUCTION_START) {
builder.append(ResUtil.getString(R.string.avroom_widget_messageview_0117), new ForegroundColorSpan(roomTipNickColor));
} else if (attachment.getSecond() == CustomAttachment.CUSTOM_MSG_SUB_TYPE_AUCTION_FINISH) {
if (auctionAttachment.getAuctionInfo().getCurMaxUid() > 0) {
senderNick = UserInfoHelper.getUserDisplayName(auctionAttachment.getAuctionInfo().getCurMaxUid() + "");
String voiceActorNick = UserInfoHelper.getUserDisplayName(auctionAttachment.getAuctionInfo().getAuctUid() + "");
builder.append(senderNick, new ForegroundColorSpan(roomTipNickColor))
.append(ResUtil.getString(R.string.avroom_widget_messageview_0118) + auctionAttachment.getAuctionInfo().getRivals().get(0).getAuctMoney() + ResUtil.getString(R.string.avroom_widget_messageview_0119))
.append(voiceActorNick, new ForegroundColorSpan(roomTipNickColor));
} else
builder.append(ResUtil.getString(R.string.avroom_widget_messageview_0120), new ForegroundColorSpan(roomTipNickColor));
} else {
builder.append(senderNick, new ForegroundColorSpan(roomTipNickColor))
.append(ResUtil.getString(R.string.avroom_widget_messageview_0121) + auctionAttachment.getAuctionInfo().getRivals().get(0).getAuctMoney() + ResUtil.getString(R.string.avroom_widget_messageview_027));
}
tvContent.setText(builder.build());
}
/**
* {badge}xxx來了
*
* @param chatRoomMessage -
* @param tvContent -
*/
private void setMsgNotification(ChatRoomMessage chatRoomMessage, TextView tvContent, int position) {
int fromType = 0;
String fromNick = "";
String fromUid = "";
Map<String, Object> remoteExtension = chatRoomMessage.getRemoteExtension();
if (remoteExtension != null) {
fromType = (int) remoteExtension.get("fromType");
fromNick = (String) remoteExtension.get("fromNick");
fromUid = (String) remoteExtension.get("fromUid");
}
ChatRoomNotificationAttachment attachment = (ChatRoomNotificationAttachment) chatRoomMessage.getAttachment();
String senderNick = "";
List<String> nicks = attachment.getTargetNicks();
if (nicks != null && nicks.size() > 0)
senderNick = RegexUtil.getPrintableString(attachment.getTargetNicks().get(0));
if (attachment.getType() != NotificationType.ChatRoomMemberIn) return;
// 座駕
String carName = NobleUtil.getCarName(CarInfo.CAR_NAME, chatRoomMessage);
carName = TextUtils.isEmpty(carName) ? "" : "\"" + carName + "\"";
SpannableBuilder text = new SpannableBuilder(tvContent);
addCommonTag(chatRoomMessage, text, tvContent);
text.append(senderNick, new ForegroundColorSpan(roomTipColor),
new OriginalDrawStatusClickSpan() {
@Override
public void onClick(@NonNull View view) {
if (clickConsumer != null) {
Single.just(chatRoomMessage.getFromAccount())
.doOnSuccess(clickConsumer).subscribe();
}
}
});
text.append(TextUtils.isEmpty(carName) ? "" : ResUtil.getString(R.string.avroom_widget_messageview_0150), new ForegroundColorSpan(greyColor))
.append(carName, new ForegroundColorSpan(roomTipColor));
String enterText = ResUtil.getString(R.string.avroom_widget_messageview_0151);
if (fromType == AVRoomActivity.FROM_TYPE_RECOMMEND) {
enterText = ResUtil.getString(R.string.avroom_widget_messageview_0152);
}
if (fromType == AVRoomActivity.FROM_TYPE_USER || fromType == AVRoomActivity.FROM_TYPE_HELLO) {
String finalFromUid = fromUid;
text.append(ResUtil.getString(R.string.avroom_widget_messageview_0153), new ForegroundColorSpan(whiteColor))
.append(fromNick, new ForegroundColorSpan(roomTipColor),
new OriginalDrawStatusClickSpan() {
@Override
public void onClick(@NonNull View view) {
if (clickConsumer != null) {
Single.just(finalFromUid).doOnSuccess(clickConsumer).subscribe();
}
}
});
enterText = ResUtil.getString(R.string.avroom_widget_messageview_0154);
}
if (fromType == AVRoomActivity.FROM_TYPE_GAME_RECOMMEND) {
String finalFromUid = fromUid;
text.append(ResUtil.getString(R.string.avroom_widget_messageview_0155), new ForegroundColorSpan(whiteColor))
.append(fromNick, new ForegroundColorSpan(roomTipColor),
new OriginalDrawStatusClickSpan() {
@Override
public void onClick(@NonNull View view) {
if (clickConsumer != null) {
Single.just(finalFromUid).doOnSuccess(clickConsumer).subscribe();
}
}
});
enterText = ResUtil.getString(R.string.avroom_widget_messageview_0156);
}
text.append(enterText, new ForegroundColorSpan(whiteColor));
tvContent.setText(text.build());
tvContent.setOnClickListener(null);
tvContent.setMovementMethod(new LinkMovementMethod());
}
@Nullable
private Drawable getNewUserDrawable(ChatRoomMessage chatRoomMessage) {
boolean newUser = NobleUtil.getIsNewUser(UserInfo.IS_NEW_USER, chatRoomMessage);
boolean isHelloUser = NobleUtil.getIsNewUser(UserInfo.IS_FROM_SAY_HELLO_CHANNEL, chatRoomMessage);
if (newUser) {
return ResourcesCompat.getDrawable(getResources(),
isHelloUser ? R.drawable.ic_new_user_hello : R.drawable.ic_new_user,
null);
}
return null;
}
@SuppressLint("CheckResult")
@Override
public void onClick(View v) {
String account = "";
ChatRoomMessage chatRoomMessage = (ChatRoomMessage) v.getTag();
if (chatRoomMessage.getMsgType() != MsgTypeEnum.tip) {
if (chatRoomMessage.getMsgType() == MsgTypeEnum.text) {
account = chatRoomMessage.getFromAccount();
} else if (chatRoomMessage.getMsgType() == MsgTypeEnum.notification) {
account = chatRoomMessage.getFromAccount();
} else if (chatRoomMessage.getMsgType() == MsgTypeEnum.custom) {
CustomAttachment attachment = (CustomAttachment) chatRoomMessage.getAttachment();
if (attachment.getFirst() == CustomAttachment.CUSTOM_MSG_HEADER_TYPE_ROOM_TIP) {
account = ((RoomTipAttachment) attachment).getUid() + "";
} else if (attachment.getFirst() == CustomAttachment.CUSTOM_MSG_BOX) {
account = String.valueOf(((RoomBoxPrizeAttachment) attachment).getUid());
} else if (attachment.getFirst() == CustomAttachment.CUSTOM_MSG_HEADER_TYPE_QUEUE) {
long handleUid = ((RoomQueueMsgAttachment) attachment).handleUid;
if (handleUid > 0) {
account = ((RoomQueueMsgAttachment) attachment).handleUid + "";
} else {
//ios沒用handleUid導致iOS發的自定義消息拿不到uid
account = chatRoomMessage.getFromAccount();
}
} else if (attachment.getFirst() == CustomAttachment.CUSTOM_MSG_HEADER_TYPE_MONSTER_HUNTING) {
switch (attachment.getSecond()) {
case CustomAttachment.CUSTOM_MSG_SUB_TYPE_MONSTER_HUNTING:
MonsterDataBean dataBean = ((MonsterStatusAttachment) attachment).getDataBean();
RoomInfo mCurrentRoomInfo = AvRoomDataManager.get().mCurrentRoomInfo;
if (!Objects.equals(mCurrentRoomInfo.getUid(), dataBean.getAppearRoomUid())) {
AVRoomActivity.start(getContext(), dataBean.getAppearRoomUid());
} else {
SingleToastUtil.showToast("你已經在怪獸房間內");
}
break;
case CustomAttachment.CUSTOM_NOTI_SUB_GAME_RESULT:
MonsterHuntingResult result = ((MonsterHuntingResultAttachment) attachment).getResult();
UIHelper.showMonsterResult(getContext(), String.valueOf(result.getMonster().getMonsterId()));
break;
}
} else if (attachment.getFirst() == CustomAttachment.CUSTOM_MESS_HEAD_ROOM_PK) {
if (attachment.getSecond() == CustomAttachment.CUSTOM_MESS_SUB_ROOM_PK_RESULT) {
PKResultDialog pkResultDialog = new PKResultDialog(getContext(), ((RoomPkAttachment) attachment).getRoomPkData());
pkResultDialog.show();
}
} else if (attachment instanceof RoomFollowOwnerAttachment2 && !AvRoomDataManager.get().isRoomFans) {
CollectionRoomModel.get().followRoom("1", ((RoomFollowOwnerAttachment2) attachment).getOwnerUid())
.subscribe(s -> {
AvRoomDataManager.get().isRoomFans = true;
SingleToastUtil.showToast("收藏成功!");
EventBus.getDefault().post(new FollowRoomEvent());
PraiseModel.get().setFollowRoomSuccessRoomTip(JavaUtil.str2long(chatRoomMessage.getFromAccount()));
});
} else if (attachment.getFirst() == CustomAttachment.CUSTOM_MESS_TAROT) {
if (attachment instanceof TarotAttachment) {
account = ((TarotAttachment) attachment).getTarotMsgBean().getUid() + "";
}
}
}
if (TextUtils.isEmpty(account)) return;
if (clickConsumer != null) {
Single.just(account).subscribe(clickConsumer);
}
} else {
String content = chatRoomMessage.getContent();
if (!TextUtils.isEmpty(content) && content.equals(XConstants.ROOM_INTRODUCTION))
if (onClick != null) {
onClick.onShowRoomIntroduction();
}
}
}
class MessageViewHolder extends RecyclerView.ViewHolder {
TextView tvContent;
public MessageViewHolder(View itemView) {
super(itemView);
tvContent = itemView.findViewById(R.id.tv_content);
}
}
}
}

View File

@@ -0,0 +1,102 @@
package com.chwl.app.avroom.public_chat
import android.content.Context
import android.util.AttributeSet
import android.view.ViewGroup
import com.chwl.app.R
import com.chwl.app.public_chat.core.ChatRoomClient
import com.chwl.app.public_chat.core.ChatRoomClientManager
import com.chwl.core.initial.InitialModel
import com.chwl.core.support.room.FrameLayoutRoomWidget
import com.chwl.core.support.room.RoomView
import com.chwl.library.utils.SingleToastUtil
import com.netease.nim.uikit.api.model.NimException
import com.netease.nimlib.sdk.chatroom.model.ChatRoomMessage
import com.netease.nimlib.sdk.msg.constant.MsgTypeEnum
import com.netease.nimlib.sdk.msg.model.QueryDirectionEnum
import java.util.Collections
class PublicChatRoomMessageWidget : FrameLayoutRoomWidget {
private var messageListView: PublicChatMessageView = PublicChatMessageView(context)
private var chatRoomClient: ChatRoomClient? = null
constructor(context: Context) : super(context)
constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)
constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(
context,
attrs,
defStyleAttr
)
constructor(
context: Context,
attrs: AttributeSet?,
defStyleAttr: Int,
defStyleRes: Int
) : super(context, attrs, defStyleAttr, defStyleRes)
init {
addView(
messageListView,
LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)
)
}
override fun onStart(roomView: RoomView) {
super.onStart(roomView)
val sessionId = InitialModel.get().publicChatSessionId
if (sessionId != null) {
chatRoomClient = ChatRoomClientManager.getClient(sessionId);
} else {
SingleToastUtil.showToast(R.string.public_chat_not_found)
}
chatRoomClient?.let {
initChatRoom(it)
}
}
private fun onReceiveMessage(list: List<ChatRoomMessage>) {
messageListView.addMessages(list)
}
private fun initChatRoom(chatRoomClient: ChatRoomClient) {
getCompositeDisposable().add(
chatRoomClient.enterChatRoom()
.subscribe({ requestHistory(chatRoomClient) },
{
if (it is NimException) {
SingleToastUtil.showToast(context.getString(R.string.avroom_fragment_homepartyroomfragment_011) + "(${it.code})")
} else {
SingleToastUtil.showToast(R.string.avroom_fragment_homepartyroomfragment_011)
}
})
)
getCompositeDisposable().add(chatRoomClient.messageObservable.subscribe {
onReceiveMessage(it)
})
}
private fun requestHistory(chatRoomClient: ChatRoomClient) {
val typeEnums = arrayOf(MsgTypeEnum.text, MsgTypeEnum.image)
getCompositeDisposable().add(
chatRoomClient.requestRemoteMessageType(
0,
50,
QueryDirectionEnum.QUERY_OLD,
typeEnums
).subscribe({
messageListView.addHistoryMessages(it.reversed())
}, {
it.printStackTrace()
})
)
}
override fun onStop() {
super.onStop()
chatRoomClient = null
}
}

View File

@@ -115,17 +115,35 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_alignParentBottom="true" /> android:layout_alignParentBottom="true" />
<com.chwl.app.avroom.widget.MessageView <com.chwl.app.ui.widget.magicindicator.MagicIndicator
android:id="@+id/message_view" android:id="@+id/message_indicator"
android:layout_width="wrap_content"
android:layout_height="@dimen/dp_44"
android:layout_below="@id/micro_view"
android:layout_marginTop="@dimen/dp_5" />
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/message_pager"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:layout_above="@id/bottom_view" android:layout_above="@id/bottom_view"
android:layout_below="@id/micro_view" android:layout_below="@id/message_indicator"
android:layout_marginStart="12dp" android:layout_marginStart="12dp"
android:layout_marginTop="@dimen/dp_5"
android:layout_marginEnd="90dp" android:layout_marginEnd="90dp"
android:layout_marginBottom="@dimen/dp_10" /> android:layout_marginBottom="@dimen/dp_10" />
<!-- <com.chwl.app.avroom.widget.MessageView-->
<!-- android:visibility="gone"-->
<!-- android:id="@+id/message_view"-->
<!-- android:layout_width="match_parent"-->
<!-- android:layout_height="match_parent"-->
<!-- android:layout_above="@id/bottom_view"-->
<!-- android:layout_below="@id/micro_view"-->
<!-- android:layout_marginStart="12dp"-->
<!-- android:layout_marginTop="@dimen/dp_5"-->
<!-- android:layout_marginEnd="90dp"-->
<!-- android:layout_marginBottom="@dimen/dp_10" />-->
<com.coorchice.library.SuperTextView <com.coorchice.library.SuperTextView
android:id="@+id/tv_dating_next" android:id="@+id/tv_dating_next"
android:layout_width="wrap_content" android:layout_width="wrap_content"

View File

@@ -725,4 +725,6 @@
<color name="color_FFF45E">#FFF45E</color> <color name="color_FFF45E">#FFF45E</color>
<color name="color_FFE44E">#FFE44E</color> <color name="color_FFE44E">#FFE44E</color>
<color name="color_10ECD6">#10ECD6</color>
<color name="color_4D415E">#4D415E</color>
</resources> </resources>

View File

@@ -1,5 +1,7 @@
package com.chwl.app.public_chat.core package com.chwl.app.public_chat.core
import com.chwl.core.user.UserModel
import com.chwl.core.utils.ExtensionUtils
import com.chwl.core.utils.net.RxHelper import com.chwl.core.utils.net.RxHelper
import com.example.lib_utils.ICleared import com.example.lib_utils.ICleared
import com.example.lib_utils.log.ILog import com.example.lib_utils.log.ILog
@@ -14,6 +16,8 @@ import com.netease.nimlib.sdk.chatroom.model.ChatRoomMessage
import com.netease.nimlib.sdk.chatroom.model.ChatRoomStatusChangeData import com.netease.nimlib.sdk.chatroom.model.ChatRoomStatusChangeData
import com.netease.nimlib.sdk.chatroom.model.EnterChatRoomData import com.netease.nimlib.sdk.chatroom.model.EnterChatRoomData
import com.netease.nimlib.sdk.chatroom.model.EnterChatRoomResultData import com.netease.nimlib.sdk.chatroom.model.EnterChatRoomResultData
import com.netease.nimlib.sdk.msg.constant.MsgTypeEnum
import com.netease.nimlib.sdk.msg.model.QueryDirectionEnum
import io.reactivex.BackpressureStrategy import io.reactivex.BackpressureStrategy
import io.reactivex.Observable import io.reactivex.Observable
import io.reactivex.Single import io.reactivex.Single
@@ -25,7 +29,8 @@ open class ChatRoomClient(val sessionId: String) : ICleared, ILog {
private var isLogin = false private var isLogin = false
private var loginData: EnterChatRoomResultData? = null private var loginData: EnterChatRoomResultData? = null
private val messagePublishSubject: PublishSubject<List<ChatRoomMessage>> = PublishSubject.create() private val messagePublishSubject: PublishSubject<List<ChatRoomMessage>> =
PublishSubject.create()
val messageObservable: Observable<List<ChatRoomMessage>> = messagePublishSubject val messageObservable: Observable<List<ChatRoomMessage>> = messagePublishSubject
.toFlowable(BackpressureStrategy.BUFFER) .toFlowable(BackpressureStrategy.BUFFER)
.toObservable() .toObservable()
@@ -90,6 +95,13 @@ open class ChatRoomClient(val sessionId: String) : ICleared, ILog {
} }
fun sendMessage(message: ChatRoomMessage): Single<Any> { fun sendMessage(message: ChatRoomMessage): Single<Any> {
val map: Map<String?, Any?> = message.localExtension ?: HashMap()
val userInfo = UserModel.get().cacheLoginUserInfo
if (userInfo != null) {
ExtensionUtils.setupExtension(map, userInfo)
}
message.localExtension = map
message.remoteExtension = map
return Single.create<Any> { return Single.create<Any> {
logD("sendMessage() message:${message}") logD("sendMessage() message:${message}")
NIMClient.getService<ChatRoomService>(ChatRoomService::class.java) NIMClient.getService<ChatRoomService>(ChatRoomService::class.java)
@@ -124,6 +136,36 @@ open class ChatRoomClient(val sessionId: String) : ICleared, ILog {
.observeOnlineStatus(onlineStatusObserver, register) .observeOnlineStatus(onlineStatusObserver, register)
} }
fun requestRemoteMessageType(
startTime: Long,
count: Int,
direction: QueryDirectionEnum,
typeEnums: Array<MsgTypeEnum>
): Single<List<ChatRoomMessage>> {
return Single.create<List<ChatRoomMessage>> {
NIMClient.getService<ChatRoomService>(ChatRoomService::class.java)
.pullMessageHistoryExType(
sessionId,
startTime,
count,
direction,
typeEnums
).setCallback(object : RequestCallback<List<ChatRoomMessage>> {
override fun onSuccess(param: List<ChatRoomMessage>?) {
it.onSuccess(param ?: emptyList())
}
override fun onFailed(code: Int) {
it.onError(NimException(code))
}
override fun onException(exception: Throwable) {
it.onError(exception)
}
})
}.compose(RxHelper.handleSchedulers())
}
override fun onCleared() { override fun onCleared() {
super.onCleared() super.onCleared()
ChatRoomClientManager.onClientCleared(this) ChatRoomClientManager.onClientCleared(this)

View File

@@ -218,9 +218,9 @@ public class ChatRoomMessageAdapter extends BaseMultiItemFetchLoadAdapter<ChatRo
} }
private boolean hideTimeAlways(IMMessage message) { private boolean hideTimeAlways(IMMessage message) {
if (message.getSessionType() == SessionTypeEnum.ChatRoom) { // if (message.getSessionType() == SessionTypeEnum.ChatRoom) {
return true; // return true;
} // }
switch (message.getMsgType()) { switch (message.getMsgType()) {
case notification: case notification:
return true; return true;

View File

@@ -24,9 +24,8 @@ class PublicChatRoomMessageActivity : BaseBindingActivity<PublicChatMessageActiv
companion object { companion object {
fun start(context: Context): Boolean { fun start(context: Context): Boolean {
val partitionId = UserModel.get().partitionId.toString()
val sessionId = val sessionId =
InitialModel.get().cacheInitInfo?.publicChatRoomIdMap?.get(partitionId) InitialModel.get().publicChatSessionId
if (sessionId.isNullOrEmpty()) { if (sessionId.isNullOrEmpty()) {
SingleToastUtil.showToast(R.string.public_chat_not_found) SingleToastUtil.showToast(R.string.public_chat_not_found)
return false return false

View File

@@ -48,4 +48,6 @@ public interface IInitialModel extends IModel {
FairyOpenInfo getFairyOpenInfo(); FairyOpenInfo getFairyOpenInfo();
void regionCheck(); void regionCheck();
String getPublicChatSessionId();
} }

View File

@@ -53,6 +53,7 @@ import java.io.File;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import io.reactivex.Observable; import io.reactivex.Observable;
@@ -482,6 +483,19 @@ public class InitialModel extends BaseModel implements IInitialModel {
return fairyOpenInfo; return fairyOpenInfo;
} }
@Override
public String getPublicChatSessionId() {
long partitionId = UserModel.get().getPartitionId();
if (cacheInitInfo == null) {
return null;
}
Map<String, String> idMap = cacheInitInfo.getPublicChatRoomIdMap();
if (idMap == null) {
return null;
}
return idMap.get(partitionId + "");
}
private interface Api { private interface Api {
/** /**
* 客户端初始化 * 客户端初始化

View File

@@ -19,6 +19,7 @@ import androidx.annotation.Nullable;
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONObject;
import com.chwl.core.gift.bean.GiftType; import com.chwl.core.gift.bean.GiftType;
import com.chwl.core.initial.InitialModel;
import com.chwl.core.monsterhunting.bean.MonsterDataBean; import com.chwl.core.monsterhunting.bean.MonsterDataBean;
import com.google.gson.Gson; import com.google.gson.Gson;
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
@@ -619,6 +620,9 @@ public final class IMNetEaseManager {
if (Objects.equals(sessionId, String.valueOf(PublicChatHallDataManager.get().getPublicChatHallId()))) { if (Objects.equals(sessionId, String.valueOf(PublicChatHallDataManager.get().getPublicChatHallId()))) {
return true; return true;
} }
if (Objects.equals(sessionId, InitialModel.get().getPublicChatSessionId())) {
return true;
}
RoomInfo currentRoomInfo = AvRoomDataManager.get().mCurrentRoomInfo; RoomInfo currentRoomInfo = AvRoomDataManager.get().mCurrentRoomInfo;
if (currentRoomInfo == null) { if (currentRoomInfo == null) {
return false; return false;

View File

@@ -41,6 +41,8 @@ public class UserInfo implements Serializable {
public static String IS_NEW_USER = "newUser"; public static String IS_NEW_USER = "newUser";
public static String IS_FROM_SAY_HELLO_CHANNEL = "fromSayHelloChannel"; public static String IS_FROM_SAY_HELLO_CHANNEL = "fromSayHelloChannel";
public static String GENDER = "gender"; public static String GENDER = "gender";
public static String NICK = "nick";
public static String AVATAR = "avatar";
public static String IS_OFFICIAL = "official"; public static String IS_OFFICIAL = "official";
public static String DEF_USER = "defUser"; public static String DEF_USER = "defUser";
public static String HAS_PRETTY = "hasPrettyErbanNo"; public static String HAS_PRETTY = "hasPrettyErbanNo";
@@ -662,6 +664,8 @@ public class UserInfo implements Serializable {
if (map == null) { if (map == null) {
map = new HashMap<>(); map = new HashMap<>();
} }
map.put(NICK, userInfo.getNick());
map.put(AVATAR, userInfo.getNewAvatar());
map.put(GENDER, userInfo.getGender()); map.put(GENDER, userInfo.getGender());
map.put(IS_OFFICIAL, userInfo.getDefUser() == USER_TYPE_OFFICIAL); map.put(IS_OFFICIAL, userInfo.getDefUser() == USER_TYPE_OFFICIAL);
map.put(IS_NEW_USER, isNewUser()); map.put(IS_NEW_USER, isNewUser());