diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 3ffec60fd..27378fcba 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -676,7 +676,6 @@ android:label="单聊界面" android:launchMode="singleTop" android:screenOrientation="portrait" - android:theme="@style/AppTheme.NoActionBar" android:windowSoftInputMode="stateHidden|adjustResize" /> + android:theme="@style/room_message_activity" + android:windowSoftInputMode="stateHidden|adjustResize" /> + android:theme="@style/room_message_activity" + android:windowSoftInputMode="stateHidden|adjustNothing" /> diff --git a/app/src/main/java/com/mango/moshen/ui/im/AutoHidePanelRecyclerView.java b/app/src/main/java/com/mango/moshen/ui/im/AutoHidePanelRecyclerView.java new file mode 100644 index 000000000..fd2abc7dc --- /dev/null +++ b/app/src/main/java/com/mango/moshen/ui/im/AutoHidePanelRecyclerView.java @@ -0,0 +1,44 @@ +package com.mango.moshen.ui.im; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.MotionEvent; + +import androidx.annotation.Nullable; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import com.effective.android.panel.PanelSwitchHelper; + +public class AutoHidePanelRecyclerView extends RecyclerView { + + PanelSwitchHelper panelSwitchHelper; + + public void setPanelSwitchHelper(PanelSwitchHelper panelSwitchHelper) { + this.panelSwitchHelper = panelSwitchHelper; + } + + public AutoHidePanelRecyclerView(Context context) { + this(context, null); + } + + public AutoHidePanelRecyclerView(Context context, @Nullable AttributeSet attrs) { + this(context, attrs, 0); + } + + + public AutoHidePanelRecyclerView(Context context, @Nullable AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + setLayoutManager(new LinearLayoutManager(context)); + } + + @Override + public boolean onTouchEvent(MotionEvent e) { + if (e != null && e.getAction() != MotionEvent.ACTION_CANCEL) { + if (panelSwitchHelper != null) { + panelSwitchHelper.hookSystemBackByPanelSwitcher(); + } + } + return super.onTouchEvent(e); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/mango/moshen/ui/im/ImInitHelper.java b/app/src/main/java/com/mango/moshen/ui/im/ImInitHelper.java index f89b44fdc..98dea393c 100644 --- a/app/src/main/java/com/mango/moshen/ui/im/ImInitHelper.java +++ b/app/src/main/java/com/mango/moshen/ui/im/ImInitHelper.java @@ -7,7 +7,9 @@ import com.netease.nim.uikit.api.model.contact.ContactEventListener; import com.netease.nim.uikit.api.model.session.SessionCustomization; import com.netease.nim.uikit.api.model.session.SessionEventListener; import com.netease.nim.uikit.business.session.actions.BaseAction; +import com.netease.nim.uikit.business.session.actions.CameraAction; import com.netease.nim.uikit.business.session.actions.ImageAction; +import com.netease.nim.uikit.business.session.actions.PhotoAction; import com.netease.nimlib.sdk.msg.model.IMMessage; import com.mango.moshen.community.holder.DynamicSysHolder; import com.mango.moshen.community.im.WorldDynamicShareViewHolder; @@ -116,10 +118,11 @@ public class ImInitHelper { private void initP2PSessionCustomization() { SessionCustomization sessionCustomization = new SessionCustomization(); ArrayList actions = new ArrayList<>(); - actions.add(new ImageAction()); + actions.add(new PhotoAction()); + actions.add(new CameraAction()); actions.add(new GiftAction()); sessionCustomization.actions = actions; - sessionCustomization.withSticker = true; + sessionCustomization.withSticker = false; NimUIKit.setCommonP2PSessionCustomization(sessionCustomization); // 语音派对 diff --git a/app/src/main/java/com/mango/moshen/ui/im/InputPanel.java b/app/src/main/java/com/mango/moshen/ui/im/InputPanel.java new file mode 100644 index 000000000..201bc642e --- /dev/null +++ b/app/src/main/java/com/mango/moshen/ui/im/InputPanel.java @@ -0,0 +1,878 @@ +package com.mango.moshen.ui.im; + +import android.annotation.SuppressLint; +import android.app.Activity; +import android.content.Context; +import android.content.Intent; +import android.graphics.Color; +import android.os.Handler; +import android.os.SystemClock; +import android.text.Editable; +import android.text.InputType; +import android.text.TextUtils; +import android.text.TextWatcher; +import android.util.Log; +import android.view.KeyEvent; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewGroup; +import android.view.WindowManager; +import android.view.inputmethod.EditorInfo; +import android.view.inputmethod.InputMethodManager; +import android.widget.Button; +import android.widget.Chronometer; +import android.widget.EditText; +import android.widget.FrameLayout; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; + +import com.alibaba.fastjson.JSONObject; +import com.effective.android.panel.PanelSwitchHelper; +import com.effective.android.panel.interfaces.PanelHeightMeasurer; +import com.effective.android.panel.interfaces.listener.OnPanelChangeListener; +import com.effective.android.panel.view.panel.IPanelView; +import com.effective.android.panel.view.panel.PanelView; +import com.mango.moshen.R; +import com.mango.moshen.ui.im.actions.GiftAction; +import com.mango.xchat_android_library.utils.SingleToastUtil; +import com.mango.xchat_android_library.utils.SizeUtils; +import com.netease.nim.uikit.api.NimUIKit; +import com.netease.nim.uikit.api.UIKitOptions; +import com.netease.nim.uikit.api.model.session.SessionCustomization; +import com.netease.nim.uikit.business.ait.AitTextChangeListener; +import com.netease.nim.uikit.business.session.actions.BaseAction; +import com.netease.nim.uikit.business.session.actions.CameraAction; +import com.netease.nim.uikit.business.session.actions.PhotoAction; +import com.netease.nim.uikit.business.session.emoji.EmoticonPickerView; +import com.netease.nim.uikit.business.session.emoji.IEmoticonSelectedListener; +import com.netease.nim.uikit.business.session.emoji.MoonUtil; +import com.netease.nim.uikit.business.session.event.ActiveEvent; +import com.netease.nim.uikit.business.session.module.Container; +import com.netease.nim.uikit.business.session.module.input.ActionsPanel; +import com.netease.nim.uikit.business.session.module.input.NimAudioChatEvent; +import com.netease.nim.uikit.common.antispam.AntiSpamEvent; +import com.netease.nim.uikit.common.ui.dialog.EasyAlertDialogHelper; +import com.netease.nim.uikit.common.util.AntiSpamUtil; +import com.netease.nim.uikit.common.util.log.LogUtil; +import com.netease.nim.uikit.common.util.string.StringUtil; +import com.netease.nim.uikit.common.util.sys.ScreenUtil; +import com.netease.nim.uikit.impl.NimUIKitImpl; +import com.netease.nimlib.sdk.NIMClient; +import com.netease.nimlib.sdk.media.record.AudioRecorder; +import com.netease.nimlib.sdk.media.record.IAudioRecordCallback; +import com.netease.nimlib.sdk.media.record.RecordType; +import com.netease.nimlib.sdk.msg.MessageBuilder; +import com.netease.nimlib.sdk.msg.MsgService; +import com.netease.nimlib.sdk.msg.attachment.MsgAttachment; +import com.netease.nimlib.sdk.msg.constant.SessionTypeEnum; +import com.netease.nimlib.sdk.msg.model.CustomNotification; +import com.netease.nimlib.sdk.msg.model.CustomNotificationConfig; +import com.netease.nimlib.sdk.msg.model.IMMessage; + +import org.greenrobot.eventbus.EventBus; + +import java.io.File; +import java.util.List; + +/** + * 底部文本编辑,语音等模块 + * Created by hzxuwen on 2015/6/16. + */ +public class InputPanel implements IEmoticonSelectedListener, IAudioRecordCallback, AitTextChangeListener { + + private static final String TAG = "MsgSendLayout"; + + private static final int SHOW_LAYOUT_DELAY = 0; + + protected Container container; + protected View view; + protected Handler uiHandler; + + protected EditText messageEditText;// 文本消息编辑框 + protected Button audioRecordBtn; // 录音按钮 + protected View audioAnimLayout; // 录音动画布局 + protected FrameLayout textAudioSwitchLayout; // 切换文本,语音按钮布局 + protected View switchToTextButtonInInputBar;// 文本消息选择按钮 + protected View switchToAudioButtonInInputBar;// 语音消息选择按钮 + protected View sendMessageButtonInInputBar;// 发送消息按钮 + protected View emojiButtonInInputBar;// 发送消息按钮 + protected View messageInputBar; + // 表情 + protected EmoticonPickerView emoticonPickerView; // 贴图表情控件 + // 语音 + protected AudioRecorder audioMessageHelper; + private AutoHidePanelRecyclerView messageListView; + private SessionCustomization customization; + private Chronometer time; + private TextView timerTip; + private LinearLayout timerTipContainer; + private boolean started = false; + private boolean cancelled = false; + private boolean touched = false; // 是否按着 + private boolean isKeyboardShowed = true; // 是否显示键盘 + private boolean isTextAudioSwitchShow; // 是否展示左侧语音按钮 + // adapter + private List actions; + // data + private long typingTime = 0; + private TextWatcher aitTextWatcher; + private volatile boolean disable; + private boolean isChat; + private PanelSwitchHelper mHelper; + private final Runnable showTextRunnable = new Runnable() { + @Override + public void run() { + showInputMethod(messageEditText); + } + }; + private ImageView ivImage; + private ImageView ivCamera; + private ImageView ivGift; + /** + * ************************* 键盘布局切换 ******************************* + */ + + private final View.OnClickListener clickListener = new View.OnClickListener() { + + @Override + public void onClick(View v) { + if (v == switchToTextButtonInInputBar) { + switchToTextLayout(true);// 显示文本发送的布局 + } else if (v == sendMessageButtonInInputBar) { + onTextMessageSendButtonPressed(); + } else if (v == switchToAudioButtonInInputBar) { + switchToAudioLayout(); + } else if (v == ivCamera) { + for (BaseAction action : actions) { + if (action instanceof CameraAction) { + action.onClick(); + break; + } + } + mHelper.resetState(); + } else if (v == ivGift) { + + ivGift.postDelayed(() -> { + for (BaseAction action : actions) { + if (action instanceof GiftAction) { + action.onClick(); + break; + } + } + }, !mHelper.isResetState() ? 300 : 0); + mHelper.resetState(); + } else if (v == ivImage) { + for (BaseAction action : actions) { + if (action instanceof PhotoAction) { + action.onClick(); + break; + } + } + mHelper.resetState(); + } + } + }; + + public InputPanel(Container container, View view, List actions, boolean isTextAudioSwitchShow) { + this.container = container; + this.view = view; + this.actions = actions; + this.uiHandler = new Handler(); + this.isTextAudioSwitchShow = isTextAudioSwitchShow; + init(); + } + + public InputPanel(Container container, View view, List actions) { + this(container, view, actions, true); + } + + // 上滑取消录音判断 + private static boolean isCancelled(View view, MotionEvent event) { + int[] location = new int[2]; + view.getLocationOnScreen(location); + + return event.getRawX() < location[0] || event.getRawX() > location[0] + view.getWidth() + || event.getRawY() < location[1] - 40; + } + + public void onPause() { + // 停止录音 + if (audioMessageHelper != null) { + onEndAudioRecord(true); + } + } + + public void onDestroy() { + // release + if (audioMessageHelper != null) { + audioMessageHelper.destroyAudioRecorder(); + } + } + + public boolean collapse(boolean immediately) { + boolean respond = !mHelper.isResetState(); + mHelper.resetState(); + return respond; + } + + public void addAitTextWatcher(TextWatcher watcher) { + aitTextWatcher = watcher; + } + + private void init() { + initViews(); + initInputBarListener(); + initTextEdit(); + initAudioRecordButton(); + restoreText(false); + + for (int i = 0; i < actions.size(); ++i) { + actions.get(i).setIndex(i); + actions.get(i).setContainer(container); + } + + if (disable) { + disableButtons(); + } + if (mHelper == null) { + mHelper = new PanelSwitchHelper.Builder(container.activity) + //可选 + .addKeyboardStateListener((visible, height) -> { + Log.d(TAG, "系统键盘是否可见 : " + visible + " 高度为:" + height); + }) + //可选 + .addEditTextFocusChangeListener((view, hasFocus) -> { + Log.d(TAG, "输入框是否获得焦点 : " + hasFocus); + }) + //可选 + .addViewClickListener(view -> { + if (view == null) return; + if (view.getId() == R.id.emoji_button) { + switchToTextLayout(false); + } + Log.d(TAG, "点击了View : " + view); + }) + //可选 + .addPanelChangeListener(new OnPanelChangeListener() { + + @Override + public void onKeyboard() { + Log.d(TAG, "唤起系统输入法"); + container.proxy.onInputPanelExpand(); + } + + @Override + public void onNone() { + Log.d(TAG, "隐藏所有面板"); + + } + + @Override + public void onPanel(IPanelView view) { + Log.d(TAG, "唤起面板 : " + view); + container.proxy.onInputPanelExpand(); + } + + @Override + public void onPanelSizeChange(IPanelView panelView, boolean portrait, int oldWidth, int oldHeight, int width, int height) { + + } + }) + .addPanelHeightMeasurer(new PanelHeightMeasurer() { + @Override + public boolean synchronizeKeyboardHeight() { + return false; + } + + @Override + public int getTargetPanelDefaultHeight() { + return ScreenUtil.dip2px(200); + } + + @Override + public int getPanelTriggerId() { + return R.id.iv_image; + } + }) + .addPanelHeightMeasurer(new PanelHeightMeasurer() { + @Override + public boolean synchronizeKeyboardHeight() { + return false; + } + + @Override + public int getTargetPanelDefaultHeight() { + return ScreenUtil.dip2px(200); + } + + @Override + public int getPanelTriggerId() { + return R.id.emoji_button; + } + }) + .logTrack(true)//output log + .build(); + + messageListView.setPanelSwitchHelper(mHelper); + } + + } + + public void setCustomization(SessionCustomization customization) { + this.customization = customization; + if (customization != null) { + emoticonPickerView.setWithSticker(customization.withSticker); + } + } + + public void reload(Container container, SessionCustomization customization) { + this.container = container; + setCustomization(customization); + } + + private void initViews() { + messageInputBar = view.findViewById(R.id.textMessageLayout); + switchToTextButtonInInputBar = view.findViewById(R.id.buttonTextMessage); + switchToAudioButtonInInputBar = view.findViewById(R.id.buttonAudioMessage); + emojiButtonInInputBar = view.findViewById(R.id.emoji_button); + sendMessageButtonInInputBar = view.findViewById(R.id.buttonSendMessage); + messageEditText = view.findViewById(R.id.editTextMessage); + + // 语音 + audioRecordBtn = view.findViewById(R.id.audioRecord); + audioAnimLayout = view.findViewById(R.id.layoutPlayAudio); + time = view.findViewById(R.id.timer); + timerTip = view.findViewById(R.id.timer_tip); + timerTipContainer = view.findViewById(R.id.timer_tip_container); + + // 表情 + emoticonPickerView = view.findViewById(R.id.emoticon_picker_view); + emoticonPickerView.show(this); + + // 显示录音按钮 + switchToTextButtonInInputBar.setVisibility(View.GONE); + switchToAudioButtonInInputBar.setVisibility(View.VISIBLE); + + // 文本录音按钮切换布局 + textAudioSwitchLayout = view.findViewById(R.id.switchLayout); + if (isTextAudioSwitchShow) { + textAudioSwitchLayout.setVisibility(View.VISIBLE); + } else { + textAudioSwitchLayout.setVisibility(View.GONE); + } + + messageListView = view.findViewById(R.id.messageListView); + ivImage = view.findViewById(R.id.iv_image); + ivCamera = view.findViewById(R.id.iv_camera); + ivGift = view.findViewById(R.id.iv_gift); + ivCamera.setOnClickListener(clickListener); + ivGift.setOnClickListener(clickListener); + + } + + public void disableButtons() { + if (messageEditText != null && audioRecordBtn != null && + switchToTextButtonInInputBar != null && + switchToAudioButtonInInputBar != null && + emojiButtonInInputBar != null) { + messageEditText.setEnabled(false); + messageEditText.setHint("禁言中,快找管理员解除禁言吧!"); + messageEditText.setHintTextColor(Color.parseColor("#999999")); + audioRecordBtn.setEnabled(false); + switchToTextButtonInInputBar.setEnabled(false); + switchToAudioButtonInInputBar.setEnabled(false); + emojiButtonInInputBar.setEnabled(false); + } else { + setDisable(true); + } + } + + public void setDisable(boolean disable) { + this.disable = disable; + } + + private void initInputBarListener() { + switchToTextButtonInInputBar.setOnClickListener(clickListener); + switchToAudioButtonInInputBar.setOnClickListener(clickListener); + sendMessageButtonInInputBar.setOnClickListener(clickListener); + } + + private void initTextEdit() { + messageEditText.setInputType(InputType.TYPE_CLASS_TEXT); + messageEditText.setImeOptions(EditorInfo.IME_ACTION_SEND); + messageEditText.setOnEditorActionListener((v, actionId, event) -> { + //当actionId == XX_SEND 或者 XX_DONE时都触发 + //或者event.getKeyCode == ENTER 且 event.getAction == ACTION_DOWN时也触发 + //注意,这是一定要判断event != null。因为在某些输入法上会返回null。 + if (actionId == EditorInfo.IME_ACTION_SEND + || actionId == EditorInfo.IME_ACTION_DONE + || (event != null && KeyEvent.KEYCODE_ENTER == event.getKeyCode() && KeyEvent.ACTION_DOWN == event.getAction())) { + //处理事件 + onTextMessageSendButtonPressed(); + return true; + } + return false; + }); + + messageEditText.setOnFocusChangeListener((v, hasFocus) -> { + messageEditText.setHint(""); + checkSendButtonEnable(messageEditText); + }); + + messageEditText.addTextChangedListener(new TextWatcher() { + private int start; + private int count; + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + this.start = start; + this.count = count; + if (aitTextWatcher != null) { + aitTextWatcher.onTextChanged(s, start, before, count); + } + } + + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + if (aitTextWatcher != null) { + aitTextWatcher.beforeTextChanged(s, start, count, after); + } + } + + @Override + public void afterTextChanged(Editable s) { + checkSendButtonEnable(messageEditText); + MoonUtil.replaceEmoticons(container.activity, s, start, count); + + int editEnd = messageEditText.getSelectionEnd(); + messageEditText.removeTextChangedListener(this); + while (StringUtil.counterChars(s.toString()) > NimUIKitImpl.getOptions().maxInputTextLength && editEnd > 0) { + s.delete(editEnd - 1, editEnd); + editEnd--; + } + messageEditText.setSelection(Math.min(s.length(), editEnd)); + messageEditText.addTextChangedListener(this); + + if (aitTextWatcher != null) { + aitTextWatcher.afterTextChanged(s); + } + + sendTypingCommand(); + } + }); + + // 不展示右侧按钮时需要添加edit间距 + if (!isTextAudioSwitchShow) { + try { + ViewGroup.MarginLayoutParams layoutParams = (ViewGroup.MarginLayoutParams) messageEditText.getLayoutParams(); + layoutParams.setMarginStart(SizeUtils.dp2px(view.getContext(), 12)); + messageEditText.requestLayout(); + } catch (Exception ex) { + ex.printStackTrace(); + } + + } + } + + /** + * 发送“正在输入”通知 + */ + private void sendTypingCommand() { + if (container.account.equals(NimUIKit.getAccount())) { + return; + } + + if (container.sessionType == SessionTypeEnum.Team || container.sessionType == SessionTypeEnum.ChatRoom) { + return; + } + + if (System.currentTimeMillis() - typingTime > 5000L) { + typingTime = System.currentTimeMillis(); + CustomNotification command = new CustomNotification(); + command.setSessionId(container.account); + command.setSessionType(container.sessionType); + CustomNotificationConfig config = new CustomNotificationConfig(); + config.enablePush = false; + config.enableUnreadCount = false; + command.setConfig(config); + + JSONObject json = new JSONObject(); + json.put("id", "1"); + command.setContent(json.toString()); + + NIMClient.getService(MsgService.class).sendCustomNotification(command); + } + } + + // 点击edittext,切换键盘和更多布局 + private void switchToTextLayout(boolean needShowInput) { + audioRecordBtn.setVisibility(View.GONE); + messageEditText.setVisibility(View.VISIBLE); + switchToTextButtonInInputBar.setVisibility(View.GONE); + switchToAudioButtonInInputBar.setVisibility(View.VISIBLE); + messageInputBar.setVisibility(View.VISIBLE); + + if (needShowInput) { + uiHandler.postDelayed(showTextRunnable, SHOW_LAYOUT_DELAY); + } + } + + // 发送文本消息 + private void onTextMessageSendButtonPressed() { + String text = messageEditText.getText().toString(); + if (TextUtils.isEmpty(text.trim())) return; + EventBus.getDefault().post(new ActiveEvent()); + IMMessage textMessage = createTextMessage(text); + if (AntiSpamUtil.checkLocalAntiSpam(textMessage)) { + EventBus.getDefault().post(new AntiSpamEvent()); + } else { + if (container.proxy.sendMessage(textMessage)) { + restoreText(true); + } + } + } + + protected IMMessage createTextMessage(String text) { + return MessageBuilder.createTextMessage(container.account, container.sessionType, text); + } + + // 切换成音频,收起键盘,按钮切换成键盘 + private void switchToAudioLayout() { + if (!isChat) { + SingleToastUtil.showToast("等级不够"); + return; + } + Log.e(TAG, "switchToAudioLayout: "); + NimAudioChatEvent event = new NimAudioChatEvent(); + event.setSuccess(o -> { + messageEditText.setVisibility(View.GONE); + audioRecordBtn.setVisibility(View.VISIBLE); + hideInputMethod(); + switchToAudioButtonInInputBar.setVisibility(View.GONE); + switchToTextButtonInInputBar.setVisibility(View.VISIBLE); + mHelper.resetState(); + }); + Log.e(TAG, "switchToAudioLayout: post event"); + EventBus.getDefault().post(event); + } + + // 隐藏键盘布局 + public void hideInputMethod() { + isKeyboardShowed = false; + uiHandler.removeCallbacks(showTextRunnable); + InputMethodManager imm = (InputMethodManager) container.activity.getSystemService(Context.INPUT_METHOD_SERVICE); + imm.hideSoftInputFromWindow(messageEditText.getWindowToken(), 0); + messageEditText.clearFocus(); + } + + // 显示键盘布局 + private void showInputMethod(EditText editTextMessage) { + editTextMessage.requestFocus(); + //如果已经显示,则继续操作时不需要把光标定位到最后 + if (!isKeyboardShowed) { + editTextMessage.setSelection(editTextMessage.getText().length()); + isKeyboardShowed = true; + } + + mHelper.toKeyboardState(); + container.proxy.onInputPanelExpand(); + } + + private void restoreText(boolean clearText) { + if (clearText) { + messageEditText.setText(""); + } + checkSendButtonEnable(messageEditText); + } + + /** + * 显示发送或更多 + * + * @param editText + */ + private void checkSendButtonEnable(EditText editText) { + String textMessage = editText.getText().toString(); + setEditTextState(); + if (!TextUtils.isEmpty(StringUtil.removeBlanks(textMessage)) && editText.hasFocus()) { + sendMessageButtonInInputBar.setVisibility(View.VISIBLE); + } else { + sendMessageButtonInInputBar.setVisibility(View.GONE); + } + } + + /** + * *************** IEmojiSelectedListener *************** + */ + @Override + public void onEmojiSelected(String key) { + Editable mEditable = messageEditText.getText(); + if (key.equals("/DEL")) { + messageEditText.dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DEL)); + } else { + int start = messageEditText.getSelectionStart(); + int end = messageEditText.getSelectionEnd(); + start = (start < 0 ? 0 : start); + end = (start < 0 ? 0 : end); + mEditable.replace(start, end, key); + } + } + + @Override + public void onStickerSelected(String category, String item) { + Log.i("InputPanel", "onStickerSelected, category =" + category + ", sticker =" + item); + + if (customization != null) { + MsgAttachment attachment = customization.createStickerAttachment(category, item); + IMMessage stickerMessage = MessageBuilder.createCustomMessage(container.account, container.sessionType, "贴图消息", attachment); + container.proxy.sendMessage(stickerMessage); + } + } + + @Override + public void onTextAdd(String content, int start, int length) { + if (messageEditText.getVisibility() != View.VISIBLE || + (emoticonPickerView != null && emoticonPickerView.getVisibility() == View.VISIBLE)) { + switchToTextLayout(true); + } else { + uiHandler.postDelayed(showTextRunnable, SHOW_LAYOUT_DELAY); + } + messageEditText.getEditableText().insert(start, content); + } + + @Override + public void onTextDelete(int start, int length) { + if (messageEditText.getVisibility() != View.VISIBLE) { + switchToTextLayout(true); + } else { + uiHandler.postDelayed(showTextRunnable, SHOW_LAYOUT_DELAY); + } + int end = start + length - 1; + messageEditText.getEditableText().replace(start, end, ""); + } + + public int getEditSelectionStart() { + return messageEditText.getSelectionStart(); + } + + + /** + * ****************************** 语音 *********************************** + */ + @SuppressLint("ClickableViewAccessibility") + private void initAudioRecordButton() { + audioRecordBtn.setOnTouchListener((v, event) -> { + if (event.getAction() == MotionEvent.ACTION_DOWN) { + touched = true; + initAudioRecord(); + onStartAudioRecord(); + } else if (event.getAction() == MotionEvent.ACTION_CANCEL + || event.getAction() == MotionEvent.ACTION_UP) { + touched = false; + onEndAudioRecord(isCancelled(v, event)); + } else if (event.getAction() == MotionEvent.ACTION_MOVE) { + touched = true; + cancelAudioRecord(isCancelled(v, event)); + } + + return false; + }); + } + + /** + * 初始化AudioRecord + */ + private void initAudioRecord() { + if (audioMessageHelper == null) { + UIKitOptions options = NimUIKitImpl.getOptions(); + audioMessageHelper = new AudioRecorder(container.activity, options.audioRecordType, options.audioRecordMaxTime, this); + } + } + + /** + * 开始语音录制 + */ + private void onStartAudioRecord() { + container.activity.getWindow().setFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON, + WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); + audioMessageHelper.startRecord(); + cancelled = false; + } + + /** + * 结束语音录制 + * + * @param cancel + */ + private void onEndAudioRecord(boolean cancel) { + started = false; + container.activity.getWindow().setFlags(0, WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); + + audioMessageHelper.completeRecord(cancel); + audioRecordBtn.setText(R.string.record_audio); + audioRecordBtn.setBackgroundResource(R.drawable.bg_message_voice); + stopAudioRecordAnim(); + + if (!cancel) { + EventBus.getDefault().post(new ActiveEvent()); + } + } + + /** + * 取消语音录制 + * + * @param cancel + */ + private void cancelAudioRecord(boolean cancel) { + // reject + if (!started) { + return; + } + // no change + if (cancelled == cancel) { + return; + } + + cancelled = cancel; + updateTimerTip(cancel); + } + + /** + * 正在进行语音录制和取消语音录制,界面展示 + * + * @param cancel + */ + private void updateTimerTip(boolean cancel) { + if (cancel) { + timerTip.setText(R.string.recording_cancel_tip); + timerTipContainer.setBackgroundResource(R.drawable.nim_cancel_record_red_bg); + } else { + timerTip.setText(R.string.recording_cancel); + timerTipContainer.setBackgroundResource(0); + } + } + + /** + * 开始语音录制动画 + */ + private void playAudioRecordAnim() { + audioAnimLayout.setVisibility(View.VISIBLE); + time.setBase(SystemClock.elapsedRealtime()); + time.start(); + } + + /** + * 结束语音录制动画 + */ + private void stopAudioRecordAnim() { + audioAnimLayout.setVisibility(View.GONE); + time.stop(); + time.setBase(SystemClock.elapsedRealtime()); + } + + // 录音状态回调 + @Override + public void onRecordReady() { + + } + + @Override + public void onRecordStart(File audioFile, RecordType recordType) { + started = true; + if (!touched) { + return; + } + + audioRecordBtn.setText(R.string.record_audio_end); + audioRecordBtn.setBackgroundResource(R.drawable.bg_message_voice_pressed); + + updateTimerTip(false); // 初始化语音动画状态 + playAudioRecordAnim(); + } + + @Override + public void onRecordSuccess(File audioFile, long audioLength, RecordType recordType) { + IMMessage audioMessage = MessageBuilder.createAudioMessage(container.account, container.sessionType, audioFile, audioLength); + container.proxy.sendMessage(audioMessage); + } + + @Override + public void onRecordFail() { + if (started) { + SingleToastUtil.showToast(R.string.recording_error); + } + } + + @Override + public void onRecordCancel() { + + } + + @Override + public void onRecordReachedMaxTime(final int maxTime) { + stopAudioRecordAnim(); + EasyAlertDialogHelper.createOkCancelDiolag(container.activity, "", container.activity.getString(R.string.recording_max_time), false, new EasyAlertDialogHelper.OnDialogActionListener() { + @Override + public void doCancelAction() { + } + + @Override + public void doOkAction() { + audioMessageHelper.handleEndRecord(true, maxTime); + } + }).show(); + } + + public boolean isRecording() { + return audioMessageHelper != null && audioMessageHelper.isRecording(); + } + + public void onActivityResult(int requestCode, int resultCode, Intent data) { + if (resultCode != Activity.RESULT_OK) { + return; + } + int index = (requestCode << 16) >> 24; + if (index != 0) { + index--; + if (index < 0 | index >= actions.size()) { + LogUtil.d(TAG, "request code out of actions' range"); + return; + } + BaseAction action = actions.get(index); + if (action != null) { + action.onActivityResult(requestCode & 0xff, resultCode, data); + } + } + } + + public void reloadActions(List actions) { + this.actions = actions; + for (int i = 0; i < this.actions.size(); ++i) { + this.actions.get(i).setIndex(i); + this.actions.get(i).setContainer(container); + } + ActionsPanel.init(view, actions); + } + + public void setLimitLevel(boolean isChat, String msg) { + this.isChat = isChat; + setEditTextState(); + } + + private void setEditTextState() { + if (!isChat) { + messageEditText.setHint("暂未达到可发起私聊等级"); + messageEditText.setFocusable(false); + messageEditText.setFocusableInTouchMode(false); + messageEditText.setEnabled(false); + sendMessageButtonInInputBar.setEnabled(false); + } else { + messageEditText.setHint("请输入消息"); + messageEditText.setFocusable(true); + messageEditText.setFocusableInTouchMode(true); + messageEditText.setEnabled(true); + sendMessageButtonInInputBar.setEnabled(true); + } + } + +} diff --git a/app/src/main/java/com/mango/moshen/ui/im/MessageListPanelEx.java b/app/src/main/java/com/mango/moshen/ui/im/MessageListPanelEx.java index d2cee003b..f7ca26651 100644 --- a/app/src/main/java/com/mango/moshen/ui/im/MessageListPanelEx.java +++ b/app/src/main/java/com/mango/moshen/ui/im/MessageListPanelEx.java @@ -17,6 +17,8 @@ import androidx.recyclerview.widget.RecyclerView; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; +import com.mango.core.room.event.MessageSizeEvent; +import com.mango.xchat_android_library.utils.SingleToastUtil; import com.netease.nim.uikit.R; import com.netease.nim.uikit.api.NimUIKit; import com.netease.nim.uikit.api.model.user.UserInfoObserver; @@ -65,8 +67,6 @@ import com.netease.nimlib.sdk.robot.model.RobotAttachment; import com.netease.nimlib.sdk.robot.model.RobotMsgType; import com.netease.nimlib.sdk.team.constant.TeamMemberType; import com.netease.nimlib.sdk.team.model.TeamMember; -import com.mango.core.room.event.MessageSizeEvent; -import com.mango.xchat_android_library.utils.SingleToastUtil; import org.greenrobot.eventbus.EventBus; @@ -87,7 +87,7 @@ public class MessageListPanelEx { private static final int REQUEST_CODE_FORWARD_TEAM = 0x02; // 背景图片缓存 private static Pair background; - private static Comparator comp = new Comparator() { + private static final Comparator comp = new Comparator() { @Override public int compare(IMMessage o1, IMMessage o2) { @@ -97,7 +97,7 @@ public class MessageListPanelEx { }; // container private Container container; - private View rootView; + private final View rootView; // message list view private RecyclerView messageListView; private List items; @@ -107,15 +107,15 @@ public class MessageListPanelEx { private IncomingMsgPrompt incomingMsgPrompt; private Handler uiHandler; // 仅显示消息记录,不接收和发送消息 - private boolean recordOnly; + private final boolean recordOnly; // 从服务器拉取消息记录 - private boolean remote; + private final boolean remote; // 语音转文字 private VoiceTrans voiceTrans; // 待转发消息 private IMMessage forwardMessage; private CountDownTimer countDownTimer; - private OnItemClickListener listener = new OnItemClickListener() { + private final OnItemClickListener listener = new OnItemClickListener() { @Override public void onItemClick(IRecyclerView adapter, View view, int position) { @@ -142,7 +142,7 @@ public class MessageListPanelEx { container.activity.startActivity(intent); } catch (ActivityNotFoundException e) { // Toast.makeText(container.activity, "路径错误", Toast.LENGTH_SHORT).show(); - SingleToastUtil.showToastShort("路径错误"); + SingleToastUtil.showToast("路径错误"); } } else if (LinkElement.TYPE_BLOCK.equals(element.getType())) { @@ -162,7 +162,7 @@ public class MessageListPanelEx { /** * 消息状态变化观察者 */ - private Observer messageStatusObserver = new Observer() { + private final Observer messageStatusObserver = new Observer() { @Override public void onEvent(IMMessage message) { if (isMyMessage(message)) { @@ -173,7 +173,7 @@ public class MessageListPanelEx { /** * 消息附件上传/下载进度观察者 */ - private Observer attachmentProgressObserver = new Observer() { + private final Observer attachmentProgressObserver = new Observer() { @Override public void onEvent(AttachmentProgress progress) { onAttachmentProgressChange(progress); @@ -182,7 +182,7 @@ public class MessageListPanelEx { /** * 本地消息接收观察者 */ - private MessageListPanelHelper.LocalMessageObserver incomingLocalMessageObserver = new MessageListPanelHelper.LocalMessageObserver() { + private final MessageListPanelHelper.LocalMessageObserver incomingLocalMessageObserver = new MessageListPanelHelper.LocalMessageObserver() { @Override public void onAddMessage(IMMessage message) { if (message == null || !container.account.equals(message.getSessionId())) { @@ -202,7 +202,7 @@ public class MessageListPanelEx { /** * 消息撤回观察者 */ - private Observer revokeMessageObserver = new Observer() { + private final Observer revokeMessageObserver = new Observer() { @Override public void onEvent(RevokeMsgNotification notification) { if (notification == null || notification.getMessage() == null) { @@ -282,10 +282,10 @@ public class MessageListPanelEx { } private void initListView(IMMessage anchor) { - listviewBk = (ImageView) rootView.findViewById(R.id.message_activity_background); + listviewBk = rootView.findViewById(R.id.message_activity_background); // RecyclerView - messageListView = (RecyclerView) rootView.findViewById(R.id.messageListView); + messageListView = rootView.findViewById(R.id.messageListView); messageListView.setLayoutManager(new LinearLayoutManager(container.activity)); messageListView.requestDisallowInterceptTouchEvent(true); messageListView.addOnScrollListener(new RecyclerView.OnScrollListener() { @@ -339,12 +339,7 @@ public class MessageListPanelEx { } public void scrollToBottom() { - uiHandler.postDelayed(new Runnable() { - @Override - public void run() { - doScrollToBottom(); - } - }, 200); + doScrollToBottom(); } private void doScrollToBottom() { @@ -603,15 +598,11 @@ public class MessageListPanelEx { } private boolean receiveReceiptCheck(final IMMessage msg) { - if (msg != null && msg.getSessionType() == SessionTypeEnum.P2P + return msg != null && msg.getSessionType() == SessionTypeEnum.P2P && msg.getDirect() == MsgDirectionEnum.Out && msg.getMsgType() != MsgTypeEnum.tip && msg.getMsgType() != MsgTypeEnum.notification - && msg.isRemoteRead()) { - return true; - } - - return false; + && msg.isRemoteRead(); } /** @@ -649,12 +640,8 @@ public class MessageListPanelEx { } private boolean sendReceiptCheck(final IMMessage msg) { - if (msg == null || msg.getDirect() != MsgDirectionEnum.In || - msg.getMsgType() == MsgTypeEnum.tip || msg.getMsgType() == MsgTypeEnum.notification) { - return false; // 非收到的消息,Tip消息和通知类消息,不要发已读回执 - } - - return true; + return msg != null && msg.getDirect() == MsgDirectionEnum.In && + msg.getMsgType() != MsgTypeEnum.tip && msg.getMsgType() != MsgTypeEnum.notification; // 非收到的消息,Tip消息和通知类消息,不要发已读回执 } // 删除消息 @@ -699,7 +686,7 @@ public class MessageListPanelEx { if (message == null) { // Toast.makeText(container.activity, "该类型不支持转发", Toast.LENGTH_SHORT).show(); - SingleToastUtil.showToastShort("该类型不支持转发"); + SingleToastUtil.showToast("该类型不支持转发"); return; } @@ -742,15 +729,15 @@ public class MessageListPanelEx { private class MessageLoader implements BaseFetchLoadAdapter.RequestLoadMoreListener, BaseFetchLoadAdapter.RequestFetchMoreListener { - private int loadMsgCount = NimUIKitImpl.getOptions().messageCountLoadOnce; + private final int loadMsgCount = NimUIKitImpl.getOptions().messageCountLoadOnce; private QueryDirectionEnum direction = null; - private IMMessage anchor; - private boolean remote; + private final IMMessage anchor; + private final boolean remote; private boolean firstLoad = true; - private RequestCallback> callback = new RequestCallbackWrapper>() { + private final RequestCallback> callback = new RequestCallbackWrapper>() { @Override public void onResult(int code, List messages, Throwable exception) { if (code != ResponseCode.RES_SUCCESS || exception != null) { @@ -1209,8 +1196,7 @@ public class MessageListPanelEx { @Override public void onClick() { -// Toast.makeText(container.activity, finalContent, Toast.LENGTH_SHORT).show(); - SingleToastUtil.showToastShort(finalContent); + SingleToastUtil.showToast(finalContent); setEarPhoneMode(!UserPreferences.isEarPhoneModeEnable(), true); } }); @@ -1257,8 +1243,7 @@ public class MessageListPanelEx { @Override public void onClick() { if (!NetworkUtil.isNetAvailable(container.activity)) { -// Toast.makeText(container.activity, R.string.network_is_not_available, Toast.LENGTH_SHORT).show(); - SingleToastUtil.showToastShort(R.string.network_is_not_available); + SingleToastUtil.showToast(R.string.network_is_not_available); return; } NIMClient.getService(MsgService.class).revokeMessage(item).setCallback(new RequestCallback() { @@ -1271,11 +1256,9 @@ public class MessageListPanelEx { @Override public void onFailed(int code) { if (code == ResponseCode.RES_OVERDUE) { -// Toast.makeText(container.activity, R.string.revoke_failed, Toast.LENGTH_SHORT).show(); - SingleToastUtil.showToastShort(R.string.revoke_failed); + SingleToastUtil.showToast(R.string.revoke_failed); } else { -// Toast.makeText(container.activity, "revoke msg failed, code:" + code, Toast.LENGTH_SHORT).show(); - SingleToastUtil.showToastShort("revoke msg failed, code:" + code); + SingleToastUtil.showToast("revoke msg failed, code:" + code); } } diff --git a/app/src/main/java/com/mango/moshen/ui/im/avtivity/NimP2PMessageActivity.java b/app/src/main/java/com/mango/moshen/ui/im/avtivity/NimP2PMessageActivity.java index 5e3e91c34..6f0862faf 100644 --- a/app/src/main/java/com/mango/moshen/ui/im/avtivity/NimP2PMessageActivity.java +++ b/app/src/main/java/com/mango/moshen/ui/im/avtivity/NimP2PMessageActivity.java @@ -17,6 +17,31 @@ import androidx.annotation.Nullable; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; +import com.mango.core.audio.event.VoiceShakeHeartEvent; +import com.mango.core.auth.AuthModel; +import com.mango.core.im.friend.IMFriendModel; +import com.mango.core.mentoring_relationship.event.MentoringSuccessEvent; +import com.mango.core.noble.NobleUtil; +import com.mango.core.praise.PraiseModel; +import com.mango.core.praise.event.IsLikedEvent; +import com.mango.core.praise.event.PraiseEvent; +import com.mango.core.user.UserModel; +import com.mango.core.user.bean.UserDetailInfo; +import com.mango.core.user.bean.UserInfo; +import com.mango.core.utils.StringExtensionKt; +import com.mango.core.utils.SystemUidUtil; +import com.mango.core.utils.net.BeanObserver; +import com.mango.moshen.R; +import com.mango.moshen.avroom.activity.AVRoomActivity; +import com.mango.moshen.common.widget.CustomImageSpan; +import com.mango.moshen.mentoring_relationship.dialog.BuildMentoringRelationshipSuccessDialog; +import com.mango.moshen.ui.im.audio.ShakeHeartDialogFragment; +import com.mango.moshen.ui.im.fragment.MessageFragment; +import com.mango.moshen.ui.user.UserInfoActivity; +import com.mango.moshen.ui.utils.ImageLoadUtils; +import com.mango.xchat_android_library.utils.ListUtils; +import com.mango.xchat_android_library.utils.SingleToastUtil; +import com.netease.nim.uikit.StatusBarUtil; import com.netease.nim.uikit.api.NimUIKit; import com.netease.nim.uikit.api.model.contact.ContactChangedObserver; import com.netease.nim.uikit.api.model.main.OnlineStateChangeObserver; @@ -31,33 +56,6 @@ import com.netease.nimlib.sdk.Observer; import com.netease.nimlib.sdk.msg.MsgServiceObserve; import com.netease.nimlib.sdk.msg.constant.SessionTypeEnum; import com.netease.nimlib.sdk.msg.model.CustomNotification; -import com.mango.moshen.R; -import com.mango.moshen.avroom.activity.AVRoomActivity; -import com.mango.moshen.common.widget.CustomImageSpan; -import com.mango.moshen.ui.im.audio.ShakeHeartDialogFragment; -import com.mango.moshen.ui.im.fragment.MessageFragment; -import com.mango.moshen.ui.user.UserInfoActivity; -import com.mango.moshen.ui.utils.ImageLoadUtils; -import com.mango.moshen.mentoring_relationship.dialog.BuildMentoringRelationshipSuccessDialog; -import com.mango.core.audio.event.VoiceShakeHeartEvent; -import com.mango.core.auth.AuthModel; -import com.mango.core.im.friend.IMFriendModel; -import com.mango.core.initial.InitialModel; -import com.mango.core.initial.bean.InitInfo; -import com.mango.core.level.UserLevelVo; -import com.mango.core.mentoring_relationship.event.MentoringSuccessEvent; -import com.mango.core.noble.NobleUtil; -import com.mango.core.praise.PraiseModel; -import com.mango.core.praise.event.IsLikedEvent; -import com.mango.core.praise.event.PraiseEvent; -import com.mango.core.user.UserModel; -import com.mango.core.user.bean.UserDetailInfo; -import com.mango.core.user.bean.UserInfo; -import com.mango.core.utils.StringExtensionKt; -import com.mango.core.utils.SystemUidUtil; -import com.mango.core.utils.net.BeanObserver; -import com.mango.xchat_android_library.utils.ListUtils; -import com.mango.xchat_android_library.utils.SingleToastUtil; import org.greenrobot.eventbus.EventBus; import org.greenrobot.eventbus.Subscribe; @@ -414,21 +412,6 @@ public class NimP2PMessageActivity extends NewBaseMessageActivity { MessageFragment fragment = new MessageFragment(); fragment.setArguments(arguments); fragment.setContainerId(R.id.message_fragment_container); - - // 等级限制:官方小秘书 和 系统消息,不设置等级限制 - if (!SystemUidUtil.isSystemUid(sessionId)) { - UserInfo userInfo = UserModel.get().getCacheLoginUserInfo(); - if (userInfo != null) { - UserLevelVo userLevelVo = userInfo.getUserLevelVo(); - if (userLevelVo != null) { - fragment.setCurrentLevel(userLevelVo.experLevelSeq); - } - } - InitInfo initInfo = InitialModel.get().getCacheInitInfo(); - if (initInfo != null) { - fragment.setLimitLevel(initInfo.getPrivateChatLevelNo()); - } - } return fragment; } @@ -486,4 +469,16 @@ public class NimP2PMessageActivity extends NewBaseMessageActivity { ShakeHeartDialogFragment shakeHeartDialogFragment = ShakeHeartDialogFragment.newInstance(event.showTextHint); shakeHeartDialogFragment.show(getSupportFragmentManager(), "shake_heart"); } + + @Override + protected boolean needSteepStateBar() { + return true; + } + + @Override + protected void setStatusBar() { + super.setStatusBar(); + StatusBarUtil.transparencyBar(this); + StatusBarUtil.StatusBarLightMode(this); + } } diff --git a/app/src/main/java/com/mango/moshen/ui/im/fragment/MessageFragment.java b/app/src/main/java/com/mango/moshen/ui/im/fragment/MessageFragment.java index 5c2fb0294..51c51163a 100644 --- a/app/src/main/java/com/mango/moshen/ui/im/fragment/MessageFragment.java +++ b/app/src/main/java/com/mango/moshen/ui/im/fragment/MessageFragment.java @@ -20,6 +20,24 @@ import android.widget.TextView; import androidx.annotation.NonNull; import androidx.core.content.ContextCompat; +import com.mango.core.UriProvider; +import com.mango.core.auth.AuthModel; +import com.mango.core.im.chatterbox.ChatterBoxHelper; +import com.mango.core.im.chatterbox.HideInputEvent; +import com.mango.core.room.event.MessageSizeEvent; +import com.mango.core.statistic.StatisticManager; +import com.mango.core.statistic.protocol.StatisticsProtocol; +import com.mango.moshen.R; +import com.mango.moshen.common.widget.OriginalDrawStatusClickSpan; +import com.mango.moshen.ui.im.GreetPresenter; +import com.mango.moshen.ui.im.InputPanel; +import com.mango.moshen.ui.im.MessageListPanelEx; +import com.mango.moshen.ui.im.chat.MVHChatterBoxStart; +import com.mango.moshen.ui.im.model.IMCustomModel; +import com.mango.moshen.ui.webview.CommonWebViewActivity; +import com.mango.moshen.utils.PushMessageHandler; +import com.mango.xchat_android_library.utils.SingleToastUtil; +import com.mango.xchat_android_library.utils.config.BasicConfig; import com.netease.nim.uikit.api.UIKitOptions; import com.netease.nim.uikit.api.model.main.CustomPushContentProvider; import com.netease.nim.uikit.api.model.session.SessionCustomization; @@ -28,7 +46,6 @@ import com.netease.nim.uikit.business.session.actions.BaseAction; import com.netease.nim.uikit.business.session.constant.Extras; import com.netease.nim.uikit.business.session.module.Container; import com.netease.nim.uikit.business.session.module.ModuleProxy; -import com.netease.nim.uikit.business.session.module.input.InputPanel; import com.netease.nim.uikit.business.session.module.input.NimAudioChatEvent; import com.netease.nim.uikit.business.session.module.input.NimImageActionEvent; import com.netease.nim.uikit.common.fragment.TFragment; @@ -51,25 +68,6 @@ import com.netease.nimlib.sdk.robot.model.NimRobotInfo; import com.netease.nimlib.sdk.robot.model.RobotAttachment; import com.netease.nimlib.sdk.robot.model.RobotMsgType; import com.tbruyelle.rxpermissions2.RxPermissions; -import com.mango.moshen.R; -import com.mango.moshen.common.widget.OriginalDrawStatusClickSpan; -import com.mango.moshen.ui.im.GreetPresenter; -import com.mango.moshen.ui.im.MessageListPanelEx; -import com.mango.moshen.ui.im.chat.MVHChatterBoxStart; -import com.mango.moshen.ui.im.model.IMCustomModel; -import com.mango.moshen.ui.webview.CommonWebViewActivity; -import com.mango.moshen.utils.PushMessageHandler; -import com.mango.core.UriProvider; -import com.mango.core.auth.AuthModel; -import com.mango.core.im.chatterbox.ChatterBoxHelper; -import com.mango.core.im.chatterbox.HideInputEvent; -import com.mango.core.im.custom.bean.CustomAttachment; -import com.mango.core.im.custom.bean.ImTipAttachment; -import com.mango.core.room.event.MessageSizeEvent; -import com.mango.core.statistic.StatisticManager; -import com.mango.core.statistic.protocol.StatisticsProtocol; -import com.mango.xchat_android_library.utils.SingleToastUtil; -import com.mango.xchat_android_library.utils.config.BasicConfig; import org.greenrobot.eventbus.EventBus; import org.greenrobot.eventbus.Subscribe; @@ -103,6 +101,7 @@ public class MessageFragment extends TFragment implements ModuleProxy, MessageLi protected InputPanel inputPanel; protected MessageListPanelEx messageListPanel; protected AitManager aitManager; + private boolean inRoom; /** * 消息接收观察者 */ @@ -190,27 +189,12 @@ public class MessageFragment extends TFragment implements ModuleProxy, MessageLi } } - /** - * 发送提示信息 - * - * @param msg - */ - public void sendTipMessage(String msg, int second) { - ImTipAttachment attachment = new ImTipAttachment(CustomAttachment.CUSTOM_MSG_IM_TIP, second); - attachment.setMsg(msg); - IMMessage message = MessageBuilder.createCustomMessage(sessionId, SessionTypeEnum.P2P, attachment); - sendMessage(message); - } - public boolean onBackPressed() { if (inputPanel.collapse(true)) { return true; } - if (messageListPanel.onBackPressed()) { - return true; - } - return false; + return messageListPanel.onBackPressed(); } public void refreshMessageList() { @@ -243,8 +227,6 @@ public class MessageFragment extends TFragment implements ModuleProxy, MessageLi initAitManager(); - inputPanel.switchRobotMode(NimUIKitImpl.getRobotInfoProvider().getRobotByAccount(sessionId) != null); - registerObservers(true); if (customization != null) { @@ -302,7 +284,7 @@ public class MessageFragment extends TFragment implements ModuleProxy, MessageLi */ // 是否允许发送消息 protected boolean isAllowSendMessage(final IMMessage message) { - return true; + return isChat; } /** @@ -324,7 +306,9 @@ public class MessageFragment extends TFragment implements ModuleProxy, MessageLi */ @Override public boolean sendMessage(IMMessage message) { + if (!isAllowSendMessage(message)) { + SingleToastUtil.showToast("未到达私聊等级!"); return false; } @@ -346,8 +330,6 @@ public class MessageFragment extends TFragment implements ModuleProxy, MessageLi final IMMessage msg = message; appendPushConfig(message); - // send message to server and save to db - IMMessage finalMessage = message; NIMClient.getService(MsgService.class).sendMessage(message, false).setCallback(new RequestCallback() { @Override public void onSuccess(Void param) { @@ -542,10 +524,6 @@ public class MessageFragment extends TFragment implements ModuleProxy, MessageLi // 操作面板集合 protected List getActionList() { List actions = new ArrayList<>(); -// actions.add(new ImageAction()); -// actions.add(new VideoAction()); -// actions.add(new LocationAction()); - if (customization != null && customization.actions != null) { actions.addAll(customization.actions); } @@ -566,18 +544,6 @@ public class MessageFragment extends TFragment implements ModuleProxy, MessageLi messageListPanel.receiveReceipt(); } - /** - * 重新加载 输入面板 - * - * @param sessionCustomization - */ - public void reloadInputPanel(SessionCustomization sessionCustomization) { - this.customization = sessionCustomization; - Container container = new Container(getActivity(), sessionId, sessionType, this); - inputPanel.reload(container, customization); - inputPanel.reloadActions(sessionCustomization.actions); - } - @Subscribe(threadMode = ThreadMode.MAIN) public void onHideInput(HideInputEvent event) { if (inputPanel != null) { @@ -592,51 +558,54 @@ public class MessageFragment extends TFragment implements ModuleProxy, MessageLi if (inputPanel != null) { if (event.getSize() > 0) { tvChatLimit.setVisibility(View.GONE); + isChat = true; inputPanel.setLimitLevel(true, ""); } else { - IMCustomModel.get().getPrivateChatLimit(sessionId).subscribe(((privateChatLimitInfo, throwable) -> { - if (throwable != null) { - throwable.printStackTrace(); - } else { - isChat = privateChatLimitInfo.isChat(); - hintText = "暂未达到可发起私聊等级"; - inputPanel.setLimitLevel(privateChatLimitInfo.isChat(), privateChatLimitInfo.getMessage()); + IMCustomModel.get() + .getPrivateChatLimit(sessionId) + .subscribe(((privateChatLimitInfo, throwable) -> { + if (throwable != null) { + throwable.printStackTrace(); + } else { + isChat = privateChatLimitInfo.isChat(); + hintText = "暂未达到可发起私聊等级"; + inputPanel.setLimitLevel(privateChatLimitInfo.isChat(), privateChatLimitInfo.getMessage()); - String experLevel = "财富等级≥" + privateChatLimitInfo.getWealthLevel(); - String charmLevel = "魅力等级≥" + privateChatLimitInfo.getCharmLevel(); - String privacyAgreementDescTip = getContext().getString(R.string.text_chat_limit, experLevel, charmLevel); - SpannableString ss = new SpannableString(privacyAgreementDescTip); - int experLevelIndex = privacyAgreementDescTip.indexOf(experLevel); - int charmLevelIndex = privacyAgreementDescTip.indexOf(charmLevel); + String experLevel = "财富等级≥" + privateChatLimitInfo.getWealthLevel(); + String charmLevel = "魅力等级≥" + privateChatLimitInfo.getCharmLevel(); + String privacyAgreementDescTip = getContext().getString(R.string.text_chat_limit, experLevel, charmLevel); + SpannableString ss = new SpannableString(privacyAgreementDescTip); + int experLevelIndex = privacyAgreementDescTip.indexOf(experLevel); + int charmLevelIndex = privacyAgreementDescTip.indexOf(charmLevel); - ss.setSpan(new ForegroundColorSpan(ContextCompat.getColor(getContext(), R.color.appColor)), experLevelIndex, experLevelIndex + experLevel.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE); - ss.setSpan(new OriginalDrawStatusClickSpan(ContextCompat.getColor(getContext(), R.color.appColor)) { - @Override - public void onClick(@NonNull View widget) { - if (widget instanceof TextView) - ((TextView) widget).setHighlightColor(getResources().getColor(android.R.color.transparent)); + ss.setSpan(new ForegroundColorSpan(ContextCompat.getColor(getContext(), R.color.appColor)), experLevelIndex, experLevelIndex + experLevel.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE); + ss.setSpan(new OriginalDrawStatusClickSpan(ContextCompat.getColor(getContext(), R.color.appColor)) { + @Override + public void onClick(@NonNull View widget) { + if (widget instanceof TextView) + ((TextView) widget).setHighlightColor(getResources().getColor(android.R.color.transparent)); - CommonWebViewActivity.start(getContext(), UriProvider.getUserLevelUrl()); + CommonWebViewActivity.start(getContext(), UriProvider.getUserLevelUrl()); + } + }, experLevelIndex, experLevelIndex + experLevel.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE); + ss.setSpan(new ForegroundColorSpan(ContextCompat.getColor(getContext(), R.color.appColor)), charmLevelIndex, charmLevelIndex + charmLevel.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE); + ss.setSpan(new OriginalDrawStatusClickSpan(ContextCompat.getColor(getContext(), R.color.appColor)) { + @Override + public void onClick(@NonNull View widget) { + if (widget instanceof TextView) + ((TextView) widget).setHighlightColor(getResources().getColor(android.R.color.transparent)); + + CommonWebViewActivity.start(getContext(), UriProvider.getUserLevelUrl()); + } + }, charmLevelIndex, charmLevelIndex + experLevel.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE); + + tvChatLimit.setText(ss); + tvChatLimit.setHighlightColor(Color.TRANSPARENT); + tvChatLimit.setMovementMethod(new LinkMovementMethod()); + tvChatLimit.setVisibility(isChat ? View.GONE : View.VISIBLE); } - }, experLevelIndex, experLevelIndex + experLevel.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE); - ss.setSpan(new ForegroundColorSpan(ContextCompat.getColor(getContext(), R.color.appColor)), charmLevelIndex, charmLevelIndex + charmLevel.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE); - ss.setSpan(new OriginalDrawStatusClickSpan(ContextCompat.getColor(getContext(), R.color.appColor)) { - @Override - public void onClick(@NonNull View widget) { - if (widget instanceof TextView) - ((TextView) widget).setHighlightColor(getResources().getColor(android.R.color.transparent)); - - CommonWebViewActivity.start(getContext(), UriProvider.getUserLevelUrl()); - } - }, charmLevelIndex, charmLevelIndex + experLevel.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE); - - tvChatLimit.setText(ss); - tvChatLimit.setHighlightColor(Color.TRANSPARENT); - tvChatLimit.setMovementMethod(new LinkMovementMethod()); - tvChatLimit.setVisibility(isChat ? View.GONE : View.VISIBLE); - } - })); + })); } } } @@ -672,12 +641,4 @@ public class MessageFragment extends TFragment implements ModuleProxy, MessageLi }); } - public void setLimitLevel(int limitLevel) { - } - - // -// - public void setCurrentLevel(int currentLevel) { - } - } diff --git a/app/src/main/res/layout/activity_p2p_message.xml b/app/src/main/res/layout/activity_p2p_message.xml index 01190cc33..ce9a0c773 100644 --- a/app/src/main/res/layout/activity_p2p_message.xml +++ b/app/src/main/res/layout/activity_p2p_message.xml @@ -4,7 +4,8 @@ xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" - android:background="@color/bg_normal_1c1b22"> + android:background="@color/bg_normal_1c1b22" + android:paddingTop="30dp"> + + + + diff --git a/app/src/module_public_chat_hall/res/layout/nim_message_photo_layout.xml b/app/src/module_public_chat_hall/res/layout/nim_message_photo_layout.xml new file mode 100644 index 000000000..e7e106925 --- /dev/null +++ b/app/src/module_public_chat_hall/res/layout/nim_message_photo_layout.xml @@ -0,0 +1,21 @@ + + + + + + \ No newline at end of file diff --git a/app/src/module_public_chat_hall/res/layout/nim_msg_fragment.xml b/app/src/module_public_chat_hall/res/layout/nim_msg_fragment.xml index 1c4f393b9..cd0aa3dba 100644 --- a/app/src/module_public_chat_hall/res/layout/nim_msg_fragment.xml +++ b/app/src/module_public_chat_hall/res/layout/nim_msg_fragment.xml @@ -1,58 +1,24 @@ - + android:orientation="vertical" + app:animationSpeed="standard"> - - - - - - - - - - - - + android:layout_height="match_parent" + android:orientation="vertical" + app:edit_view="@id/editTextMessage"> - + android:paddingStart="@dimen/dp_10" + android:paddingTop="@dimen/dp_2" + android:paddingEnd="@dimen/dp_10" + android:paddingBottom="@dimen/dp_2" + android:text="哈哈哈哈哈" + android:visibility="gone" /> - + - + - \ No newline at end of file + + + + + + + + +