新增自动打招呼功能

This commit is contained in:
huangjian
2023-02-02 16:01:30 +08:00
parent e6d2e6707f
commit 4b374fc3fb
24 changed files with 826 additions and 359 deletions

View File

@@ -829,7 +829,6 @@
android:launchMode="singleTop"
android:theme="@style/dialogactivity" />
<activity android:name=".home.activity.NewUserListActivity" />
<activity
android:name=".ui.widget.RecallDialog"
android:screenOrientation="portrait"
@@ -1289,6 +1288,9 @@
<activity
android:name=".home.activity.RelationListActivity"
android:screenOrientation="portrait" />
<activity
android:name=".ui.im.avtivity.SayHelloListActivity"
android:screenOrientation="portrait" />
</application>

View File

@@ -1,138 +0,0 @@
package com.mango.moshen.home.activity;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.chad.library.adapter.base.BaseQuickAdapter;
import com.mango.moshen.R;
import com.mango.moshen.base.BaseMvpActivity;
import com.mango.moshen.home.adapter.FindNewUserListAdapter;
import com.mango.moshen.home.presenter.NewUserListPresenter;
import com.mango.moshen.home.view.INewUserListActivityView;
import com.mango.moshen.ui.widget.marqueeview.Utils;
import com.mango.moshen.ui.widget.recyclerview.decoration.SpacingDecoration;
import com.mango.core.user.bean.UserInfo;
import com.mango.xchat_android_library.base.factory.CreatePresenter;
import com.mango.xchat_android_library.utils.ListUtils;
import java.util.List;
import io.reactivex.SingleObserver;
import io.reactivex.disposables.Disposable;
import io.reactivex.functions.Action;
@CreatePresenter(NewUserListPresenter.class)
public class NewUserListActivity extends BaseMvpActivity<INewUserListActivityView, NewUserListPresenter>
implements INewUserListActivityView, SwipeRefreshLayout.OnRefreshListener, BaseQuickAdapter.RequestLoadMoreListener {
private SwipeRefreshLayout srlRefreshContainer;
private RecyclerView rvList;
private FindNewUserListAdapter adapter;
public static void start(Context context) {
Intent intent = new Intent(context, NewUserListActivity.class);
context.startActivity(intent);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_new_user_list);
initTitleBar(getString(R.string.find_newer_list_title));
srlRefreshContainer = (SwipeRefreshLayout) findViewById(R.id.srl_refresh_container);
rvList = (RecyclerView) findViewById(R.id.rv_list);
rvList.setLayoutManager(new GridLayoutManager(this, 3));
rvList.addItemDecoration(new SpacingDecoration(
Utils.dip2px(this, 10),
Utils.dip2px(this, 20),
false));
adapter = new FindNewUserListAdapter(this, null);
adapter.setEnableLoadMore(true);
adapter.setOnLoadMoreListener(this, rvList);
rvList.setAdapter(adapter);
srlRefreshContainer.setOnRefreshListener(this);
}
@Override
protected void onResume() {
super.onResume();
if (ListUtils.isListEmpty(adapter.getData())) {
srlRefreshContainer.setRefreshing(true);
onRefresh();
}
}
@Override
public void onReloadDate() {
super.onReloadDate();
srlRefreshContainer.setRefreshing(true);
onRefresh();
}
@Override
public void onRefresh() {
getMvpPresenter().refreshData()
.doAfterTerminate(new Action() {
@Override
public void run() throws Exception {
srlRefreshContainer.setRefreshing(false);
}
})
.subscribe(new SingleObserver<List<UserInfo>>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onSuccess(List<UserInfo> userInfos) {
if (ListUtils.isListEmpty(userInfos)) {
showNoData();
return;
}
adapter.setNewData(userInfos);
}
@Override
public void onError(Throwable e) {
showNetworkErr();
toast(e.getMessage());
}
});
}
@Override
public void onLoadMoreRequested() {
getMvpPresenter().loadMoreData()
.subscribe(new SingleObserver<List<UserInfo>>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onSuccess(List<UserInfo> userInfos) {
if (ListUtils.isListEmpty(userInfos)) {
adapter.loadMoreEnd(true);
return;
}
adapter.addData(userInfos);
adapter.loadMoreComplete();
}
@Override
public void onError(Throwable e) {
toast(e.getMessage());
}
});
}
}

View File

@@ -1,55 +0,0 @@
package com.mango.moshen.home.adapter;
import android.content.Context;
import androidx.annotation.Nullable;
import android.view.View;
import android.widget.ImageView;
import com.chad.library.adapter.base.BaseQuickAdapter;
import com.chad.library.adapter.base.BaseViewHolder;
import com.netease.nim.uikit.support.glide.GlideApp;
import com.mango.moshen.R;
import com.mango.moshen.ui.user.UserInfoActivity;
import com.mango.core.user.bean.UserInfo;
import java.util.List;
/**
* @author jack
* @Description
* @Date 2018/10/30
*/
public class FindNewUserListAdapter extends BaseQuickAdapter<UserInfo, BaseViewHolder> {
private Context context;
public FindNewUserListAdapter(Context context, @Nullable List<UserInfo> data) {
super(R.layout.item_home_find_new_user_list, data);
this.context = context;
}
@Override
protected void convert(BaseViewHolder helper, UserInfo item) {
helper.setText(R.id.tv_name, item.getNick())
.setText(R.id.tv_tutu_id, "ID:" + item.getErbanNo() + "");
ImageView ivAvatar = helper.getView(R.id.civ_avatar);
GlideApp.with(context)
.load(item.getAvatar())
.dontAnimate()
.into(ivAvatar);
if (item.getGender() == 1) {
helper.setImageResource(R.id.iv_sex, R.drawable.ic_gender_male);
} else {
helper.setImageResource(R.id.iv_sex, R.drawable.ic_gender_female);
}
helper.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
UserInfoActivity.Companion.start(context, item.getUid());
}
});
}
}

View File

@@ -34,6 +34,14 @@ class AnchorGradeDialog : BaseDialog<DialogAnchorGradeBinding>() {
return AnchorGradeDialog()
}
val anchorDrawableResIds = mapOf(
"S" to R.drawable.anchor_grade_ic_level_s,
"A" to R.drawable.anchor_grade_ic_level_a,
"B" to R.drawable.anchor_grade_ic_level_b,
"C" to R.drawable.anchor_grade_ic_level_c,
"D" to R.drawable.anchor_grade_ic_level_d
)
}
override var width: Int = WindowManager.LayoutParams.MATCH_PARENT
@@ -45,14 +53,6 @@ class AnchorGradeDialog : BaseDialog<DialogAnchorGradeBinding>() {
private var disposable: Disposable? = null
private val anchorDrawableResIds = mapOf(
"S" to R.drawable.anchor_grade_ic_level_s,
"A" to R.drawable.anchor_grade_ic_level_a,
"B" to R.drawable.anchor_grade_ic_level_b,
"C" to R.drawable.anchor_grade_ic_level_c,
"D" to R.drawable.anchor_grade_ic_level_d
)
@SuppressLint("CheckResult", "SetTextI18n")
override fun init() {
meViewModel.getAnchorGradeInfo(true)
@@ -60,7 +60,7 @@ class AnchorGradeDialog : BaseDialog<DialogAnchorGradeBinding>() {
val isCompleted =
it.currentReply >= it.targetReply && it.currentDiamond >= it.targetDiamond
binding.ivTitle.setImageResource(if (isCompleted) R.drawable.anchor_grade_bg_complete_text else R.drawable.anchor_grade_bg_task_text)
anchorDrawableResIds[it.grade.toUpperCase(Locale.getDefault())]?.let { resId ->
anchorDrawableResIds[it.grade.uppercase(Locale.getDefault())]?.let { resId ->
binding.ivCurrLevel.setImageResource(resId)
}
val nextLevel = levelArray.getOrNull(levelArray.indexOf(it.grade) + 1)
@@ -102,7 +102,9 @@ class AnchorGradeDialog : BaseDialog<DialogAnchorGradeBinding>() {
for (i in nextRemaining.indices) {
if (i % 3 != 2) {
val span = RoundBackgroundColorSpan(
"#E8EAF3".toColorInt(), "#161958".toColorInt(), ScreenUtil.dip2px(4f)
"#E8EAF3".toColorInt(),
"#161958".toColorInt(),
ScreenUtil.dip2px(4f)
)
nextRemaining.setSpan(
span, i, i + 1, Spannable.SPAN_EXCLUSIVE_INCLUSIVE

View File

@@ -0,0 +1,110 @@
package com.mango.moshen.ui.im;
import android.content.Intent;
import android.net.Uri;
import android.text.TextUtils;
import com.mango.core.statistic.StatisticManager;
import com.mango.core.statistic.protocol.StatisticsProtocol;
import com.mango.moshen.utils.PushMessageHandler;
import com.netease.nim.uikit.api.model.main.CustomPushContentProvider;
import com.netease.nim.uikit.impl.NimUIKitImpl;
import com.netease.nimlib.sdk.NIMClient;
import com.netease.nimlib.sdk.RequestCallback;
import com.netease.nimlib.sdk.msg.MessageBuilder;
import com.netease.nimlib.sdk.msg.MsgService;
import com.netease.nimlib.sdk.msg.constant.SessionTypeEnum;
import com.netease.nimlib.sdk.msg.model.IMMessage;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.HashMap;
import java.util.Map;
public class SendMessageHelper {
public static void sendP2PMessage(String account, String msg) {
sendMessage(MessageBuilder.createTextMessage(account, SessionTypeEnum.P2P, msg), new RequestCallback<Void>() {
@Override
public void onSuccess(Void param) {
}
@Override
public void onFailed(int code) {
}
@Override
public void onException(Throwable exception) {
}
});
}
public static void sendMessage(IMMessage message, RequestCallback<Void> callback) {
Map<String, Object> payload = new HashMap<>();
payload.put("skiptype", PushMessageHandler.PAYLOAD_SKIPTYPE_PRIVATE_MSG);
try {
JSONObject dataObj = new JSONObject();
dataObj.putOpt("uid", message.getFromAccount()).putOpt("content", message.getContent());
payload.put("data", dataObj);
} catch (JSONException e) {
e.printStackTrace();
}
payload.put("vivoField", vivoField());
payload.put("hwField", hwField(message));
message.setPushPayload(payload);
NIMClient.getService(MsgService.class)
.sendMessage(message, false)
.setCallback(callback);
}
/**
* vivo推送payload
*
* @return
*/
private static Map<String, Object> vivoField() {
//vivo开启系统推送
int classification = 1;
Map<String, Object> vivoField = new HashMap<>();
vivoField.put("classification", classification);
return vivoField;
}
/**
* 华为推送payload
*
* @return
*/
private static JSONObject hwField(IMMessage message) {
Intent hwIntent = new Intent(Intent.ACTION_VIEW);
String intentStr = String.format(
"yinyoupushscheme://com.huawei.codelabpush/deeplink?sessionID=%s&sessionType=%s",
message.getSessionId(), message.getSessionType()
);
hwIntent.putExtra("skiptype", PushMessageHandler.PAYLOAD_SKIPTYPE_PRIVATE_MSG);
hwIntent.putExtra("uid", message.getFromAccount());
hwIntent.setData(Uri.parse(intentStr));
hwIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
String intentUri = hwIntent.toUri(Intent.URI_INTENT_SCHEME);
JSONObject clickAction = new JSONObject();
JSONObject notification = new JSONObject();
try {
clickAction.putOpt("type", 1)
.putOpt("intent", intentUri);
notification.putOpt("click_action", clickAction);
} catch (JSONException e) {
e.printStackTrace();
}
return notification;
}
}

View File

@@ -0,0 +1,48 @@
package com.mango.moshen.ui.im.adpter
import android.text.TextUtils
import android.view.View
import android.widget.ImageView
import com.chad.library.adapter.base.BaseQuickAdapter
import com.chad.library.adapter.base.BaseViewHolder
import com.mango.core.user.bean.HelloUserInfo
import com.mango.core.user.bean.UserInfo
import com.mango.moshen.R
import com.mango.moshen.ui.utils.ImageLoadUtils
class SayHelloListAdapter :
BaseQuickAdapter<HelloUserInfo, BaseViewHolder>(R.layout.item_say_hello_list) {
override fun convert(helper: BaseViewHolder, item: HelloUserInfo) {
ImageLoadUtils.loadAvatar(
mContext,
item.avatar,
helper.getView(R.id.iv_avatar)
)
helper.setText(R.id.tv_nickname, item.name)
helper.setText(R.id.tv_send_text,item.content)
helper.setText(R.id.tv_online_desc,item.onlineDesc)
val ivUserCharm = helper.getView<ImageView>(R.id.iv_user_charm)
val ivUserLevel = helper.getView<ImageView>(R.id.iv_user_level)
ivUserCharm.visibility = View.GONE
ivUserLevel.visibility = View.GONE
val userLevelVo = item.userLevelVo
if (userLevelVo != null) {
val userLevelUrl = userLevelVo.getExperUrl()
val userCharmUrl = userLevelVo.getCharmUrl()
if (!TextUtils.isEmpty(userLevelUrl)) {
ivUserLevel.visibility = View.VISIBLE
ImageLoadUtils.loadImage(mContext, userLevelUrl, ivUserLevel)
}
if (!TextUtils.isEmpty(userCharmUrl)) {
ivUserCharm.visibility = View.VISIBLE
ImageLoadUtils.loadImage(mContext, userCharmUrl, ivUserCharm)
}
}
helper.addOnClickListener(R.id.iv_avatar,R.id.tv_chat)
}
}

View File

@@ -0,0 +1,111 @@
package com.mango.moshen.ui.im.avtivity
import android.annotation.SuppressLint
import android.content.Context
import android.content.Intent
import androidx.core.view.isVisible
import androidx.recyclerview.widget.LinearLayoutManager
import com.mango.core.user.UserModel
import com.mango.core.user.bean.HelloUserInfo
import com.mango.core.utils.toast
import com.mango.moshen.R
import com.mango.moshen.base.BaseViewBindingActivity
import com.mango.moshen.common.EmptyViewHelper
import com.mango.moshen.databinding.ActivitySayHelloListBinding
import com.mango.moshen.home.dialog.AnchorGradeDialog
import com.mango.moshen.ui.im.SendMessageHelper
import com.mango.moshen.ui.im.adpter.SayHelloListAdapter
import com.mango.moshen.ui.user.UserInfoActivity
import com.mango.moshen.ui.utils.RVDelegate
import com.mango.xchat_android_library.annatation.ActLayoutRes
import com.mango.xchat_android_library.widget.IOSSwitchView.OnSwitchStateChangeListener
import com.netease.nim.uikit.StatusBarUtil
import java.util.*
@ActLayoutRes(R.layout.activity_say_hello_list)
class SayHelloListActivity : BaseViewBindingActivity<ActivitySayHelloListBinding>() {
private lateinit var rvDelegate: RVDelegate<HelloUserInfo>
companion object {
@JvmStatic
fun start(context: Context) {
val starter = Intent(context, SayHelloListActivity::class.java)
context.startActivity(starter)
}
}
@SuppressLint("CheckResult", "SetTextI18n")
override fun init() {
initTitleBar("打招呼")
rvDelegate = RVDelegate.Builder<HelloUserInfo>()
.setRefreshLayout(binding.swipeRefresh)
.setLayoutManager(LinearLayoutManager(this))
.setRecyclerView(binding.recyclerView)
.setAdapter(SayHelloListAdapter())
.setEmptyView(EmptyViewHelper.createEmptyView(this, "暂无用户"))
.build()
rvDelegate.adapter.setOnItemChildClickListener { _, view, position ->
rvDelegate.adapter.getItem(position)?.let {
if (view.id == R.id.iv_avatar) {
UserInfoActivity.Companion.start(this, it.uid)
} else if (view.id == R.id.tv_chat) {
SendMessageHelper.sendP2PMessage(it.uid.toString(), it.content)
NimP2PMessageActivity.start(this, it.uid.toString())
UserModel.get().clickSayHelloChat(it.uid).subscribe()
}
}
}
binding.switchEnable.setOnSwitchStateChangeListener { isOn: Boolean ->
UserModel.get()
.enableSayHello(isOn)
.doOnError {
it.message.toast()
binding.switchEnable.setOn(!isOn, false)
}
.subscribe()
}
binding.swipeRefresh.setOnRefreshListener {
loadData()
}
UserModel.get().sayHelloInfo
.compose(bindToLifecycle())
.subscribe({
AnchorGradeDialog.anchorDrawableResIds[it.currentLevel.uppercase(Locale.getDefault())]?.let { resId ->
binding.ivCurrLevel.setImageResource(resId)
}
binding.tvCurrLevel.text = it.currentLevel
binding.tvCurrFlow.text = "${it.currentMultiple}"
binding.tvFlowTip.text = it.desc
binding.switchEnable.isVisible = true
binding.switchEnable.setOn(it.enable, false)
}, { throwable ->
throwable.printStackTrace()
})
}
@SuppressLint("CheckResult")
private fun loadData() {
UserModel.get().sayHelloList
.compose(bindToLifecycle())
.subscribe({
rvDelegate.setNewData(it)
}, {
it.printStackTrace()
})
}
override fun needSteepStateBar() = true
override fun setStatusBar() {
super.setStatusBar()
StatusBarUtil.transparencyBar(this)
StatusBarUtil.StatusBarLightMode(this)
}
}

View File

@@ -32,6 +32,7 @@ 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.SendMessageHelper;
import com.mango.moshen.ui.im.chat.MVHChatterBoxStart;
import com.mango.moshen.ui.im.model.IMCustomModel;
import com.mango.moshen.ui.webview.CommonWebViewActivity;
@@ -101,7 +102,6 @@ public class MessageFragment extends TFragment implements ModuleProxy, MessageLi
protected InputPanel inputPanel;
protected MessageListPanelEx messageListPanel;
protected AitManager aitManager;
private boolean inRoom;
/**
* 消息接收观察者
*/
@@ -116,6 +116,7 @@ public class MessageFragment extends TFragment implements ModuleProxy, MessageLi
sendMsgReceipt(); // 发送已读回执
}
};
private boolean inRoom;
private View rootView;
private TextView tvChatLimit;
private SessionCustomization customization;
@@ -312,25 +313,7 @@ public class MessageFragment extends TFragment implements ModuleProxy, MessageLi
return false;
}
appendTeamMemberPush(message);
message = changeToRobotMsg(message);
Map<String, Object> payload = new HashMap<>();
payload.put("skiptype", PushMessageHandler.PAYLOAD_SKIPTYPE_PRIVATE_MSG);
try {
JSONObject dataObj = new JSONObject();
dataObj.putOpt("uid", message.getFromAccount()).putOpt("content", message.getContent());
payload.put("data", dataObj);
} catch (JSONException e) {
e.printStackTrace();
}
payload.put("vivoField", vivoField());
payload.put("hwField", hwField(message));
message.setPushPayload(payload);
final IMMessage msg = message;
appendPushConfig(message);
NIMClient.getService(MsgService.class).sendMessage(message, false).setCallback(new RequestCallback<Void>() {
SendMessageHelper.sendMessage(message, new RequestCallback<Void>() {
@Override
public void onSuccess(Void param) {
StatisticManager.Instance().onEvent(StatisticsProtocol.EVENT_PRIVATECHAT_CAHT,
@@ -339,7 +322,7 @@ public class MessageFragment extends TFragment implements ModuleProxy, MessageLi
@Override
public void onFailed(int code) {
sendFailWithBlackList(code, msg);
sendFailWithBlackList(code, message);
}
@Override

View File

@@ -3,8 +3,10 @@ package com.mango.moshen.ui.im.recent
import android.annotation.SuppressLint
import android.view.View
import androidx.core.view.isInvisible
import androidx.core.view.isVisible
import androidx.recyclerview.widget.LinearLayoutManager
import com.mango.core.initial.InitialModel
import com.mango.core.module_hall.hall.bean.RoleType
import com.mango.core.praise.event.PraiseEvent
import com.mango.core.statistic.StatisticManager
import com.mango.core.statistic.protocol.StatisticsProtocol
@@ -23,8 +25,10 @@ import com.mango.moshen.common.widget.dialog.DialogManager.AbsOkDialogListener
import com.mango.moshen.databinding.FragmentRecentListBinding
import com.mango.moshen.home.activity.RelationListActivity
import com.mango.moshen.home.event.ContactTrashEvent
import com.mango.moshen.module_hall.HallDataManager
import com.mango.moshen.room_chat.activity.RoomNewbieActivity
import com.mango.moshen.ui.im.avtivity.NimP2PMessageActivity
import com.mango.moshen.ui.im.avtivity.SayHelloListActivity
import com.mango.moshen.ui.im.recent.adapter.AttentionInRoomAdapter
import com.mango.xchat_android_library.utils.CommonUtils
import com.netease.nim.uikit.business.recent.RecentContactsCallback
@@ -50,7 +54,7 @@ class RecentListFragment : BaseViewBindingFragment<FragmentRecentListBinding>()
private var officialMsgUids: List<String>? = null
@SuppressLint("CheckResult")
@SuppressLint("CheckResult", "SetTextI18n")
override fun init() {
EventBus.getDefault().register(this)
recentContactsFragment = RecentContactsFragment.newInstance(false)
@@ -100,6 +104,26 @@ class RecentListFragment : BaseViewBindingFragment<FragmentRecentListBinding>()
binding.tvRedPointFindNew.visibility = if (isClicked) View.GONE else View.VISIBLE
// 等级限制
setFindNewbieView()
HallDataManager.get().registerHallExist(this) {
if (it == true && HallDataManager.get().roleType != RoleType.OWNER) {
binding.llSayHello.isVisible = true
UserModel.get().sayHelloInfo
.compose(bindToLifecycle())
.subscribe({ helloInfo ->
binding.tvSayHelloNum.text = "${helloInfo.helloCount}人想和你认识"
}, { throwable ->
throwable.printStackTrace()
})
} else {
binding.llSayHello.isVisible = false
}
}
binding.llSayHello.setOnClickListener {
SayHelloListActivity.start(mContext)
}
}
@SuppressLint("CheckResult")

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 405 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="@color/white"/>
<corners android:topLeftRadius="@dimen/dp_16"
android:topRightRadius="@dimen/dp_16"/>
</shape>

View File

@@ -1,38 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.mango.moshen.home.activity.NewUserListActivity">
<com.mango.moshen.base.TitleBar
android:id="@+id/title_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<com.mango.moshen.common.widget.StatusLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
android:id="@+id/srl_refresh_container"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipToPadding="false"
android:paddingLeft="15dp"
android:paddingTop="12dp"
android:paddingRight="15dp"
android:paddingBottom="12dp" />
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
</com.mango.moshen.common.widget.StatusLayout>
</LinearLayout>

View File

@@ -0,0 +1,139 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/white"
android:orientation="vertical">
<View
android:id="@+id/view_bg"
android:layout_width="0dp"
android:layout_height="0dp"
android:background="@drawable/bg_say_hello_top"
app:layout_constraintDimensionRatio="1:1"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<com.mango.moshen.base.TitleBar
android:id="@+id/title_bar"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="44dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<com.mango.xchat_android_library.widget.IOSSwitchView
android:id="@+id/switch_enable"
android:layout_width="42dp"
android:layout_height="23dp"
android:layout_marginEnd="16dp"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="@id/title_bar"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@id/title_bar" />
<TextView
android:id="@+id/tv_level_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="15dp"
android:text="当前主播评级:"
android:textColor="@color/color_1A1A1A"
android:textSize="12sp"
app:layout_constraintBottom_toTopOf="@id/tv_flow_text"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@id/iv_curr_level"
app:layout_constraintVertical_chainStyle="packed" />
<TextView
android:id="@+id/tv_curr_level"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="5dp"
android:includeFontPadding="false"
android:textColor="#FF8400"
android:textSize="24sp"
android:textStyle="bold"
app:layout_constraintBaseline_toBaselineOf="@id/tv_level_text"
app:layout_constraintStart_toEndOf="@id/tv_level_text"
tools:text="s" />
<TextView
android:id="@+id/tv_flow_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:text="当前打招呼流量:"
android:textColor="@color/color_1A1A1A"
android:textSize="14sp"
app:layout_constraintBottom_toTopOf="@id/tv_flow_tip"
app:layout_constraintStart_toStartOf="@id/tv_level_text"
app:layout_constraintTop_toBottomOf="@id/tv_level_text" />
<TextView
android:id="@+id/tv_curr_flow"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="5dp"
android:textColor="#171A58"
android:textSize="16sp"
android:textStyle="bold"
app:layout_constraintBaseline_toBaselineOf="@id/tv_flow_text"
app:layout_constraintStart_toEndOf="@id/tv_flow_text"
tools:text="2倍" />
<TextView
android:id="@+id/tv_flow_tip"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="3dp"
android:text="提升至下一评级可获得3倍流量"
android:textColor="#ffbabbcd"
android:textSize="10sp"
app:layout_constraintBottom_toBottomOf="@id/iv_curr_level"
app:layout_constraintStart_toStartOf="@id/tv_level_text"
app:layout_constraintTop_toBottomOf="@id/tv_flow_text" />
<ImageView
android:id="@+id/iv_curr_level"
android:layout_width="130dp"
android:layout_height="115dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="27dp"
android:src="@drawable/default_cover"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/title_bar" />
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
android:id="@+id/swipe_refresh"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginTop="17dp"
android:background="@drawable/shape_white_top_16dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/iv_curr_level">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="10dp"
android:layout_marginBottom="10dp"
android:clipToPadding="false"
android:paddingTop="10dp" />
</FrameLayout>
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -202,10 +202,44 @@
</LinearLayout>
<LinearLayout
android:id="@+id/fl_attention_online"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="17dp"
android:gravity="center_vertical"
android:orientation="horizontal">
<LinearLayout
android:id="@+id/ll_say_hello"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="15dp"
android:gravity="center"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:drawableTop="@drawable/ic_msg_hello"
android:text="打招呼"
android:textColor="#ff171a58"
android:textSize="12sp" />
<TextView
android:id="@+id/tv_say_hello_num"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#ff8a8cab"
android:textSize="8sp"
tools:text="有30人想和你认识" />
</LinearLayout>
<LinearLayout
android:id="@+id/fl_attention_online"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="15dp"
android:layout_marginEnd="15dp"
android:orientation="vertical"
android:visibility="visible">
@@ -213,20 +247,17 @@
android:id="@+id/rv_attention_online"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="15dp"
android:layout_marginTop="13dp"
android:layout_marginEnd="15dp"
android:paddingBottom="12dp" />
<View
android:layout_width="match_parent"
android:layout_height="1px"
android:layout_marginStart="15dp"
android:layout_marginEnd="15dp"
android:background="#4dd8d8d8" />
</LinearLayout>
</LinearLayout>
<FrameLayout
android:id="@+id/recent_container"
android:layout_width="match_parent"

View File

@@ -1,57 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<com.mango.moshen.common.widget.CircleImageView
android:id="@+id/civ_avatar"
android:layout_width="60dp"
android:layout_height="60dp"
tools:src="@drawable/default_avatar"
android:layout_gravity="center_horizontal" />
<LinearLayout
android:layout_marginTop="10dp"
android:gravity="center_vertical"
android:layout_gravity="center_horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:id="@+id/tv_name"
android:layout_width="wrap_content"
android:layout_weight="1"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:ellipsize="end"
android:maxLines="1"
android:textColor="@color/color_1A1A1A"
android:textSize="@dimen/sp_14"
tools:text="房间名房" />
<ImageView
android:id="@+id/iv_sex"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/dp_5"
android:layout_marginRight="@dimen/dp_5"
android:src="@drawable/ic_gender_female" />
</LinearLayout>
<TextView
android:id="@+id/tv_tutu_id"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="8dp"
android:ellipsize="end"
android:maxLines="1"
android:textColor="@color/color_999999"
android:textSize="12sp"
tools:text="ID:122445" />
</LinearLayout>

View File

@@ -0,0 +1,128 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/root_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingStart="15dp"
android:paddingTop="8dp"
android:paddingEnd="15dp"
android:paddingBottom="8dp"
tools:background="@color/white">
<com.mango.moshen.common.widget.CircleImageView
android:id="@+id/iv_avatar"
android:layout_width="54dp"
android:layout_height="54dp"
android:scaleType="centerCrop"
android:src="@drawable/default_avatar"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/tv_nickname"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/dp_10"
android:ellipsize="end"
android:lines="1"
android:textColor="@color/color_333333"
android:textSize="13sp"
app:layout_constrainedWidth="true"
app:layout_constraintBottom_toTopOf="@id/iv_user_level"
app:layout_constraintStart_toEndOf="@+id/iv_avatar"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_chainStyle="packed"
tools:text="交友厅官方交友厅交友厅官方交友厅" />
<ImageView
android:id="@+id/iv_gender"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_gender_female"
app:layout_constraintBottom_toBottomOf="@id/iv_avatar"
app:layout_constraintEnd_toEndOf="@id/iv_avatar" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/iv_user_level"
android:layout_width="wrap_content"
android:layout_height="17dp"
android:layout_marginTop="4dp"
android:layout_marginEnd="@dimen/dp_3"
android:adjustViewBounds="true"
android:visibility="visible"
app:layout_constraintBottom_toBottomOf="@id/iv_avatar"
app:layout_constraintStart_toStartOf="@id/tv_nickname"
app:layout_constraintTop_toBottomOf="@id/tv_nickname"
tools:src="@mipmap/ic_user_level" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/iv_user_charm"
android:layout_width="wrap_content"
android:layout_height="17dp"
android:layout_marginStart="4dp"
android:layout_marginEnd="3dp"
android:adjustViewBounds="true"
android:visibility="visible"
app:layout_constraintBottom_toBottomOf="@id/iv_user_level"
app:layout_constraintStart_toEndOf="@id/iv_user_level"
tools:src="@drawable/ic_user_charm_level" />
<TextView
android:id="@+id/tv_online_desc"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="在线"
android:textColor="#ffbabbcd"
android:textSize="10sp"
app:layout_constraintBottom_toBottomOf="@id/iv_avatar"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@id/iv_avatar" />
<View
android:id="@+id/view_text"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginTop="3dp"
android:background="@drawable/bg_say_hello_item"
app:layout_constraintDimensionRatio="690:112"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/iv_avatar" />
<TextView
android:id="@+id/tv_send_text"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="7dp"
android:layout_marginEnd="16dp"
android:ellipsize="end"
android:gravity="start"
android:lines="1"
android:text="嗨,小哥哥 认识一下💗嗨,小嗨,小哥哥 认识一下💗嗨,小"
android:textColor="#ff8a8cab"
android:textSize="12sp"
app:layout_constraintBottom_toBottomOf="@id/view_text"
app:layout_constraintEnd_toStartOf="@id/tv_chat"
app:layout_constraintStart_toStartOf="@id/view_text"
app:layout_constraintTop_toTopOf="@id/view_text" />
<TextView
android:id="@+id/tv_chat"
android:layout_width="56dp"
android:layout_height="24dp"
android:layout_marginTop="7dp"
android:layout_marginEnd="16dp"
android:background="@drawable/common_btn_bg"
android:gravity="center"
android:text="和Ta聊"
android:textColor="@color/white"
android:textSize="10sp"
app:layout_constraintBottom_toBottomOf="@id/view_text"
app:layout_constraintEnd_toEndOf="@id/view_text"
app:layout_constraintTop_toTopOf="@id/view_text" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -7,6 +7,7 @@ import androidx.annotation.Nullable;
import androidx.lifecycle.LiveData;
import com.mango.core.base.IModel;
import com.mango.core.bean.response.ServiceResult;
import com.mango.core.home.bean.MainTabInfo;
import com.mango.core.initial.bean.BoxInfo;
import com.mango.core.initial.bean.InitInfo;
@@ -14,6 +15,7 @@ import com.mango.core.initial.bean.InitInfo;
import java.util.List;
import io.reactivex.Single;
import retrofit2.http.GET;
/**
* @author: hewenhao
@@ -55,4 +57,8 @@ public interface IInitialModel extends IModel {
int getTeenagerMode();
int getDefaultHomeTab();
void heartbeat();
void startApp();
}

View File

@@ -14,6 +14,7 @@ import androidx.lifecycle.MutableLiveData;
import com.bumptech.glide.request.FutureTarget;
import com.bumptech.glide.request.target.Target;
import com.mango.core.user.event.LoadLoginUserInfoEvent;
import com.netease.nim.uikit.support.glide.GlideApp;
import com.mango.core.DemoCache;
import com.mango.core.base.BaseModel;
@@ -36,12 +37,22 @@ import com.mango.xchat_android_library.utils.JavaUtil;
import com.mango.xchat_android_library.utils.ListUtils;
import com.mango.xchat_android_library.utils.NetworkUtils;
import com.mango.xchat_android_library.utils.config.BasicConfig;
import com.tencent.bugly.proguard.A;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
import org.reactivestreams.Publisher;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeUnit;
import io.reactivex.Flowable;
import io.reactivex.Observable;
import io.reactivex.ObservableSource;
import io.reactivex.Single;
import io.reactivex.SingleOnSubscribe;
import io.reactivex.SingleSource;
@@ -106,6 +117,7 @@ public class InitialModel extends BaseModel implements IInitialModel {
private InitialModel() {
api = RxNet.create(Api.class);
EventBus.getDefault().register(this);
loadMainTabInfoList();
List<MainTabInfo> tabInfoList = DemoCache.readMainTabInfoList();
if (ListUtils.isListEmpty(tabInfoList)) {
@@ -180,6 +192,12 @@ public class InitialModel extends BaseModel implements IInitialModel {
));
}
@Subscribe(threadMode = ThreadMode.MAIN)
public void onLoadLoginUserInfoEvent(LoadLoginUserInfoEvent event) {
heartbeat();
startApp();
}
@Override
@NonNull
public LiveData<List<MainTabInfo>> getMainTabInfosLiveData() {
@@ -440,6 +458,22 @@ public class InitialModel extends BaseModel implements IInitialModel {
return defaultHomeTab;
}
@Override
public void heartbeat() {
Observable.timer(30, TimeUnit.SECONDS)
.flatMap(aLong -> api.heartbeat())
.subscribeOn(Schedulers.io())
.doFinally(this::heartbeat)
.subscribe();
}
@Override
public void startApp() {
api.startApp()
.subscribeOn(Schedulers.io())
.subscribe();
}
@Override
public int getFindNewbieCharmLevel() {
return findNewbieCharmLevel;
@@ -454,6 +488,22 @@ public class InitialModel extends BaseModel implements IInitialModel {
@GET("/client/init")
Single<ServiceResult<InitInfo>> init();
/**
* 心跳接口
*
* @return -
*/
@POST("/client/heartbeat")
Observable<ServiceResult<String>> heartbeat();
/**
* 心跳接口
*
* @return -
*/
@POST("/client/start_app")
Single<ServiceResult<String>> startApp();
/**
* 获取首页Tab配置
*

View File

@@ -8,8 +8,10 @@ import com.mango.core.bean.response.ServiceResult;
import com.mango.core.home.bean.VisitorInfo;
import com.mango.core.user.bean.GiftAchievementInfo;
import com.mango.core.user.bean.GiftWallInfo;
import com.mango.core.user.bean.HelloUserInfo;
import com.mango.core.user.bean.NewUserInfo;
import com.mango.core.user.bean.ProtocolInfo;
import com.mango.core.user.bean.SayHelloInfo;
import com.mango.core.user.bean.UserDetailInfo;
import com.mango.core.user.bean.UserGameInfo;
import com.mango.core.user.bean.UserInfo;
@@ -18,6 +20,9 @@ import com.mango.core.user.bean.UserRandomConfig;
import java.util.List;
import io.reactivex.Single;
import retrofit2.http.Field;
import retrofit2.http.FormUrlEncoded;
import retrofit2.http.POST;
/**
* Created by chenran on 2017/3/15.
@@ -229,4 +234,34 @@ public interface IUserModel extends IModel {
Single<String> visitUserDetail(long uid);
Single<List<VisitorInfo>> getVisitorUserList(int pageNum, int pageSize);
/**
* 主播评级信息
*
* @return -
*/
Single<SayHelloInfo> getSayHelloInfo();
/**
* 开启关闭自动打招呼
*
* @return -
*/
Single<String> enableSayHello(boolean enable);
/**
* 打招呼列表
*
* @return -
*/
Single<List<HelloUserInfo>> getSayHelloList();
/**
* 点击私聊按钮
*
* @return -
*/
Single<String> clickSayHelloChat(long toUserUid);
}

View File

@@ -22,8 +22,10 @@ import com.mango.core.level.event.LevelUpEvent;
import com.mango.core.noble.NobleUtil;
import com.mango.core.user.bean.GiftAchievementInfo;
import com.mango.core.user.bean.GiftWallInfo;
import com.mango.core.user.bean.HelloUserInfo;
import com.mango.core.user.bean.NewUserInfo;
import com.mango.core.user.bean.ProtocolInfo;
import com.mango.core.user.bean.SayHelloInfo;
import com.mango.core.user.bean.UserDetailInfo;
import com.mango.core.user.bean.UserGameInfo;
import com.mango.core.user.bean.UserInfo;
@@ -65,27 +67,21 @@ import retrofit2.http.Query;
public final class UserModel extends BaseModel implements IUserModel {
private static final String TAG = "UserModel";
private final Api api = RxNet.create(Api.class);
private volatile UserInfo currentUserInfo = null;
private volatile LruCache<Long, UserInfo> cache = new LruCache<>(50);
private final Api api = RxNet.create(Api.class);
//用户信息不全的情况下,currentUserInfo并不会被保存,这里单独保存下预填写的邀请码...
private String preFillInviteCode;
private static final class Helper {
public static final IUserModel INSTANCE = new UserModel();
}
public static IUserModel get() {
return Helper.INSTANCE;
}
private UserModel() {
super();
EventBus.getDefault().register(this);
}
public static IUserModel get() {
return Helper.INSTANCE;
}
/**
* 登录进来接受事件
*
@@ -106,7 +102,6 @@ public final class UserModel extends BaseModel implements IUserModel {
onLogout();
}
/**
* 用户等级升级从后台刷新一下用户信息
*
@@ -127,8 +122,6 @@ public final class UserModel extends BaseModel implements IUserModel {
updateCurrentUserInfo().subscribe();
}
/******************************************************************************************************/
/**
* 登录后第一次获取用户信息
*
@@ -174,6 +167,8 @@ public final class UserModel extends BaseModel implements IUserModel {
}
/******************************************************************************************************/
private void onLogout() {
currentUserInfo = null;
cache.evictAll();
@@ -345,7 +340,6 @@ public final class UserModel extends BaseModel implements IUserModel {
.compose(RxHelper.handleSchedulers());
}
//此方法兼容其他端,其他端最好改为 return Single的同名方法
@Override
public void requestCompleteUserInfo(final UserInfo userInfo, String shareChannel, String shareUid, String roomUid) {
@@ -584,7 +578,6 @@ public final class UserModel extends BaseModel implements IUserModel {
.compose(RxHelper.handleSchedulers());
}
/**
* 重置支付密码
*
@@ -649,7 +642,6 @@ public final class UserModel extends BaseModel implements IUserModel {
.compose(RxHelper.singleMainResult());
}
@Override
public Single<String> useOrDelete(long id, int status) {
return api.useOrDeleteTag(id, status)
@@ -818,7 +810,33 @@ public final class UserModel extends BaseModel implements IUserModel {
.compose(RxHelper.handleSchedulers());
}
@Override
public Single<SayHelloInfo> getSayHelloInfo() {
return api.getSayHelloInfo()
.compose(RxHelper.handleBeanData())
.compose(RxHelper.handleSchedulers());
}
@Override
public Single<String> enableSayHello(boolean enable) {
return api.enableSayHello(enable)
.compose(RxHelper.handleStringData())
.compose(RxHelper.handleSchedulers());
}
@Override
public Single<List<HelloUserInfo>> getSayHelloList() {
return api.getSayHelloList()
.compose(RxHelper.handleBeanData())
.compose(RxHelper.handleSchedulers());
}
@Override
public Single<String> clickSayHelloChat(long toUserUid) {
return api.clickSayHelloChat(toUserUid)
.compose(RxHelper.handleStringData())
.compose(RxHelper.handleSchedulers());
}
private interface Api {
/**
@@ -1043,5 +1061,44 @@ public final class UserModel extends BaseModel implements IUserModel {
@GET("/uservisitrecord/visitUserList")
Single<ServiceResult<List<VisitorInfo>>> getVisitorUserList(@Query("pageNum") int pageNum,
@Query("pageSize") int pageSize);
/**
* 主播评级信息
*
* @return -
*/
@POST("shunt/level_info")
Single<ServiceResult<SayHelloInfo>> getSayHelloInfo();
/**
* 开启关闭自动打招呼
*
* @return -
*/
@FormUrlEncoded
@POST("shunt/enable")
Single<ServiceResult<String>> enableSayHello(@Field("enable") boolean enable);
/**
* 打招呼列表
*
* @return -
*/
@POST("shunt/list")
Single<ServiceResult<List<HelloUserInfo>>> getSayHelloList();
/**
* 点击私聊按钮
*
* @return -
*/
@FormUrlEncoded
@POST("shunt/click_chat")
Single<ServiceResult<String>> clickSayHelloChat(@Field("toUserId") long toUserUid);
}
private static final class Helper {
public static final IUserModel INSTANCE = new UserModel();
}
}

View File

@@ -0,0 +1,13 @@
package com.mango.core.user.bean
import com.mango.core.level.UserLevelVo
data class HelloUserInfo(
val avatar: String = "",
val content: String = "",
val gender: Int = 0,
val name: String = "",
val onlineDesc: String = "",
val uid: Long = 0,
val userLevelVo: UserLevelVo? = null
)

View File

@@ -0,0 +1,9 @@
package com.mango.core.user.bean
data class SayHelloInfo(
val currentLevel: String = "",
val currentMultiple: Int = 0,
val helloCount: Int = 0,
val desc: String = "",
val enable: Boolean = false
)