package com.lqr.wechat.ui.presenter;
import android.content.Intent;
import android.graphics.drawable.AnimationDrawable;
import android.net.Uri;
import android.text.TextUtils;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import com.lqr.audio.AudioPlayManager;
import com.lqr.audio.IAudioPlayListener;
import com.lqr.wechat.R;
import com.lqr.wechat.db.DBManager;
import com.lqr.wechat.db.model.GroupMember;
import com.lqr.wechat.model.cache.UserCache;
import com.lqr.wechat.model.data.LocationData;
import com.lqr.wechat.model.message.RedPacketMessage;
import com.lqr.wechat.ui.activity.SessionActivity;
import com.lqr.wechat.ui.activity.ShowBigImageActivity;
import com.lqr.wechat.ui.adapter.SessionAdapter;
import com.lqr.wechat.ui.base.BaseFragmentActivity;
import com.lqr.wechat.ui.base.BaseFragmentPresenter;
import com.lqr.wechat.ui.view.ISessionAtView;
import com.lqr.wechat.util.FileOpenUtils;
import com.lqr.wechat.util.LogUtils;
import com.lqr.wechat.util.MediaFileUtils;
import com.lqr.wechat.util.RedPacketUtil;
import com.lqr.wechat.util.UIUtils;
import com.lqr.wechat.widget.CustomDialog;
import com.yunzhanghu.redpacketsdk.RPSendPacketCallback;
import com.yunzhanghu.redpacketsdk.bean.RedPacketInfo;
import com.yunzhanghu.redpacketsdk.constant.RPConstant;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import io.rong.imlib.IRongCallback;
import io.rong.imlib.RongIMClient;
import io.rong.imlib.model.Conversation;
import io.rong.imlib.model.Message;
import io.rong.imlib.model.MessageContent;
import io.rong.imlib.model.UserInfo;
import io.rong.message.FileMessage;
import io.rong.message.GroupNotificationMessage;
import io.rong.message.ImageMessage;
import io.rong.message.LocationMessage;
import io.rong.message.RecallNotificationMessage;
import io.rong.message.TextMessage;
import io.rong.message.VoiceMessage;
import rx.Observable;
import rx.android.schedulers.AndroidSchedulers;
import rx.schedulers.Schedulers;
public class SessionAtPresenter extends BaseFragmentPresenter<ISessionAtView> {
public Conversation.ConversationType mConversationType;
private String mSessionId;
private String mPushCotent = "";//接收方离线时需要显示的push消息内容。
private String mPushData = "";//接收方离线时需要在push消息中携带的非显示内容。
private int mMessageCount = 5;//一次获取历史消息的最大数量
private List<Message> mData = new ArrayList<>();
private SessionAdapter mAdapter;
private CustomDialog mSessionMenuDialog;
public SessionAtPresenter(BaseFragmentActivity context, String sessionId, Conversation.ConversationType conversationType) {
super(context);
mSessionId = sessionId;
mConversationType = conversationType;
}
public void loadMessage() {
loadData();
setAdapter();
}
private void loadData() {
getLocalHistoryMessage();
setAdapter();
}
public void loadMore() {
getLocalHistoryMessage();
mAdapter.notifyDataSetChangedWrapper();
}
public void receiveNewMessage(Message message) {
mData.add(message);
setAdapter();
RongIMClient.getInstance().clearMessagesUnreadStatus(mConversationType, mSessionId);
}
public void resetDraft() {
Observable.just(RongIMClient.getInstance().getTextMessageDraft(mConversationType, mSessionId))
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(s -> {
if (!TextUtils.isEmpty(s)) {
getView().getEtContent().setText(s);
RongIMClient.getInstance().clearTextMessageDraft(mConversationType, mSessionId);
}
}, this::loadError);
}
public void saveDraft() {
String draft = getView().getEtContent().getText().toString();
if (!TextUtils.isEmpty(draft)) {
RongIMClient.getInstance().saveTextMessageDraft(mConversationType, mSessionId, draft);
}
}
public void setAdapter() {
if (mAdapter == null) {
mAdapter = new SessionAdapter(mContext, mData, this);
mAdapter.setOnItemClickListener((helper, parent, itemView, position) -> {
Message message = mData.get(position);
MessageContent content = message.getContent();
if (content instanceof ImageMessage) {
ImageMessage imageMessage = (ImageMessage) content;
Intent intent = new Intent(mContext, ShowBigImageActivity.class);
intent.putExtra("url", imageMessage.getLocalUri() == null ? imageMessage.getRemoteUri().toString() : imageMessage.getLocalUri().toString());
mContext.jumpToActivity(intent);
} else if (content instanceof FileMessage) {
FileMessage fileMessage = (FileMessage) content;
if (MediaFileUtils.isVideoFileType(fileMessage.getName())) {
helper.getView(R.id.bivPic).setOnClickListener(v -> {
boolean isSend = message.getMessageDirection() == Message.MessageDirection.SEND ? true : false;
if (isSend) {
if (fileMessage.getLocalPath() != null && new File(fileMessage.getLocalPath().getPath()).exists()) {
FileOpenUtils.openFile(mContext, fileMessage.getLocalPath().getPath());
} else {
downloadMediaMessage(message);
}
} else {
Message.ReceivedStatus receivedStatus = message.getReceivedStatus();
if (receivedStatus.isDownload() || receivedStatus.isRetrieved()) {
if (fileMessage.getLocalPath() != null) {
FileOpenUtils.openFile(mContext, fileMessage.getLocalPath().getPath());
} else {
UIUtils.showToast(UIUtils.getString(R.string.file_out_of_date));
}
} else {
downloadMediaMessage(message);
}
}
});
}
} else if (content instanceof VoiceMessage) {
VoiceMessage voiceMessage = (VoiceMessage) content;
final ImageView ivAudio = helper.getView(R.id.ivAudio);
AudioPlayManager.getInstance().startPlay(mContext, voiceMessage.getUri(), new IAudioPlayListener() {
@Override
public void onStart(Uri var1) {
if (ivAudio != null && ivAudio.getBackground() instanceof AnimationDrawable) {
AnimationDrawable animation = (AnimationDrawable) ivAudio.getBackground();
animation.start();
}
}
@Override
public void onStop(Uri var1) {
if (ivAudio != null && ivAudio.getBackground() instanceof AnimationDrawable) {
AnimationDrawable animation = (AnimationDrawable) ivAudio.getBackground();
animation.stop();
animation.selectDrawable(0);
}
}
@Override
public void onComplete(Uri var1) {
if (ivAudio != null && ivAudio.getBackground() instanceof AnimationDrawable) {
AnimationDrawable animation = (AnimationDrawable) ivAudio.getBackground();
animation.stop();
animation.selectDrawable(0);
}
}
});
} else if (content instanceof RedPacketMessage) {
RedPacketMessage redPacketMessage = (RedPacketMessage) content;
int chatType = mConversationType == Conversation.ConversationType.PRIVATE ? RPConstant.RP_ITEM_TYPE_SINGLE : RPConstant.RP_ITEM_TYPE_GROUP;
String redPacketId = redPacketMessage.getBribery_ID();
String redPacketType = redPacketMessage.getBribery_Message();
String receiverId = UserCache.getId();
String direct = RPConstant.MESSAGE_DIRECT_RECEIVE;
RedPacketUtil.openRedPacket(((SessionActivity) mContext), chatType, redPacketId, redPacketType, receiverId, direct);
}
});
getView().getRvMsg().setAdapter(mAdapter);
mAdapter.setOnItemLongClickListener((helper, viewGroup, view, position) -> {
View sessionMenuView = View.inflate(mContext, R.layout.dialog_session_menu, null);
mSessionMenuDialog = new CustomDialog(mContext, sessionMenuView, R.style.MyDialog);
TextView tvReCall = (TextView) sessionMenuView.findViewById(R.id.tvReCall);
TextView tvDelete = (TextView) sessionMenuView.findViewById(R.id.tvDelete);
//根据消息类型控制显隐
Message message = mData.get(position);
MessageContent content = message.getContent();
if (content instanceof GroupNotificationMessage || content instanceof RecallNotificationMessage) {
return false;
}
if (content instanceof RedPacketMessage || !message.getSenderUserId().equalsIgnoreCase(UserCache.getId())) {
tvReCall.setVisibility(View.GONE);
}
tvReCall.setOnClickListener(v -> RongIMClient.getInstance().recallMessage(message, "", new RongIMClient.ResultCallback<RecallNotificationMessage>() {
@Override
public void onSuccess(RecallNotificationMessage recallNotificationMessage) {
UIUtils.postTaskSafely(() -> {
recallMessageAndInsertMessage(recallNotificationMessage, position);
mSessionMenuDialog.dismiss();
mSessionMenuDialog = null;
UIUtils.showToast(UIUtils.getString(R.string.recall_success));
});
}
@Override
public void onError(RongIMClient.ErrorCode errorCode) {
UIUtils.postTaskSafely(() -> {
mSessionMenuDialog.dismiss();
mSessionMenuDialog = null;
UIUtils.showToast(UIUtils.getString(R.string.recall_fail) + ":" + errorCode.getValue());
});
}
}));
tvDelete.setOnClickListener(v -> RongIMClient.getInstance().deleteMessages(new int[]{message.getMessageId()}, new RongIMClient.ResultCallback<Boolean>() {
@Override
public void onSuccess(Boolean aBoolean) {
UIUtils.postTaskSafely(() -> {
mSessionMenuDialog.dismiss();
mSessionMenuDialog = null;
mData.remove(position);
mAdapter.notifyDataSetChangedWrapper();
UIUtils.showToast(UIUtils.getString(R.string.delete_success));
});
}
@Override
public void onError(RongIMClient.ErrorCode errorCode) {
UIUtils.postTaskSafely(() -> {
mSessionMenuDialog.dismiss();
mSessionMenuDialog = null;
UIUtils.showToast(UIUtils.getString(R.string.delete_fail) + ":" + errorCode.getValue());
});
}
}));
mSessionMenuDialog.show();
return false;
});
UIUtils.postTaskDelay(() -> getView().getRvMsg().smoothMoveToPosition(mData.size() - 1), 200);
} else {
mAdapter.notifyDataSetChangedWrapper();
if (getView() != null && getView().getRvMsg() != null)
rvMoveToBottom();
}
}
private void rvMoveToBottom() {
getView().getRvMsg().smoothMoveToPosition(mData.size() - 1);
}
private void updateMessageStatus(Message message) {
for (int i = 0; i < mData.size(); i++) {
Message msg = mData.get(i);
if (msg.getMessageId() == message.getMessageId()) {
mData.remove(i);
mData.add(i, message);
mAdapter.notifyDataSetChangedWrapper();
break;
}
}
}
private void updateMessageStatus(int messageId) {
RongIMClient.getInstance().getMessage(messageId, new RongIMClient.ResultCallback<Message>() {
@Override
public void onSuccess(Message message) {
for (int i = 0; i < mData.size(); i++) {
Message msg = mData.get(i);
if (msg.getMessageId() == message.getMessageId()) {
mData.remove(i);
mData.add(i, message);
mAdapter.notifyDataSetChangedWrapper();
break;
}
}
}
@Override
public void onError(RongIMClient.ErrorCode errorCode) {
}
});
}
public void sendTextMsg() {
sendTextMsg(getView().getEtContent().getText().toString());
getView().getEtContent().setText("");
}
public void sendTextMsg(String content) {
RongIMClient.getInstance().sendMessage(mConversationType, mSessionId, TextMessage.obtain(content), mPushCotent, mPushData,
new RongIMClient.SendMessageCallback() {// 发送消息的回调
@Override
public void onError(Integer integer, RongIMClient.ErrorCode errorCode) {
updateMessageStatus(integer);
}
@Override
public void onSuccess(Integer integer) {
updateMessageStatus(integer);
}
}, new RongIMClient.ResultCallback<Message>() {//消息存库的回调,可用于获取消息实体
@Override
public void onSuccess(Message message) {
mAdapter.addLastItem(message);
rvMoveToBottom();
}
@Override
public void onError(RongIMClient.ErrorCode errorCode) {
}
});
}
public void sendImgMsg(Uri imageFileThumbUri, Uri imageFileSourceUri) {
ImageMessage imgMsg = ImageMessage.obtain(imageFileThumbUri, imageFileSourceUri);
RongIMClient.getInstance().sendImageMessage(mConversationType, mSessionId, imgMsg, mPushCotent, mPushData,
new RongIMClient.SendImageMessageCallback() {
@Override
public void onAttached(Message message) {
//保存数据库成功
mAdapter.addLastItem(message);
rvMoveToBottom();
}
@Override
public void onError(Message message, RongIMClient.ErrorCode errorCode) {
//发送失败
updateMessageStatus(message);
}
@Override
public void onSuccess(Message message) {
//发送成功
updateMessageStatus(message);
}
@Override
public void onProgress(Message message, int progress) {
//发送进度
message.setExtra(progress + "");
updateMessageStatus(message);
}
});
}
public void sendImgMsg(File imageFileThumb, File imageFileSource) {
Uri imageFileThumbUri = Uri.fromFile(imageFileThumb);
Uri imageFileSourceUri = Uri.fromFile(imageFileSource);
sendImgMsg(imageFileThumbUri, imageFileSourceUri);
}
public void sendFileMsg(File file) {
Message fileMessage = Message.obtain(mSessionId, mConversationType, FileMessage.obtain(Uri.fromFile(file)));
RongIMClient.getInstance().sendMediaMessage(fileMessage, mPushCotent, mPushData, new IRongCallback.ISendMediaMessageCallback() {
@Override
public void onProgress(Message message, int progress) {
//发送进度
message.setExtra(progress + "");
updateMessageStatus(message);
}
@Override
public void onCanceled(Message message) {
}
@Override
public void onAttached(Message message) {
//保存数据库成功
mAdapter.addLastItem(message);
rvMoveToBottom();
}
@Override
public void onSuccess(Message message) {
//发送成功
updateMessageStatus(message);
}
@Override
public void onError(Message message, RongIMClient.ErrorCode errorCode) {
//发送失败
updateMessageStatus(message);
}
});
}
public void sendLocationMessage(LocationData locationData) {
LocationMessage message = LocationMessage.obtain(locationData.getLat(), locationData.getLng(), locationData.getPoi(), Uri.parse(locationData.getImgUrl()));
RongIMClient.getInstance().sendLocationMessage(Message.obtain(mSessionId, mConversationType, message), mPushCotent, mPushData, new IRongCallback.ISendMessageCallback() {
@Override
public void onAttached(Message message) {
//保存数据库成功
mAdapter.addLastItem(message);
rvMoveToBottom();
}
@Override
public void onSuccess(Message message) {
//发送成功
updateMessageStatus(message);
}
@Override
public void onError(Message message, RongIMClient.ErrorCode errorCode) {
//发送失败
updateMessageStatus(message);
}
});
}
public void sendAudioFile(Uri audioPath, int duration) {
if (audioPath != null) {
File file = new File(audioPath.getPath());
if (!file.exists() || file.length() == 0L) {
LogUtils.sf(UIUtils.getString(R.string.send_audio_fail));
return;
}
VoiceMessage voiceMessage = VoiceMessage.obtain(audioPath, duration);
RongIMClient.getInstance().sendMessage(Message.obtain(mSessionId, mConversationType, voiceMessage), mPushCotent, mPushData, new IRongCallback.ISendMessageCallback() {
@Override
public void onAttached(Message message) {
//保存数据库成功
mAdapter.addLastItem(message);
rvMoveToBottom();
}
@Override
public void onSuccess(Message message) {
//发送成功
updateMessageStatus(message);
}
@Override
public void onError(Message message, RongIMClient.ErrorCode errorCode) {
//发送失败
updateMessageStatus(message);
}
});
}
}
public void sendRedPacketMsg() {
if (mConversationType == Conversation.ConversationType.PRIVATE) {
UserInfo userInfo = DBManager.getInstance().getUserInfo(mSessionId);
if (userInfo != null)
RedPacketUtil.startRedPacket(mContext, userInfo, RPSendPacketCallback);
} else {
List<GroupMember> groupMembers = DBManager.getInstance().getGroupMembers(mSessionId);
if (groupMembers != null)
RedPacketUtil.startRedPacket(mContext, mSessionId, groupMembers.size(), RPSendPacketCallback);
}
}
RPSendPacketCallback RPSendPacketCallback = new RPSendPacketCallback() {
@Override
public void onGenerateRedPacketId(String redPacketId) {
}
@Override
public void onSendPacketSuccess(RedPacketInfo redPacketInfo) {
RedPacketMessage rpMsg = RedPacketMessage.obtain(redPacketInfo.redPacketId, redPacketInfo.fromNickName, redPacketInfo.redPacketType, redPacketInfo.redPacketGreeting);
RongIMClient.getInstance().sendMessage(Message.obtain(mSessionId, mConversationType, rpMsg), mPushCotent, mPushData, new IRongCallback.ISendMessageCallback() {
@Override
public void onAttached(Message message) {
//保存数据库成功
mAdapter.addLastItem(message);
rvMoveToBottom();
}
@Override
public void onSuccess(Message message) {
//发送成功
updateMessageStatus(message);
}
@Override
public void onError(Message message, RongIMClient.ErrorCode errorCode) {
//发送失败
updateMessageStatus(message);
}
});
}
};
public void downloadMediaMessage(Message message) {
RongIMClient.getInstance().downloadMediaMessage(message, new IRongCallback.IDownloadMediaMessageCallback() {
@Override
public void onSuccess(Message message) {
message.getReceivedStatus().setDownload();
updateMessageStatus(message);
}
@Override
public void onProgress(Message message, int progress) {
//发送进度
message.setExtra(progress + "");
updateMessageStatus(message);
}
@Override
public void onError(Message message, RongIMClient.ErrorCode errorCode) {
updateMessageStatus(message);
}
@Override
public void onCanceled(Message message) {
updateMessageStatus(message);
}
});
}
//获取会话中,从指定消息之前、指定数量的最新消息实体
public void getLocalHistoryMessage() {
//没有消息第一次调用应设置为:-1。
int messageId = -1;
if (mData.size() > 0) {
messageId = mData.get(0).getMessageId();
} else {
messageId = -1;
}
RongIMClient.getInstance().getHistoryMessages(mConversationType, mSessionId, messageId, mMessageCount, new RongIMClient.ResultCallback<List<Message>>() {
@Override
public void onSuccess(List<Message> messages) {
getView().getRefreshLayout().endRefreshing();
if (messages == null || messages.size() == 0)
getRemoteHistoryMessages();
else
saveHistoryMsg(messages);
}
@Override
public void onError(RongIMClient.ErrorCode errorCode) {
getView().getRefreshLayout().endRefreshing();
loadMessageError(errorCode);
}
});
}
//单聊、群聊、讨论组、客服的历史消息从远端获取
public void getRemoteHistoryMessages() {
//消息中的 sentTime;第一次可传 0,获取最新 count 条。
long dateTime = 0;
if (mData.size() > 0) {
dateTime = mData.get(0).getSentTime();
} else {
dateTime = 0;
}
RongIMClient.getInstance().getRemoteHistoryMessages(mConversationType, mSessionId, dateTime, mMessageCount,
new RongIMClient.ResultCallback<List<Message>>() {
@Override
public void onSuccess(List<Message> messages) {
saveHistoryMsg(messages);
}
@Override
public void onError(RongIMClient.ErrorCode errorCode) {
loadMessageError(errorCode);
}
});
}
private void saveHistoryMsg(List<Message> messages) {
//messages的时间顺序从新到旧排列,所以必须反过来加入到mData中
if (messages != null && messages.size() > 0) {
for (Message msg : messages) {
mData.add(0, msg);
}
getView().getRvMsg().moveToPosition(messages.size() - 1);
}
}
private void loadMessageError(RongIMClient.ErrorCode errorCode) {
LogUtils.sf("拉取历史消息失败,errorCode = " + errorCode);
}
private void loadError(Throwable throwable) {
LogUtils.sf(throwable.getLocalizedMessage());
}
public void recallMessageFromListener(int messageId, RecallNotificationMessage recallNotificationMessage) {
for (int i = 0; i < mData.size(); i++) {
Message message = mData.get(i);
if (message.getMessageId() == messageId) {
recallMessageAndInsertMessage(recallNotificationMessage, i);
break;
}
}
}
private void recallMessageAndInsertMessage(RecallNotificationMessage recallNotificationMessage, int position) {
RongIMClient.getInstance().insertMessage(mConversationType, mSessionId, UserCache.getId(), recallNotificationMessage);
mData.remove(position);
mData.add(Message.obtain(mSessionId, mConversationType, recallNotificationMessage));
mAdapter.notifyDataSetChangedWrapper();
}
}