From 69f0d76330e13bf3dc3be2b5f50823ddb9bacede Mon Sep 17 00:00:00 2001 From: huangjian Date: Wed, 11 Jan 2023 19:09:36 +0800 Subject: [PATCH] =?UTF-8?q?=E7=A7=81=E8=81=8A=E6=94=B9=E9=80=A0:=E8=BE=93?= =?UTF-8?q?=E5=85=A5=E4=BD=93=E9=AA=8C=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/AndroidManifest.xml | 7 +- .../ui/im/AutoHidePanelRecyclerView.java | 44 + .../com/mango/moshen/ui/im/ImInitHelper.java | 7 +- .../com/mango/moshen/ui/im/InputPanel.java | 878 ++++++++++++++++++ .../moshen/ui/im/MessageListPanelEx.java | 73 +- .../ui/im/avtivity/NimP2PMessageActivity.java | 79 +- .../ui/im/fragment/MessageFragment.java | 167 ++-- .../main/res/layout/activity_p2p_message.xml | 3 +- .../message_input_ic_camera.png | Bin 0 -> 2348 bytes .../drawable-xhdpi/message_input_ic_gift.png | Bin 0 -> 3380 bytes .../drawable-xhdpi/message_input_ic_image.png | Bin 0 -> 1987 bytes .../res/layout/nim_message_emoji_layout.xml | 8 + .../res/layout/nim_message_photo_layout.xml | 21 + .../res/layout/nim_msg_fragment.xml | 231 +++-- .../activity/NimRoomP2PMessageActivity.java | 49 +- library/build.gradle | 3 + nim_uikit/build.gradle | 2 - nim_uikit/res/drawable/bg_message_input.xml | 4 +- nim_uikit/res/layout/nim_emoji_layout.xml | 10 +- nim_uikit/res/values/colors.xml | 4 +- .../nim/uikit/AndroidBug5497Workaround.java | 61 -- .../com/netease/nim/uikit/api/NimUIKit.java | 10 - .../api/wrapper/NimUserInfoProvider.java | 82 -- .../session/actions/CameraAction.java | 44 + .../business/session/actions/PhotoAction.java | 43 + .../session/actions/PickImageAction.java | 25 +- .../session/emoji/EmoticonPickerView.java | 64 +- .../common/media/picker/PickImageHelper.java | 102 +- .../impl/preference/UserPreferences.java | 36 - .../support/permission/BaseMPermission.java | 204 ---- .../uikit/support/permission/MPermission.java | 170 ---- .../annotation/OnMPermissionDenied.java | 15 - .../annotation/OnMPermissionGranted.java | 15 - .../OnMPermissionNeverAskAgain.java | 15 - 34 files changed, 1455 insertions(+), 1021 deletions(-) create mode 100644 app/src/main/java/com/mango/moshen/ui/im/AutoHidePanelRecyclerView.java create mode 100644 app/src/main/java/com/mango/moshen/ui/im/InputPanel.java create mode 100644 app/src/module_public_chat_hall/res/drawable-xhdpi/message_input_ic_camera.png create mode 100644 app/src/module_public_chat_hall/res/drawable-xhdpi/message_input_ic_gift.png create mode 100644 app/src/module_public_chat_hall/res/drawable-xhdpi/message_input_ic_image.png create mode 100644 app/src/module_public_chat_hall/res/layout/nim_message_emoji_layout.xml create mode 100644 app/src/module_public_chat_hall/res/layout/nim_message_photo_layout.xml delete mode 100644 nim_uikit/src/com/netease/nim/uikit/AndroidBug5497Workaround.java delete mode 100644 nim_uikit/src/com/netease/nim/uikit/api/wrapper/NimUserInfoProvider.java create mode 100644 nim_uikit/src/com/netease/nim/uikit/business/session/actions/CameraAction.java create mode 100644 nim_uikit/src/com/netease/nim/uikit/business/session/actions/PhotoAction.java delete mode 100644 nim_uikit/src/com/netease/nim/uikit/impl/preference/UserPreferences.java delete mode 100644 nim_uikit/src/com/netease/nim/uikit/support/permission/BaseMPermission.java delete mode 100644 nim_uikit/src/com/netease/nim/uikit/support/permission/MPermission.java delete mode 100644 nim_uikit/src/com/netease/nim/uikit/support/permission/annotation/OnMPermissionDenied.java delete mode 100644 nim_uikit/src/com/netease/nim/uikit/support/permission/annotation/OnMPermissionGranted.java delete mode 100644 nim_uikit/src/com/netease/nim/uikit/support/permission/annotation/OnMPermissionNeverAskAgain.java 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"> 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 KMNUMnLSTYKatQDM literal 0 HcmV?d00001 diff --git a/app/src/module_public_chat_hall/res/drawable-xhdpi/message_input_ic_image.png b/app/src/module_public_chat_hall/res/drawable-xhdpi/message_input_ic_image.png new file mode 100644 index 0000000000000000000000000000000000000000..7c3f6bbcfea83b22ca2388a8b28b979135f5d8da GIT binary patch literal 1987 zcmV;!2R!(RP)Px+eMv+?RCr$PT5D_^R~7!w%=+21v0LxV?xaE`M4=T>ULrh113`dNT34m%X2(d- zN}(b|fOtPDg&!4C(jtDeQjjPF3RLy37dh082<1l!jVM%5ARsj=O({rWW@mPtG=w_q zUC$gew%48+c099hOWyl)?sOtVz)R1I}cM^CUz#9RIGjXgQ5v`;pCJR7;fiujQfo1)yP{{qa9vzWWKuW3~2k{{S zZK+2=Cuteb2{>qInWItlMgSlsN{a9hfeu6!x(?`$8k%(g$d$uv2?an>(no@vXXXVE z>I%6qgX){7D+uTd;5lk&nNNnvTN3~$?1}IbpO9I$=@9Y!F~gXC832bVY3KY%LcMN) z_;v=qMnnm>E@u9esb?QvOMfr`PQkN<7kxQ@+A8BC#bQQlr&Eo{mZS-pM4ka*#|l4l z!Kz$-U9mWGDM)4@08%3T2@>eXF2-4_j2qXZ^Hm#V`J)nx1AiePS^dV$`%OLjy}ALA zlj$iCrB(#l^kp+Y`JF~qr;|KVB7J}aIhmDnP~|FF*4B$g z&dK?8J)9_jIAFMp{Fk9+uB#saMJ)gra~Pd!Z|d3pZWp|$$jgfA>`YfI)0Ye_GgLPK zl9IkappiuYz^|BEb~LI1-KKNf?$}~znZQU7E`mJ(dJ)h|fktY8ET>*;3AmaT@It*e zvsTrPuGD}rCG~odg`a}x9o6c~un(Ks)P0@aJvt7+sFHe39}Ca=&*BacHuHl8J^T4q zt!@-K9R(mBPi>+;;S_=15@;OT2MvAdTTzT}1x*J5aC!yeGy%7H3}=`iNZxOJkD+IO z&oRuVH+b;<8L2uFHyUcvn-#7d}EaJ+ z9$w(DmCM#nciMOumGNO2!x@154Gky%SJQ9l#<~&-Z2{inSE@mT^nJ;7>2q2`N!Z3Rxm@z;g}$k)dVxjU`e$ zML|3Uz|(+nw%AI^PW#fOCJ25znvMWp2x`{6wPSWR_wQ&9*P=@G%SqvvAll`fwPyff zw?DrD{Ls)|+z&igsUa;Cgcbt8a~9h>i+b+4#+_f{934$)TGy@oz{D55cu$z=JCtt|GRB0#A!IZasG<~xe{sb5DHv_x1FgoXg{bcLBOnR<3L z8tSwvj9ilT+z2uDx*Vx!?SBm1$8;m~tG|uHNN8_qZCArd416IXtQGN74SCh$>5FaSyQ1QDDqX>r&#-Cf8}x__3o&533N#}j+^ z3WAVbE#5e3=o#O3yQ(1&fViT5P5>Ts6{f$Nn0squho5F#s)zUH0XccqA3*e`m4ySo zUeGf42T2M3IqLjm6#8ER(MmC4=4n&^&&Plh&JMB8Myg*{#76*3xD2~oDV4XougZR- z*M1?gMLkFir>(s@7=N_b{%SEl^_!rMOox%7cv5|@K>Pqe@ABDt$j~$Qu4PZi8=?2d zBt<^qzXC4{oCU*aXn1aM9d>>Q#9N)`dVamk{Isdt9}0UY75YeOWaRdd{-J@#iD+ks zoohzj@8>|{m$b=Zn2=BamIN$bUhZe$Gep$2hmm2m_O`1k_jyR&-sOg%d50>CRcH6+VO*fDIbM`0^zsUlo5 zOTUo literal 0 HcmV?d00001 diff --git a/app/src/module_public_chat_hall/res/layout/nim_message_emoji_layout.xml b/app/src/module_public_chat_hall/res/layout/nim_message_emoji_layout.xml new file mode 100644 index 000000000..a4d06fff0 --- /dev/null +++ b/app/src/module_public_chat_hall/res/layout/nim_message_emoji_layout.xml @@ -0,0 +1,8 @@ + + + + + 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 + + + + + + + + +