Compare commits

...

18 Commits

Author SHA1 Message Date
max
1b7e8dd8e8 feat:子模块改用master分支(有google登录) 2024-07-08 18:31:34 +08:00
max
13baa2746d 增加子模块(gms仓库) 2024-07-08 18:31:34 +08:00
max
3a9c338df6 feat:初步实现H5唤起支付逻辑(不完善,用于打内测包验证) 2024-07-08 18:24:37 +08:00
max
cdc1c51fec feat:调整版本号 2024-07-08 11:27:30 +08:00
max
a8191616a3 feat:私聊、公聊、房间、支持垃圾字检测 2024-07-08 11:27:11 +08:00
max
410832690f feat:调整启动背景-logo 2024-07-08 11:27:11 +08:00
max
b1d2f0515b fix:修复麦位空指针异常 2024-07-05 18:26:14 +08:00
max
82c2d8c25d feat:修改启动页背景 2024-07-04 19:17:35 +08:00
max
549088c99e feat:完成公聊厅-头条UI调整 2024-07-04 19:01:24 +08:00
max
5910e7c5fd feat:配置云信-安全通ID 2024-07-04 17:52:42 +08:00
max
53aed7599a feat:头条间距微调 2024-07-04 16:46:12 +08:00
max
8aebb7c2c2 feat:调整房间公聊-头条UI 2024-07-04 16:38:32 +08:00
max
3a120bf5f0 fix:修复反馈-联系客服-排序问题 2024-07-04 16:13:38 +08:00
max
2a0d8f06fa feat:头饰支持SVGA(个人资料页、房间个人资料弹窗、动态列表、动态详情、我的头饰列表、公聊厅、房间麦位) 2024-07-04 15:19:11 +08:00
max
495bae0d00 fix:修复反馈-bug 2024-07-03 19:40:59 +08:00
max
2af7cec8dd feat:完成反馈功能 2024-07-03 16:47:14 +08:00
max
e9e4da8d60 feat:补充启动时更新ticket逻辑 2024-07-02 17:36:08 +08:00
max
14c1805a2b feat:完成部分页面主题UI修改 2024-07-02 15:28:16 +08:00
170 changed files with 2456 additions and 1297 deletions

4
.gitmodules vendored Normal file
View File

@@ -0,0 +1,4 @@
[submodule "modules/module_google"]
path = modules/module_google
url = https://e.coding.net/chwllive/peko/peko-android-gms.git
branch = molistar

View File

@@ -221,7 +221,6 @@ dependencies {
api "com.jzxiang.pickerview:TimePickerDialog:1.0.1"
api "com.github.zyyoona7:EasyPopup:1.0.2"
api "com.github.donkingliang:LabelsView:1.6.5"
api "com.github.yyued:SVGAPlayer-Android:2.6.1"
api "com.ms-square:expandableTextView:0.1.4"
annotationProcessor 'androidx.annotation:annotation:1.6.0'

View File

@@ -943,6 +943,12 @@
android:launchMode="singleTop"
android:screenOrientation="portrait"
android:windowSoftInputMode="stateHidden|adjustNothing" />
<activity
android:windowSoftInputMode="adjustPan"
android:name=".ui.feedback.FeedbackActivity"
android:screenOrientation="portrait" />
<activity android:name=".ui.debug.DebugActivity"
android:screenOrientation="portrait"/>
</application>
</manifest>

View File

@@ -325,7 +325,9 @@ public class App extends BaseApp {
BasicConfig.INSTANCE.setVoiceDir(Constants.VOICE_DIR);
BasicConfig.INSTANCE.setCacheDir(Constants.CACHE_DIR);
BasicConfig.INSTANCE.setImageDir(Constants.IMAGE_CACHE_DIR);
com.example.lib_utils.log.LogUtil.INSTANCE.setConsolePrinterEnabled(BuildConfig.DEBUG);
// TODO 临时调整
com.example.lib_utils.log.LogUtil.INSTANCE.setConsolePrinterEnabled(true);
// com.example.lib_utils.log.LogUtil.INSTANCE.setConsolePrinterEnabled(BuildConfig.DEBUG);
}
/**
@@ -484,7 +486,6 @@ public class App extends BaseApp {
ChannelModel.get();
MarketVerifyModel.get();
GiftModel.get();
GiftModel.get().tryLoadGiftList();
// 模厅
HallDataManager.get().application();
//全局处理

View File

@@ -42,6 +42,7 @@ import com.alibaba.fastjson.JSONObject;
import com.chwl.app.notify.RoomNotifyManager;
import com.chwl.app.ui.webview.baishun.BaiShunGameWebFragment;
import com.chwl.app.ui.webview.baishun.IBaiShunGameListener;
import com.chwl.library.widget.SVGAView;
import com.chwl.core.monsterhunting.bean.MonsterDataBean;
import com.chwl.core.room.game.bean.BaiShunGameConfig;
import com.chwl.core.support.room.AudioRoomContext;
@@ -177,6 +178,15 @@ public class AVRoomActivity extends BaseMvpActivity<IAvRoomView, AvRoomPresenter
private static final String TAG = "AVRoomActivity";
private static final int SHOW_RED_DIALOG_MAX = 10;
public static boolean isPKModel = false;
private static SVGAView.SVGACache svgaCache;
public static SVGAView.SVGACache getSvgaCache() {
if (svgaCache == null) {
svgaCache = SVGAView.newCache(20);
}
return svgaCache;
}
/**
* 管理限制进房
*/
@@ -899,6 +909,10 @@ public class AVRoomActivity extends BaseMvpActivity<IAvRoomView, AvRoomPresenter
GiftModel.get().cancelCountDownTimer();
EventBus.getDefault().unregister(this);
DemoCache.saveBoolean("FirstCharge", false);
if (svgaCache != null) {
svgaCache.clear();
}
svgaCache = null;
super.onDestroy();
}

View File

@@ -15,8 +15,12 @@ import androidx.annotation.Nullable;
import androidx.lifecycle.Observer;
import androidx.recyclerview.widget.RecyclerView;
import com.chwl.app.avroom.activity.AVRoomActivity;
import com.chwl.app.utils.AvatarHelper;
import com.chwl.library.widget.SVGAView;
import com.chwl.core.utils.extension.StringExtensionKt;
import com.coorchice.library.SuperTextView;
import com.example.lib_utils.StringUtils2;
import com.netease.nim.uikit.common.util.string.StringUtil;
import com.opensource.svgaplayer.SVGAImageView;
import com.chwl.app.R;
@@ -145,7 +149,7 @@ public abstract class BaseMicroViewAdapter extends RecyclerView.Adapter<Recycler
SVGAImageView ivHalo;
@Nullable
ImageView ivHeadWear;
SVGAView ivHeadWear;
@Nullable
ImageView ivCharmLevelTag;
@@ -171,6 +175,9 @@ public abstract class BaseMicroViewAdapter extends RecyclerView.Adapter<Recycler
ivUpImage.setOnClickListener(this);
ivLockImage.setOnClickListener(this);
ivAvatar.setOnClickListener(this);
if (ivHeadWear != null) {
ivHeadWear.bindCache(AVRoomActivity.getSvgaCache());
}
}
public void clear() {
@@ -276,6 +283,7 @@ public abstract class BaseMicroViewAdapter extends RecyclerView.Adapter<Recycler
private void clearHeadWear() {
if (ivHeadWear == null) return;
ivHeadWear.clearAnimation();
ivHeadWear.stopAnimation();
ivHeadWear.setImageDrawable(null);
ivHeadWear.setTag(R.id.mic_item_head_wear, null);
ivHeadWear.setVisibility(View.GONE);
@@ -299,10 +307,13 @@ public abstract class BaseMicroViewAdapter extends RecyclerView.Adapter<Recycler
private void updateNobleView(MicMemberInfo chatRoomMember) {
if (ivHeadWear == null) return;
String headWear = chatRoomMember.getHeadWearUrl();
int headWearType = chatRoomMember.getHeadWearType();
if (TextUtils.isEmpty(headWear)) {
headWear = NobleUtil.getHeadResource(HeadWearInfo.EFFECT, chatRoomMember) != null ?
NobleUtil.getHeadResource(HeadWearInfo.EFFECT, chatRoomMember) :
NobleUtil.getHeadResource(HeadWearInfo.PIC, chatRoomMember);
String type = NobleUtil.getHeadResource(HeadWearInfo.TYPE, chatRoomMember);
headWearType = StringUtils2.INSTANCE.toInt(type);
}
String nobleHeadWear = (String) NobleUtil.getResource(NobleResourceType.KEY_HEAD_WEAR, chatRoomMember);
if (!TextUtils.isEmpty(headWear)) {
@@ -310,7 +321,7 @@ public abstract class BaseMicroViewAdapter extends RecyclerView.Adapter<Recycler
//只有头饰发生改变才更新,防止闪烁
if (!headWear.equals(ivHeadWear.getTag(R.id.mic_item_head_wear))) {
ivHeadWear.setTag(R.id.mic_item_head_wear, headWear);
NobleUtil.loadMicHeadWear(headWear, ivHeadWear, R.id.mic_item_head_wear, headWear);
AvatarHelper.loadAvatarFrame(ivHeadWear, headWear, headWearType);
}
} else if (!TextUtils.isEmpty(nobleHeadWear)) {
// 头饰

View File

@@ -2,7 +2,6 @@ package com.chwl.app.avroom.adapter;
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Color;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -13,8 +12,6 @@ import androidx.recyclerview.widget.RecyclerView;
import com.chwl.app.R;
import com.chwl.core.bean.RoomQueueInfo;
import com.chwl.core.manager.AvRoomDataManager;
import com.chwl.library.utils.ResUtil;
/**
* @author xiaoyu

View File

@@ -2,6 +2,7 @@ package com.chwl.app.avroom.headline
import android.content.Context
import android.util.AttributeSet
import android.view.Gravity
import android.view.LayoutInflater
import androidx.core.view.isVisible
import androidx.databinding.DataBindingUtil
@@ -9,12 +10,15 @@ import com.chwl.app.R
import com.chwl.app.databinding.RoomHeadlineWidgetBinding
import com.chwl.app.public_chat.core.ChatRoomClient
import com.chwl.app.public_chat.core.ChatRoomClientManager
import com.chwl.app.ui.utils.loadAvatar
import com.chwl.core.im.custom.bean.CustomAttachment
import com.chwl.core.im.custom.bean.HeadlineChangedAttachment
import com.chwl.core.public_chat_hall.bean.HeadlineBean
import com.chwl.core.public_chat_hall.model.PublicChatModel
import com.chwl.core.support.room.FrameLayoutRoomWidget
import com.chwl.core.support.room.RoomView
import com.example.lib_utils.AppUtils
import com.example.lib_utils.UiUtils
import com.netease.nimlib.sdk.chatroom.model.ChatRoomMessage
import com.netease.nimlib.sdk.msg.constant.MsgTypeEnum
@@ -44,6 +48,12 @@ class RoomHeadlineWidget : FrameLayoutRoomWidget {
defStyleRes: Int
) : super(context, attrs, defStyleAttr, defStyleRes)
init {
if (UiUtils.isRtl(AppUtils.getApp())) {
binding.tvHeadlineContent.gravity = Gravity.RIGHT
}
}
override fun onStart(roomView: RoomView) {
super.onStart(roomView)
if (!isInEditMode) {
@@ -89,13 +99,11 @@ class RoomHeadlineWidget : FrameLayoutRoomWidget {
}
private fun updateHeadline(data: HeadlineBean?) {
val content = data?.content
if (data?.isValid() == true && !content.isNullOrEmpty()) {
binding.tvHeadlineContent.text = content
this.isVisible = true
} else {
this.isVisible = false
}
binding.tvHeadlineContent.text = data?.content ?: ""
binding.ivAvatar.loadAvatar(data?.avatar)
binding.tvName.text = "${data?.nick ?: ""} :"
binding.tvMoney.text = data?.payMoneyNum?.toString() ?: "0"
this.isVisible = data?.isValid() == true && !data.content.isNullOrEmpty()
}
override fun onStop() {

View File

@@ -6,7 +6,6 @@ import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.animation.AccelerateDecelerateInterpolator;
@@ -14,7 +13,7 @@ import android.widget.RelativeLayout;
import androidx.annotation.NonNull;
import com.chwl.core.helper.PathHelper;
import com.chwl.library.utils.PathHelper;
import com.chwl.library.download.DownloadException;
import com.chwl.library.download.DownloadManager;
import com.chwl.library.download.DownloadRequest;

View File

@@ -17,7 +17,6 @@ import com.chwl.app.databinding.PhotoDialogBinding
import com.chwl.app.ui.widget.dialog.CommonTipDialog
import com.chwl.library.common.base.BaseDialogFragment
import com.chwl.library.common.photo.PhotoProvider
import com.chwl.library.common.photo.PhotoProviderNew
import com.chwl.library.common.util.PhotoCompressCallback
import com.chwl.library.common.util.PhotoCompressUtil
import com.chwl.library.common.util.PhotosCompressCallback
@@ -84,7 +83,7 @@ class PhotoDialog : BaseDialogFragment<PhotoDialogBinding>(), EasyPermissions.Pe
if (Build.VERSION.SDK_INT >= 33) Manifest.permission.READ_MEDIA_IMAGES else Manifest.permission.READ_EXTERNAL_STORAGE
)
} else {
PhotoProviderNew.photoProvider(this, resultCode = REQUEST_CODE_OPEN_PHOTO_PROVIDER)
PhotoProvider.photoProvider(this, resultCode = REQUEST_CODE_OPEN_PHOTO_PROVIDER)
}
}
@@ -118,7 +117,7 @@ class PhotoDialog : BaseDialogFragment<PhotoDialogBinding>(), EasyPermissions.Pe
if (Build.VERSION.SDK_INT >= 33) Manifest.permission.READ_MEDIA_IMAGES else Manifest.permission.READ_EXTERNAL_STORAGE
)
} else {
PhotoProviderNew.photoCamera(this, REQUEST_CODE_OPEN_CAMERA_PROVIDER)
PhotoProvider.photoCamera(this, REQUEST_CODE_OPEN_CAMERA_PROVIDER)
}
}

View File

@@ -1,72 +0,0 @@
package com.chwl.app.decoration.adapter;
import android.view.View;
import com.chwl.app.R;
import com.chwl.app.bindadapter.BaseAdapter;
import com.chwl.app.bindadapter.BindingViewHolder;
import com.chwl.app.databinding.ItemHeadWearBinding;
import com.chwl.core.decoration.headwear.bean.HeadWearInfo;
import com.chwl.core.noble.NobleUtil;
import com.chwl.library.utils.ListUtils;
/**
* Created by huangmeng1 on 2018/5/10.
*/
public class HeadWearShopAdapter extends BaseAdapter<HeadWearInfo> {
private int selectPosition;
public int getSelectPosition() {
return selectPosition;
}
public void setSelectPosition(int selectPosition) {
notifyItemChanged(this.selectPosition);
this.selectPosition = selectPosition;
notifyItemChanged(this.selectPosition);
}
public HeadWearShopAdapter(int layoutResId, int brid) {
super(layoutResId, brid);
}
@Override
protected void convert(BindingViewHolder helper, HeadWearInfo item) {
super.convert(helper, item);
ItemHeadWearBinding binding = (ItemHeadWearBinding) helper.getBinding();
binding.llRoot.setSelected(selectPosition == helper.getAdapterPosition());
NobleUtil.loadHeadWears(item.getPic(), binding.ivHeadWear);
binding.setSelectPosition(selectPosition == helper.getAdapterPosition());
if (item.getLabelType() == HeadWearInfo.LABEL_TYPE_NORMAL) {
binding.ivTag.setVisibility(View.GONE);
} else if (HeadWearInfo.LABEL_TYPE_NEW == item.getLabelType()) {
binding.ivTag.setVisibility(View.VISIBLE);
binding.ivTag.setImageResource(R.drawable.ic_mark_new);
} else if (HeadWearInfo.LABEL_TYPE_DISCOUNT == item.getLabelType()) {
binding.ivTag.setVisibility(View.VISIBLE);
binding.ivTag.setImageResource(R.drawable.ic_mark_discount);
} else if (HeadWearInfo.LABEL_TYPE_LIMIT == item.getLabelType()) {
binding.ivTag.setVisibility(View.VISIBLE);
binding.ivTag.setImageResource(R.drawable.ic_mark_limit);
} else if (HeadWearInfo.LABEL_TYPE_EXCLUSIVE == item.getLabelType()) {
binding.ivTag.setVisibility(View.VISIBLE);
binding.ivTag.setImageResource(R.drawable.ic_mark_exclusive);
}
binding.tvHeadName.setText(item.getName() + "");
}
public void setCarInfoHasBeenBought(HeadWearInfo carInfo) {
if (carInfo.getHeadwearId() <= 0 || ListUtils.isListEmpty(mData)) return;
int index = mData.indexOf(carInfo);
if (index == -1) return;
mData.get(index).setStatus(HeadWearInfo.STATUS_IN_USED);
notifyItemChanged(index);
}
}

View File

@@ -6,9 +6,11 @@ import com.chwl.app.R;
import com.chwl.app.bindadapter.BaseAdapter;
import com.chwl.app.bindadapter.BindingViewHolder;
import com.chwl.app.databinding.ItemMyHeadWearBinding;
import com.chwl.app.utils.AvatarHelper;
import com.chwl.core.decoration.headwear.bean.HeadWearInfo;
import com.chwl.core.noble.NobleUtil;
import com.chwl.library.utils.ResUtil;
import com.chwl.library.widget.SVGAView;
/**
* Created by huangmeng1 on 2018/5/11.
@@ -20,11 +22,14 @@ public class MyHeadWearAdapter extends BaseAdapter<HeadWearInfo> {
super(layoutResId, brid);
}
private SVGAView.SVGACache svgaCache = SVGAView.newCache(10);
@Override
protected void convert(BindingViewHolder helper, HeadWearInfo item) {
super.convert(helper, item);
ItemMyHeadWearBinding binding = (ItemMyHeadWearBinding) helper.getBinding();
NobleUtil.loadHeadWears(item.getPic(), binding.ivCarCover);
binding.ivCarCover.bindCache(svgaCache);
AvatarHelper.loadAvatarFrame(binding.ivCarCover, item.getFirstUrl(), item.getType());
helper.addOnClickListener(R.id.tv_used);
if (item.getLabelType() == HeadWearInfo.LABEL_TYPE_NORMAL) {

View File

@@ -39,8 +39,8 @@ public class HomeIndicatorAdapter extends CommonNavigatorAdapter {
@Override
public IPagerTitleView getTitleView(Context context, final int i) {
ScaleTransitionPagerTitleView scaleTransitionPagerTitleView = new ScaleTransitionPagerTitleView(context, true);
scaleTransitionPagerTitleView.setNormalColor(ContextCompat.getColor(context, R.color.white_transparent_60));
scaleTransitionPagerTitleView.setSelectedColor(ContextCompat.getColor(context, R.color.color_FFFFFF));
scaleTransitionPagerTitleView.setNormalColor(ContextCompat.getColor(context, R.color.color_990C1D18));
scaleTransitionPagerTitleView.setSelectedColor(ContextCompat.getColor(context, R.color.color_0C1D18));
scaleTransitionPagerTitleView.setMinScale(minScale);
scaleTransitionPagerTitleView.setTextSize(textSize);
int padding = UIUtil.dip2px(context, 13);
@@ -59,10 +59,10 @@ public class HomeIndicatorAdapter extends CommonNavigatorAdapter {
public IPagerIndicator getIndicator(Context context) {
LinePagerIndicator indicator = new LinePagerIndicator(context);
indicator.setMode(LinePagerIndicator.MODE_EXACTLY);
indicator.setLineHeight(UIUtil.dip2px(mContext, 2.5));
indicator.setRoundRadius(UIUtil.dip2px(mContext, 1.5));
indicator.setLineWidth(UIUtil.dip2px(mContext, 10));
indicator.setColors(context.getResources().getColor(R.color.color_10ECD6));
indicator.setLineHeight(context.getResources().getDimensionPixelOffset(R.dimen.dp_4));
indicator.setRoundRadius(context.getResources().getDimensionPixelOffset(R.dimen.dp_2));
indicator.setLineWidth(context.getResources().getDimensionPixelOffset(R.dimen.dp_13));
indicator.setColors(context.getResources().getColor(R.color.color_002512));
FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
// lp.bottomMargin = mBottomMargin;
indicator.setLayoutParams(lp);

View File

@@ -15,7 +15,12 @@ import androidx.databinding.DataBindingUtil;
import com.bumptech.glide.request.RequestOptions;
import com.chwl.app.ui.login.LoginPasswordActivity;
import com.chwl.core.auth.AuthModel;
import com.chwl.core.bean.response.result.TicketResult;
import com.chwl.core.gift.GiftModel;
import com.chwl.library.language.LanguageHelper;
import com.chwl.library.utils.SingleToastUtil;
import com.example.lib_utils.log.LogUtil;
import com.netease.nim.uikit.StatusBarUtil;
import com.netease.nim.uikit.support.glide.GlideApp;
import com.chwl.app.MainActivity;
@@ -32,6 +37,10 @@ import com.chwl.core.utils.OaidUtil;
import com.chwl.core.utils.SharedPreferenceUtils;
import com.chwl.library.common.util.DeviceUtil;
import io.reactivex.SingleObserver;
import io.reactivex.disposables.CompositeDisposable;
import io.reactivex.disposables.Disposable;
/**
* @author xiaoyu
* @date 2017/12/30
@@ -43,8 +52,15 @@ public class SplashActivity extends AppCompatActivity implements View.OnClickLis
private ActivitySplashBinding mBinding;
private SplashComponent mLocalSplashVo;
private CompositeDisposable disposable = new CompositeDisposable();
// ticket状态 -1:加载失败、0:加载中、1:加载成功
private int ticketState = 0;
private volatile boolean needJump = false;
private Runnable jumpRunnable;
public static void start(Context context) {
Intent starter = new Intent(context, SplashActivity.class);
context.startActivity(starter);
@@ -72,9 +88,10 @@ public class SplashActivity extends AppCompatActivity implements View.OnClickLis
// 从堆栈恢复不再重复解析之前的intent
setIntent(new Intent());
}
initiate();
StatusBarUtil.transparencyBar(this);
StatusBarUtil.StatusBarLightMode(this);
initTicket();
initiate();
}
@Override
@@ -145,8 +162,12 @@ public class SplashActivity extends AppCompatActivity implements View.OnClickLis
}
public void jumpActivity(Intent intent) {
AccountInfo currentAccountInfo = DemoCache.readCurrentAccountInfo();
if (currentAccountInfo == null || TextUtils.isEmpty(currentAccountInfo.getAccess_token())) {
jumpRunnable = () -> jumpActivityImpl(intent);
next();
}
public void jumpActivityImpl(Intent intent) {
if (!AuthModel.get().isLogin()) {
NimMiddleActivity.openCommunity = false;
LoginPasswordActivity.start(this);
finish();
@@ -190,4 +211,53 @@ public class SplashActivity extends AppCompatActivity implements View.OnClickLis
}
private void initTicket() {
ticketState = 0;
if (!AuthModel.get().isLogin()) {
ticketState = -1;
next();
return;
}
AuthModel.get().refreshTicket().subscribe(new SingleObserver<TicketResult>() {
@Override
public void onSubscribe(Disposable d) {
disposable.add(d);
}
@Override
public void onSuccess(TicketResult ticketResult) {
LogUtil.d("SplashActivity", "initTicket onSuccess", false);
onTicketSuccess();
ticketState = 1;
next();
}
@Override
public void onError(Throwable throwable) {
LogUtil.d("SplashActivity", "initTicket throwable:" + throwable.getMessage(), false);
SingleToastUtil.showToast(throwable.getMessage());
AuthModel.get().reset();
ticketState = -1;
next();
}
});
}
private void onTicketSuccess() {
GiftModel.get().tryLoadGiftList();
}
private void next() {
if (ticketState != 0 && jumpRunnable != null) {
jumpRunnable.run();
}
}
@Override
protected void onDestroy() {
super.onDestroy();
if (disposable != null && !disposable.isDisposed()) {
disposable.dispose();
}
}
}

View File

@@ -3,7 +3,7 @@ package com.chwl.app.support
import androidx.lifecycle.viewModelScope
import com.chwl.app.BuildConfig
import com.chwl.app.base.BaseViewModel
import com.chwl.core.helper.PathHelper
import com.chwl.library.utils.PathHelper
import com.chwl.core.home.model.HomeModel
import com.chwl.library.common.util.SPUtils
import com.chwl.library.download.DownloadException

View File

@@ -0,0 +1,50 @@
package com.chwl.app.ui.debug
import com.chwl.app.base.BaseViewBindingActivity
import com.chwl.app.databinding.DebugActivityBinding
import com.netease.nim.uikit.StatusBarUtil
class DebugActivity : BaseViewBindingActivity<DebugActivityBinding>() {
override fun init() {
initWhiteTitleBar("调试")
initSVGAList()
}
private fun initSVGAList() {
val adapter = DebugAdapter()
binding.recyclerView.adapter = adapter
// binding.recyclerView.setItemViewCacheSize(-1)
val svgaList = listOf(
"https://image.pekolive.com/花和玫瑰.svga",
"https://image.pekolive.com/firecrown.svga",
"https://image.pekolive.com/ningtangchengbaoqietu.svga",
"https://image.pekolive.com/xunmengfengche.svga",
"https://image.pekolive.com/tonghuaqiyuan1334.svga",
"https://image.pekolive.com/mengquyinhe.svga",
"https://image.pekolive.com/duqinghuashu.svga",
"https://image.pekolive.com/juzhijingling.svga",
"https://image.pekolive.com/3121_aixintouwei.svga",
"https://image.pekolive.com/4051_langmanyewan.svga"
)
val list = ArrayList<String>()
list.addAll(svgaList)
list.addAll(svgaList)
adapter.setNewData(list)
binding.btnRefreshAll.setOnClickListener {
adapter.notifyDataSetChanged()
}
binding.btnRefresh.setOnClickListener {
adapter.notifyItemChanged(5, true)
}
}
override fun needSteepStateBar(): Boolean {
return true
}
override fun setStatusBar() {
super.setStatusBar()
StatusBarUtil.transparencyBar(this)
StatusBarUtil.StatusBarLightMode(this)
}
}

View File

@@ -0,0 +1,47 @@
package com.chwl.app.ui.debug
import com.chad.library.adapter.base.BaseQuickAdapter
import com.chad.library.adapter.base.BaseViewHolder
import com.chwl.app.R
import com.chwl.library.widget.SVGAView
import com.example.lib_utils.log.ILog
class DebugAdapter : BaseQuickAdapter<String, BaseViewHolder>(R.layout.debug_item_svga), ILog {
private val svgaCache = SVGAView.newCache(10)
override fun convertPayloads(
helper: BaseViewHolder,
item: String?,
payloads: MutableList<Any>
) {
super.convertPayloads(helper, item, payloads)
logD("convertPayloads holder:${helper.absoluteAdapterPosition} #${helper.hashCode()} SVGAView")
val svgaView = helper.getView<SVGAView>(R.id.svga_view)
svgaView.loadUrl(item)
}
override fun convert(helper: BaseViewHolder, item: String?) {
logD("convert holder:${helper.absoluteAdapterPosition} #${helper.hashCode()} SVGAView")
helper.setText(R.id.tv_name, helper.absoluteAdapterPosition.toString())
val item = getItem(helper.bindingAdapterPosition)
val svgaView = helper.getView<SVGAView>(R.id.svga_view)
svgaView.bindCache(svgaCache)
svgaView.setLogTag(helper.absoluteAdapterPosition.toString())
svgaView.loadUrl(item)
}
override fun onViewAttachedToWindow(holder: BaseViewHolder) {
super.onViewAttachedToWindow(holder)
logD("onViewAttachedToWindow holder:${holder.absoluteAdapterPosition} #${holder.hashCode()} SVGAView")
// val item = getItem(holder.bindingAdapterPosition)
// val svgaView = holder.getView<SVGAView>(R.id.svga_view)
// svgaView.bindCache(SVGAView.newCache(10))
// svgaView.setLogTag(holder.absoluteAdapterPosition.toString())
// svgaView.loadUrl(item)
}
override fun onViewDetachedFromWindow(holder: BaseViewHolder) {
super.onViewDetachedFromWindow(holder)
logD("onViewDetachedFromWindow holder:${holder.absoluteAdapterPosition} #${holder.hashCode()} SVGAView")
}
}

View File

@@ -0,0 +1,61 @@
package com.chwl.app.ui.feedback
import android.content.ClipData
import android.content.ClipboardManager
import android.content.Context
import android.view.WindowManager
import com.chwl.app.R
import com.chwl.app.base.BaseBindingDialog
import com.chwl.app.databinding.FeedbackCustomerServiceDialogBinding
import com.chwl.app.ui.widget.recyclerview.decoration.SpacingDecoration
import com.chwl.library.annatation.ActLayoutRes
import com.chwl.library.utils.SingleToastUtil
@ActLayoutRes(R.layout.feedback_customer_service_dialog)
class CustomerServiceDialog(context: Context, val map: Map<String, String?>) :
BaseBindingDialog<FeedbackCustomerServiceDialogBinding>(context, R.style.dialog) {
private val adapter = CustomerServiceItemAdapter()
override fun onStart() {
width = WindowManager.LayoutParams.MATCH_PARENT
super.onStart()
}
override fun init() {
binding.layoutRoot.setOnClickListener {
dismiss()
}
binding.tvNext.setOnClickListener {
dismiss()
}
binding.recyclerView.addItemDecoration(
SpacingDecoration(
0,
context.resources.getDimensionPixelOffset(R.dimen.dp_10),
false
)
)
binding.recyclerView.adapter = adapter
val list = map.map {
it
}
adapter.setNewData(list)
adapter.setOnItemChildClickListener { adapter, view, position ->
val text = this.adapter.getItem(position)?.value
if (text != null) {
copyText(text)
}
}
}
private fun copyText(text: String) {
try {
val cm =
context?.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
cm.setPrimaryClip(ClipData.newPlainText("text", text))
SingleToastUtil.showToast(R.string.have_copy)
} catch (e: Exception) {
SingleToastUtil.showToast(e.toString())
}
}
}

View File

@@ -0,0 +1,34 @@
package com.chwl.app.ui.feedback
import android.annotation.SuppressLint
import android.view.Gravity
import android.view.ViewGroup
import android.widget.TextView
import com.chad.library.adapter.base.BaseQuickAdapter
import com.chad.library.adapter.base.BaseViewHolder
import com.chwl.app.R
import com.example.lib_utils.AppUtils
import com.example.lib_utils.UiUtils
class CustomerServiceItemAdapter :
BaseQuickAdapter<Map.Entry<String, String?>, BaseViewHolder>(R.layout.feedback_customer_service_item) {
private var isRTL = UiUtils.isRtl(AppUtils.getApp())
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BaseViewHolder {
return super.onCreateViewHolder(parent, viewType).apply {
this.addOnClickListener(R.id.layout_copy)
val textView = getView<TextView>(R.id.tv_content)
if (isRTL) {
textView.gravity = Gravity.RIGHT
}
}
}
@SuppressLint("SetTextI18n")
override fun convert(helper: BaseViewHolder, item: Map.Entry<String, String?>) {
val textView = helper.getView<TextView>(R.id.tv_content)
textView.text = "${item.key}: ${item.value ?: ""}"
}
}

View File

@@ -0,0 +1,353 @@
package com.chwl.app.ui.feedback
import android.Manifest
import android.annotation.SuppressLint
import android.content.Intent
import android.os.Build
import android.widget.ImageView.ScaleType
import androidx.activity.viewModels
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
import com.chwl.app.R
import com.chwl.app.base.BaseViewBindingActivity
import com.chwl.app.databinding.FeedbackActivityBinding
import com.chwl.app.ui.utils.load
import com.chwl.app.ui.widget.dialog.CommonTipDialog
import com.chwl.core.file.FileModel
import com.chwl.core.home.bean.FeedbackTypeBean
import com.chwl.library.common.photo.PhotoProvider
import com.chwl.library.common.photo.PhotoProvider.photoProvider
import com.chwl.library.common.util.PhotoCompressUtil
import com.chwl.library.common.util.PhotosCompressCallback
import com.chwl.library.easypermisssion.EasyPermissions
import com.chwl.library.easyphoto.utils.settings.SettingsUtils
import com.chwl.library.utils.ResUtil
import com.chwl.library.utils.SingleToastUtil
import com.example.lib_utils.SolveEditTextScrollClash
import com.example.lib_utils.ktx.getColorById
import com.example.lib_utils.ktx.setOnInputChangedListener
import com.example.lib_utils.ktx.singleClick
import com.example.lib_utils.spannable.SpannableTextBuilder
import com.google.android.flexbox.FlexDirection
import com.google.android.flexbox.FlexWrap
import com.google.android.flexbox.FlexboxLayoutManager
import com.google.android.flexbox.JustifyContent
import com.hjq.toast.ToastUtils
import com.netease.nim.uikit.StatusBarUtil
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch
class FeedbackActivity : BaseViewBindingActivity<FeedbackActivityBinding>(),
EasyPermissions.PermissionCallbacks {
private val PERMISSION_CODE_STORAGE = 12
private val REQUEST_CODE_OPEN_PHOTO_PROVIDER = 111 // 从相册中选择
private val viewModel: FeedbackViewModel by viewModels()
private val adapter = FeedbackTypeAdapter()
private var compressJob: Job? = null
private var wantShowCustomerService = false
private var imagePath: String? = null
private var imageUrl: String? = null
override fun init() {
initWhiteTitleBar(ResUtil.getString(R.string.feedback_title))
initView()
initEvent()
initObserve()
refreshSubmitState()
}
private fun initView() {
val flexBoxLayoutManager = FlexboxLayoutManager(context)
flexBoxLayoutManager.flexDirection = FlexDirection.ROW
flexBoxLayoutManager.flexWrap = FlexWrap.WRAP
flexBoxLayoutManager.justifyContent = JustifyContent.FLEX_START
binding.recyclerViewType.layoutManager = flexBoxLayoutManager
binding.recyclerViewType.adapter = adapter
binding.etContent.setOnTouchListener(SolveEditTextScrollClash(binding.etContent))
}
private fun initEvent() {
adapter.setOnItemClickListener { adapter, view, position ->
this.adapter.selectItem(this.adapter.getItem(position))
refreshSubmitState()
}
binding.tvSubmit.singleClick {
dialogManager.showProgressDialog(this)
submit()
}
binding.ivImage.singleClick {
checkStoragePermission()
}
binding.ivCustomerService.singleClick {
showCustomerServiceDialog()
}
binding.etContent.setOnInputChangedListener {
updateContentInputTips(this)
refreshSubmitState()
true
}
binding.etContact.setOnInputChangedListener {
refreshSubmitState()
true
}
}
private fun initObserve() {
viewModel.loadingLiveData.observe(this) {
if (it) dialogManager.showProgressDialog(this)
else dialogManager.dismissDialog()
}
viewModel.configLiveData.observe(this) {
if (it?.isSuccess == true) {
loadTypeList(it.data?.typeEnumList)
if (wantShowCustomerService) {
showCustomerServiceDialog(it.data?.customContactMap)
}
} else if (it?.message != null) {
toast(it.message ?: "")
}
wantShowCustomerService = false
}
lifecycleScope.launch {
repeatOnLifecycle(Lifecycle.State.RESUMED) {
viewModel.submitStateFlow.collectLatest {
dialogManager.dismissDialog()
if (it.isSuccess) {
toast(R.string.home_model_homemodel_01)
finish()
} else if (it.message != null) {
toast(it.message)
}
}
}
}
}
private fun updateContentInputTips(length: Int) {
if (length > 0) {
SpannableTextBuilder(binding.tvContentCount)
.appendText(
text = length.toString(),
textColor = getColorById(R.color.color_3FDDAC)
)
.appendText(text = "/300")
.apply()
} else {
binding.tvContentCount.text = "${length}/300"
}
}
private fun showCustomerServiceDialog() {
val config = viewModel.configLiveData.value?.data
if (config == null) {
wantShowCustomerService = true
viewModel.getConfig()
return
}
showCustomerServiceDialog(config.customContactMap)
}
private fun showCustomerServiceDialog(info: Map<String, String>?) {
if (info.isNullOrEmpty()) {
return
}
CustomerServiceDialog(this, info).show()
}
private fun loadTypeList(type: List<FeedbackTypeBean>?) {
adapter.setNewData(type)
}
private fun onAddImage(path: String?) {
if (path.isNullOrEmpty()) {
imagePath = null
imageUrl = null
binding.ivImage.scaleType = ScaleType.CENTER_INSIDE
binding.ivImage.setImageResource(R.drawable.feedback_ic_add)
} else {
imagePath = path
imageUrl = null
binding.ivImage.load(path)
binding.ivImage.scaleType = ScaleType.CENTER_CROP
}
refreshSubmitState()
}
private fun refreshSubmitState() {
binding.tvSubmit.isEnabled = canSubmit()
}
private fun canSubmit(): Boolean {
if (binding.etContent.text.isNullOrEmpty()) {
return false
}
if (binding.etContact.text.isNullOrEmpty()) {
return false
}
if (adapter.getSelectItem() == null) {
return false
}
return true
}
private fun submit() {
val content = binding.etContent.text.trim().toString()
val contact = binding.etContact.text.trim().toString()
val type = adapter.getSelectItem()?.type ?: ""
val imagePath = imagePath
if (imagePath != null && imageUrl == null) {
uploadImage(imagePath, {
imageUrl = it
submit()
}, {
if (it != null) {
toast(ResUtil.getString(R.string.ui_user_userinfomodifyactivity_08) + ":${it.message}")
}
dialogManager.dismissDialog()
})
} else {
viewModel.submitFeedback(
type = type,
content = content,
image = imageUrl ?: "",
contact = contact
)
}
}
@SuppressLint("CheckResult")
private fun uploadImage(path: String, success: (String) -> Unit, failed: (Throwable?) -> Unit) {
FileModel.get()
.uploadFile(path)
.compose(bindToLifecycle())
.subscribe { url: String?, throwable: Throwable? ->
if (url != null) {
success.invoke(url)
} else {
failed.invoke(throwable)
}
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (resultCode == RESULT_OK) {
if (requestCode == REQUEST_CODE_OPEN_PHOTO_PROVIDER) {
if (data == null) {
return
}
PhotoProvider.getResultPathListAsync(data) { list ->
if (list.isNullOrEmpty()) {
SingleToastUtil.showToastShort(com.netease.nim.uikit.R.string.picker_image_error)
return@getResultPathListAsync
}
val paths = list.map { it.path }.toMutableList()
compressPhotos(paths)
}
}
}
}
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<String?>,
grantResults: IntArray
) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this)
}
private fun checkStoragePermission() {
if (!EasyPermissions.hasPermissions(
this,
if (Build.VERSION.SDK_INT >= 33) Manifest.permission.READ_MEDIA_IMAGES else Manifest.permission.READ_EXTERNAL_STORAGE
)
) {
EasyPermissions.requestPermissions(
this,
getString(R.string.permission_storage_rationale),
PERMISSION_CODE_STORAGE,
if (Build.VERSION.SDK_INT >= 33) Manifest.permission.READ_MEDIA_IMAGES else Manifest.permission.READ_EXTERNAL_STORAGE
)
} else {
photoProvider(
this,
1,
true,
REQUEST_CODE_OPEN_PHOTO_PROVIDER,
true,
true
)
}
}
private fun compressPhotos(paths: MutableList<String>) {
compressJob?.cancel(null)
compressJob = PhotoCompressUtil.compress(
this, paths,
PhotoCompressUtil.getCompressCachePath(),
object : PhotosCompressCallback {
override fun onSuccess(compressedImgList: ArrayList<String>) {
val firstItem = compressedImgList.firstOrNull() ?: return
onAddImage(firstItem)
}
override fun onFail(e: Throwable) {
ToastUtils.show(getString(R.string.picker_image_error))
}
}
)
}
override fun needSteepStateBar(): Boolean {
return true
}
override fun setStatusBar() {
super.setStatusBar()
StatusBarUtil.transparencyBar(this)
StatusBarUtil.StatusBarLightMode(this)
}
override fun onPermissionsGranted(requestCode: Int, perms: MutableList<String>) {
if (requestCode == PERMISSION_CODE_STORAGE) {
checkStoragePermission()
}
}
override fun onPermissionsDenied(requestCode: Int, perms: MutableList<String>) {
if (requestCode == PERMISSION_CODE_STORAGE) {
val requestTip = getString(R.string.permission_storage_denied)
val mPrivacyDialog = CommonTipDialog(context)
mPrivacyDialog.setTipMsg(requestTip)
mPrivacyDialog.setOkText(getString(R.string.room_perform_go_update))
mPrivacyDialog.setOnActionListener(object : CommonTipDialog.OnActionListener {
override fun onOk() {
//同意跳到应用详情页面
SettingsUtils.startMyApplicationDetailsForResult(
this@FeedbackActivity,
packageName
)
}
override fun onCancel() {
super.onCancel()
//取消跳到应用详情页面
ToastUtils.show(getString(R.string.permission_storage_refused))
}
})
mPrivacyDialog.show()
}
}
override fun onResume() {
super.onResume()
if (viewModel.configLiveData.value?.data == null) {
viewModel.getConfig()
}
}
}

View File

@@ -0,0 +1,42 @@
package com.chwl.app.ui.feedback
import com.chad.library.adapter.base.BaseQuickAdapter
import com.chad.library.adapter.base.BaseViewHolder
import com.chwl.app.R
import com.chwl.core.home.bean.FeedbackTypeBean
class FeedbackTypeAdapter : BaseQuickAdapter<FeedbackTypeBean, BaseViewHolder>(R.layout.feedback_item_type) {
private var selectItem: FeedbackTypeBean? = null
override fun convertPayloads(
helper: BaseViewHolder,
item: FeedbackTypeBean?,
payloads: MutableList<Any>
) {
super.convertPayloads(helper, item, payloads)
convertState(helper, item)
}
override fun convert(helper: BaseViewHolder, item: FeedbackTypeBean?) {
helper.setText(R.id.tv_name, item?.desc ?: "")
convertState(helper, item)
}
private fun convertState(helper: BaseViewHolder, item: FeedbackTypeBean?) {
if (selectItem == item) {
helper.setBackgroundRes(R.id.tv_name, R.drawable.shape_85f6d3_15dp)
} else {
helper.setBackgroundRes(R.id.tv_name, R.drawable.shape_f3f5fa_15dp)
}
}
fun selectItem(item: FeedbackTypeBean?) {
this.selectItem = item
notifyItemRangeChanged(0, itemCount, true)
}
fun getSelectItem(): FeedbackTypeBean? {
return selectItem
}
}

View File

@@ -0,0 +1,36 @@
package com.chwl.app.ui.feedback
import androidx.lifecycle.MutableLiveData
import com.chwl.app.base.BaseViewModel
import com.chwl.core.bean.response.BeanResult
import com.chwl.core.home.bean.FeedbackConfigBean
import com.chwl.core.home.model.HomeModel
import kotlinx.coroutines.flow.MutableSharedFlow
class FeedbackViewModel : BaseViewModel() {
val configLiveData = MutableLiveData<BeanResult<FeedbackConfigBean>?>()
val submitStateFlow = MutableSharedFlow<BeanResult<Any?>>()
fun getConfig() {
safeLaunch(
needLoading = true,
onError = {
configLiveData.postValue(BeanResult.failed(it))
}) {
val value = HomeModel.getFeedbackConfig()
configLiveData.postValue(BeanResult.success(value))
}
}
fun submitFeedback(type: String, content: String, image: String, contact: String) {
safeLaunch(
needLoading = true,
onError = {
submitStateFlow.emit(BeanResult.failed(it))
}) {
val value = HomeModel.commitFeedback(contact, content, image, type)
submitStateFlow.emit(BeanResult.success(value))
}
}
}

View File

@@ -41,6 +41,7 @@ import com.netease.nim.uikit.common.ui.recyclerview.adapter.BaseFetchLoadAdapter
import com.netease.nim.uikit.common.ui.recyclerview.adapter.IRecyclerView;
import com.netease.nim.uikit.common.ui.recyclerview.listener.OnItemClickListener;
import com.netease.nim.uikit.common.ui.recyclerview.loadmore.MsgListFetchLoadMoreView;
import com.netease.nim.uikit.common.util.AntiSpamUtil;
import com.netease.nim.uikit.common.util.media.BitmapDecoder;
import com.netease.nim.uikit.common.util.sys.ClipboardUtil;
import com.netease.nim.uikit.common.util.sys.NetworkUtil;
@@ -449,19 +450,12 @@ public class MessageListPanelEx {
int index = getItemIndex(message.getUuid());
if (index >= 0 && index < items.size()) {
IMMessage item = items.get(index);
String antiSpamRes = message.getYidunAntiSpamRes();
if (!TextUtils.isEmpty(antiSpamRes)) {
JSONObject jsonObject = JSON.parseObject(antiSpamRes);
if (jsonObject.getIntValue("suggestion") == 2) {
item.setStatus(MsgStatusEnum.fail);
NIMClient.getService(MsgService.class).updateIMMessageStatus(item);
} else {
item.setStatus(message.getStatus());
}
if (AntiSpamUtil.isAntiSpam(message)) {
item.setStatus(MsgStatusEnum.fail);
NIMClient.getService(MsgService.class).updateIMMessageStatus(item);
} else {
item.setStatus(message.getStatus());
}
item.setAttachStatus(message.getAttachStatus());
// 处理语音、音视频通话
@@ -1052,6 +1046,9 @@ public class MessageListPanelEx {
if (message.getDirect() == MsgDirectionEnum.Out) {
// 发出的消息,如果是发送失败,直接重发,否则有可能是漫游到的多媒体消息,但文件下载
if (message.getStatus() == MsgStatusEnum.fail) {
if (AntiSpamUtil.isAntiSpam(message)) {
return;
}
resendMessage(message); // 重发
} else {
if (message.getAttachment() instanceof FileAttachment) {

View File

@@ -2,10 +2,12 @@ package com.chwl.app.ui.im;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import com.chwl.app.decoration.view.DecorationStoreActivity;
import com.chwl.app.earn.activity.EarnRecordActivity;
import com.chwl.app.pay.activity.GiveGoldActivity;
import com.chwl.app.ui.feedback.FeedbackActivity;
import com.chwl.core.module_hall.hall.bean.H5FamilyInfo;
import com.chwl.core.module_hall.hall.bean.UserClanInfo;
import com.trello.rxlifecycle3.components.support.RxAppCompatActivity;
@@ -32,13 +34,11 @@ import com.chwl.app.team.view.NimTeamMessageActivity;
import com.chwl.app.ui.login.BindPhoneActivity;
import com.chwl.app.ui.login.ShowBindPhoneActivity;
import com.chwl.app.ui.pay.ChargeActivity;
import com.chwl.app.ui.setting.FeedbackActivity;
import com.chwl.app.ui.setting.ModifyPwdActivity;
import com.chwl.app.ui.user.activity.UserInfoActivity;
import com.chwl.app.ui.webview.CommonWebViewActivity;
import com.chwl.app.vip.VipMainActivity;
import com.chwl.core.DemoCache;
import com.chwl.core.UriProvider;
import com.chwl.core.auth.AuthModel;
import com.chwl.core.community.event.SquareTaskEvent;
import com.chwl.core.im.custom.bean.RouterType;
@@ -209,7 +209,7 @@ public class RouterHandler {
break;
case RouterType.FEED_BACK:
FeedbackActivity.start(context);
context.startActivity(new Intent(context, FeedbackActivity.class));
break;
case RouterType.SET_PASSWORD:
ModifyPwdActivity.start(context, ModifyPwdActivity.LOGIN_PWD);

View File

@@ -1,24 +1,10 @@
package com.chwl.app.ui.im.chat;
import android.graphics.Color;
import android.text.SpannableString;
import android.text.Spanned;
import android.text.TextUtils;
import android.text.method.LinkMovementMethod;
import android.text.style.ForegroundColorSpan;
import android.view.View;
import android.widget.TextView;
import androidx.annotation.NonNull;
import com.netease.nim.uikit.business.session.viewholder.MsgViewHolderBase;
import com.netease.nim.uikit.common.ui.recyclerview.adapter.BaseMultiItemFetchLoadAdapter;
import com.chwl.app.R;
import com.chwl.app.common.widget.OriginalDrawStatusClickSpan;
import com.chwl.app.ui.webview.SimpleWebViewActivity;
import com.chwl.core.UriProvider;
import com.chwl.core.im.custom.bean.ChatHintAttachment;
import com.chwl.library.utils.ResUtil;
public class MsgViewHolderChatHint extends MsgViewHolderBase {
@@ -58,30 +44,7 @@ public class MsgViewHolderChatHint extends MsgViewHolderBase {
ChatHintAttachment attachment = (ChatHintAttachment) message.getAttachment();
if (attachment != null) {
String content = attachment.getContent();
String restoreTitle = ResUtil.getString(R.string.im_chat_msgviewholderchathint_01);
if (TextUtils.isEmpty(content) || !content.contains(restoreTitle)) {
tvContent.setText(content);
} else {
SpannableString ss = new SpannableString(content);
int restoreTitleIndex = content.indexOf(restoreTitle);
ss.setSpan(
new ForegroundColorSpan(Color.parseColor("#FB486A")),
restoreTitleIndex,
restoreTitleIndex + restoreTitle.length(),
Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
ss.setSpan(
new OriginalDrawStatusClickSpan() {
@Override
public void onClick(@NonNull View widget) {
SimpleWebViewActivity.start(context, UriProvider.getLiveAgreement());
}
},
restoreTitleIndex,
restoreTitleIndex + restoreTitle.length(),
Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
tvContent.setText(ss);
tvContent.setMovementMethod(new LinkMovementMethod());
}
tvContent.setText(content);
}
}

View File

@@ -29,7 +29,6 @@ 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;
import com.netease.nim.uikit.impl.NimUIKitImpl;

View File

@@ -27,6 +27,7 @@ import androidx.core.content.ContextCompat;
import com.chwl.app.BuildConfig;
import com.chwl.app.common.widget.OriginalDrawStatusClickSpan;
import com.chwl.app.ui.feedback.FeedbackActivity;
import com.chwl.app.ui.setting.LabActivity;
import com.chwl.app.ui.webview.CommonWebViewActivity;
import com.chwl.core.UriProvider;
@@ -275,7 +276,9 @@ public class LoginPasswordActivity extends BaseActivity {
});
setProtocol();
findViewById(R.id.layout_google).setOnClickListener(v -> googleLogin());
findViewById(R.id.tv_feedback).setOnClickListener(v -> {
startActivity(new Intent(this, FeedbackActivity.class));
});
if (BuildConfig.DEBUG) {
findViewById(R.id.iv_logo).setOnClickListener(v -> {
startActivity(new Intent(this, LabActivity.class));

View File

@@ -64,7 +64,7 @@ public class LogoutHelper {
String text = ResUtil.getString(R.string.login_helper_logouthelper_09) + simpleDateFormat.format(new Date(exception.getCancelDate()));
int end = text.length();
text += ResUtil.getString(R.string.login_helper_logouthelper_010);
text += ResUtil.getString(R.string.login_helper_logouthelper_010);
SpannableString spannableString = new SpannableString(text);
spannableString.setSpan(new ForegroundColorSpan(ContextCompat.getColor(activity, R.color.appColor)),
0, end, Spannable.SPAN_INCLUSIVE_EXCLUSIVE);

View File

@@ -1,100 +0,0 @@
package com.chwl.app.ui.setting;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.widget.Button;
import android.widget.EditText;
import com.netease.nim.uikit.StatusBarUtil;
import com.trello.rxlifecycle3.android.ActivityEvent;
import com.chwl.app.R;
import com.chwl.app.base.BaseActivity;
import com.chwl.core.auth.AuthModel;
import com.chwl.core.home.model.HomeModel;
import com.chwl.library.utils.ResUtil;
import io.reactivex.SingleObserver;
import io.reactivex.disposables.Disposable;
public class FeedbackActivity extends BaseActivity {
private EditText edtContent;
private EditText edtContact;
private Button btnCommit;
public static void start(Context context) {
Intent intent = new Intent(context, FeedbackActivity.class);
context.startActivity(intent);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_feedback);
initWhiteTitleBar(ResUtil.getString(R.string.ui_setting_feedbackactivity_01));
initView();
initData();
SetListener();
}
private void SetListener() {
btnCommit.setOnClickListener(v ->
HomeModel.INSTANCE.commitFeedback(AuthModel.get().getCurrentUid(),
edtContent.getText().toString(),
edtContact.getText().toString()
)
.compose(bindUntilEvent(ActivityEvent.DESTROY))
.subscribe(new SingleObserver<String>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onSuccess(String s) {
onCommitFeedback();
}
@Override
public void onError(Throwable e) {
onCommitFeedbackFail(e.getMessage());
}
})
);
}
private void initData() {
}
private void initView() {
edtContent = findViewById(R.id.edt_content);
edtContact = findViewById(R.id.edt_contact);
btnCommit = findViewById(R.id.btn_commit);
}
public void onCommitFeedback(){
getDialogManager().showProgressDialog(FeedbackActivity.this, ResUtil.getString(R.string.ui_setting_feedbackactivity_02));
toast(ResUtil.getString(R.string.ui_setting_feedbackactivity_03));
finish();
}
public void onCommitFeedbackFail(String error){
// toast(error);
}
@Override
protected boolean needSteepStateBar() {
return true;
}
@Override
protected void setStatusBar() {
super.setStatusBar();
StatusBarUtil.transparencyBar(this);
StatusBarUtil.StatusBarLightMode(this);
}
}

View File

@@ -13,6 +13,7 @@ import com.chwl.app.base.BaseViewBindingActivity
import com.chwl.app.common.widget.dialog.DialogManager.OkCancelDialogListener
import com.chwl.app.databinding.ActivitySettingBinding
import com.chwl.app.notify.RoomNotifyManager
import com.chwl.app.ui.debug.DebugActivity
import com.chwl.app.ui.im.avtivity.BlackListManageActivity
import com.chwl.app.ui.language.LanguageActivity
import com.chwl.app.ui.login.BindPhoneActivity
@@ -83,11 +84,12 @@ class SettingActivity : BaseViewBindingActivity<ActivitySettingBinding>(), View.
binding.tvLanugage.setOnClickListener(this)
binding.rlyPayPwd.setOnClickListener(this)
if (BuildConfig.DEBUG) {
// TODO 临时调整
// if (BuildConfig.DEBUG) {
binding.titleBar.setOnTitleClickListener {
debug()
}
}
// }
}
@SuppressLint("CheckResult")
@@ -221,7 +223,8 @@ class SettingActivity : BaseViewBindingActivity<ActivitySettingBinding>(), View.
}
private fun debug() {
// CommonWebViewActivity.start(this,"https://api.molistar.xyz/molistar/activity/2024-invitationFission/index.html")
// startActivity(Intent(this, DebugActivity::class.java))
CommonWebViewActivity.start(this,"http://beta.api.molistar.xyz/molistar/modules/order/index.html")
// PublicChatRoomMessageActivity.start(this)
// MyDecorationActivity.start(this,0)
}

View File

@@ -25,8 +25,9 @@ import com.chwl.app.ui.user.adapter.UserInfoTopAlbumAdapter;
import com.chwl.app.ui.user.fragment.UserInfoDataFragment;
import com.chwl.app.ui.user.fragment.UserInfoDynamicFragment;
import com.chwl.app.utils.AppBarStateChangeListener;
import com.chwl.app.utils.AvatarHelper;
import com.chwl.library.widget.SVGAView;
import com.chwl.core.decoration.headwear.bean.HeadWearInfo;
import com.chwl.core.noble.NobleUtil;
import com.example.lib_utils.UiUtils;
import com.google.android.material.appbar.AppBarLayout;
import com.netease.nim.uikit.StatusBarUtil;
@@ -254,6 +255,7 @@ public class UserInfoActivity extends BaseBindingActivity<ActivityUserInfoBindin
mBinding.tbUserInfo.setTitle("");
ivOfficialMask = mBinding.inOfficialMask.findViewById(R.id.iv_official_mask);
tvOfficialMask = mBinding.inOfficialMask.findViewById(R.id.tv_official_mask);
mBinding.ivHeadWear.bindCache(SVGAView.newCache(1));
}
@Subscribe(threadMode = ThreadMode.MAIN)
@@ -269,8 +271,7 @@ public class UserInfoActivity extends BaseBindingActivity<ActivityUserInfoBindin
ImageLoadUtilsV2.loadImage(mBinding.ivUserHead, userInfo.getAvatar());
HeadWearInfo headWearInfo = userInfo.getUserHeadwear();
if (headWearInfo != null && headWearInfo.getFirstUrl() != null) {
NobleUtil.loadHeadWear(headWearInfo.getFirstUrl(), mBinding.ivHeadWear);
mBinding.ivHeadWear.setVisibility(View.VISIBLE);
AvatarHelper.loadAvatarFrame(mBinding.ivHeadWear, headWearInfo.getFirstUrl(), headWearInfo.getType());
mBinding.ivUserHead.setPadding(0, 0, 0, 0);
mBinding.ivUserHead.setStrokeWidth(0);
} else {

View File

@@ -40,7 +40,7 @@ import com.chwl.core.user.bean.UserInfo
import com.chwl.core.user.bean.UserPhoto
import com.chwl.core.utils.CoreLogger
import com.chwl.library.common.file.FileHelper
import com.chwl.library.common.photo.PhotoProviderNew
import com.chwl.library.common.photo.PhotoProvider
import com.chwl.library.common.util.PhotoCompressCallback
import com.chwl.library.common.util.PhotoCompressUtil
import com.chwl.library.easypermisssion.EasyPermissions
@@ -371,7 +371,7 @@ class UserInfoModifyActivity : BaseViewBindingActivity<ActivityUserInfoModifyBin
)
} else {
mUri = Uri.parse("file://${FileHelper.getRootCacheDir()?.path}/${getNowTime()}.jpg")
PhotoProviderNew.photoProvider(
PhotoProvider.photoProvider(
this,
resultCode = REQUEST_CODE_OPEN_PHOTO_PROVIDER
)
@@ -429,7 +429,7 @@ class UserInfoModifyActivity : BaseViewBindingActivity<ActivityUserInfoModifyBin
}
}
REQUEST_CODE_OPEN_PHOTO_PROVIDER -> data?.let {
val photos = PhotoProviderNew.getResultPhotoList(it)
val photos = PhotoProvider.getResultPhotoList(it)
if (!photos.isNullOrEmpty()) {
val photo = photos[0]
crop(photo.uri, photo.size, mUri)

View File

@@ -32,7 +32,7 @@ import com.chwl.core.user.bean.UserPhoto
import com.chwl.core.utils.CoreLogger
import com.chwl.core.utils.net.BeanObserver
import com.chwl.library.common.file.FileHelper
import com.chwl.library.common.photo.PhotoProviderNew
import com.chwl.library.common.photo.PhotoProvider
import com.chwl.library.common.util.PhotoCompressCallback
import com.chwl.library.common.util.PhotoCompressUtil
import com.chwl.library.easypermisssion.EasyPermissions
@@ -232,7 +232,7 @@ class UserModifyPhotosActivity : TakePhotoActivity(), PhotoItemClickListener,
)
} else {
mUri = Uri.parse("file://${FileHelper.getRootCacheDir()?.path}/${getNowTime()}.jpg")
PhotoProviderNew.photoProvider(
PhotoProvider.photoProvider(
this,
resultCode = REQUEST_CODE_OPEN_PHOTO_PROVIDER
)
@@ -252,7 +252,7 @@ class UserModifyPhotosActivity : TakePhotoActivity(), PhotoItemClickListener,
} else if (resultCode == RESULT_OK) {
when (requestCode) {
REQUEST_CODE_OPEN_PHOTO_PROVIDER -> data?.let {
val photos = PhotoProviderNew.getResultPhotoList(data) ?: return
val photos = PhotoProvider.getResultPhotoList(data) ?: return
if (photos.isNotEmpty()) {
val photo = photos[0]
crop(photo.uri, photo.size, mUri)

View File

@@ -57,8 +57,8 @@ public class ContactsIndicatorAdapter extends CommonNavigatorAdapter {
if (!showIndicator) return null;
DrawableIndicator indicator = new DrawableIndicator(context);
indicator.setMode(DrawableIndicator.MODE_EXACTLY);
indicator.setDrawableWidth(UIUtil.dip2px(context, 24));
indicator.setDrawableHeight(UIUtil.dip2px(context, 8));
indicator.setDrawableWidth(context.getResources().getDimensionPixelOffset(R.dimen.dp_24));
indicator.setDrawableHeight(context.getResources().getDimensionPixelOffset(R.dimen.dp_7));
indicator.setIndicatorDrawable(context.getResources().getDrawable(R.drawable.base_ic_indicator));
FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
lp.gravity = Gravity.END;

View File

@@ -63,8 +63,8 @@ public class HomeRecommendIndicatorAdapter extends CommonNavigatorAdapter {
if (!showIndicator) return null;
DrawableIndicator indicator = new DrawableIndicator(context);
indicator.setMode(DrawableIndicator.MODE_EXACTLY);
indicator.setDrawableWidth(UIUtil.dip2px(context, 24));
indicator.setDrawableHeight(UIUtil.dip2px(context, 8));
indicator.setDrawableWidth(context.getResources().getDimensionPixelOffset(R.dimen.dp_24));
indicator.setDrawableHeight(context.getResources().getDimensionPixelOffset(R.dimen.dp_7));
indicator.setIndicatorDrawable(context.getResources().getDrawable(R.drawable.base_ic_indicator));
FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
lp.gravity = Gravity.END;

View File

@@ -0,0 +1,221 @@
package com.chwl.app.ui.wallet.payment
import android.app.Activity
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleEventObserver
import androidx.lifecycle.LifecycleOwner
import com.chwl.app.R
import com.chwl.app.common.widget.dialog.DialogManager
import com.chwl.core.pay.PayModel
import com.chwl.core.pay.bean.PayRecordId
import com.chwl.library.utils.SingleToastUtil
import com.example.lib_utils.log.ILog
import com.example.module_base.support.billing.IBillingResult
import com.example.module_base.support.billing.IBillingService
import com.example.module_base.support.billing.IProductDetails
import com.example.module_base.support.billing.IPurchase
import com.example.module_base.support.google.IGoogleService
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.disposables.Disposable
class GPaymentClient(val activity: Activity) : IPaymentClient, IBillingService.Listener,
IBillingService.ProductDetailsResponseListener, LifecycleEventObserver, ILog {
private var compositeDisposable: CompositeDisposable? = null
private var _billingService: IBillingService? = null
private val dialogManager = DialogManager(activity)
private var paymentIntent: PaymentIntent? = null
private var productItem: IProductDetails? = null
private var orderId: String? = null
init {
dialogManager.setCanceledOnClickOutside(false)
dialogManager.setCanceledOnClickBackKey(false)
(activity as? LifecycleOwner)?.lifecycle?.addObserver(this)
}
private fun getBillingService(): IBillingService? {
if (_billingService == null) {
_billingService = IGoogleService.newBillingService(activity, this)
}
return _billingService
}
override fun launchPayment(intent: PaymentIntent) {
logD("launchPayment() intent:${intent.productId}")
if (paymentIntent != null) {
SingleToastUtil.showToast(R.string.avroom_activity_roomblacklistactivity_015)
return
}
dialogManager.showProgressDialog(activity)
this.paymentIntent = intent
tryLaunch()
}
private fun tryLaunch() {
val productId = paymentIntent?.productId
val productItem = productItem
logD("tryLaunch() productId:$productId productItem:$productItem")
if (productId == null) {
return
}
if (getBillingService()?.isServiceConnected() != true) {
logD("tryLaunch() isServiceConnected = false")
return
}
if (productItem == null) {
getBillingService()?.querySkuDetailsAsync(listOf(productId), this)
} else {
placeOrder(productItem)
}
}
private fun placeOrder(productItem: IProductDetails) {
logD("placeOrder() productItem:${productItem.getProductId()}")
addDisposable(PayModel.get().placeOrder(productItem.getProductId())
.subscribe(
{ recordId: PayRecordId ->
if (paymentIntent?.productId == productItem.getProductId()) {
orderId = recordId.recordId
getBillingService()?.initiatePurchaseFlow(
productItem,
recordId.recordId
)
} else {
logE("placeOrder() 意图发生改变")
}
}
) { throwable: Throwable ->
callFailed(IPaymentClient.CODE_PLACE_ORDER_FAILED, throwable)
})
}
override fun onBillingClientSetupFinished() {
logD("onBillingClientSetupFinished()")
tryLaunch()
}
override fun onPurchasesUpdated(purchases: List<IPurchase>) {
logD("onPurchasesUpdated() purchases:${purchases.size}")
purchases.forEach {
logD("onPurchasesUpdated() item.state:${it.getPurchaseState()}")
logD("onPurchasesUpdated() item.orderId:${it.getOrderId()}")
logD("onPurchasesUpdated() item.token:${it.getPurchaseToken()}")
logD("onPurchasesUpdated() item.data:${it.getData()}")
val identifiers = it.getAccountIdentifiers()
if (it.isPurchasedState() && identifiers != null) {
addDisposable(
PayModel.get().verifyOrder(
identifiers.getObfuscatedAccountId(),
it.getProducts().firstOrNull(),
it.getPackageName(),
it.getPurchaseToken()
).subscribe({
getBillingService()?.consumeAsync(it)
}, {
callFailed(IPaymentClient.CODE_VERIFY_ORDER_FAILED, it)
})
)
}
}
}
override fun onConsumeFinished(token: String?, result: Int) {
logD("onConsumeFinished() token:${token} result:$result")
val orderId = orderId
if (orderId != null) {
callSuccess(orderId)
}
}
override fun onFailedHandle(result: Int) {
logD("onFailedHandle() result:${result}")
callFailed(IPaymentClient.CODE_OTHER)
}
override fun onProductDetailsResponse(
billingResult: IBillingResult,
productDetails: List<IProductDetails>
) {
logD("onProductDetailsResponse() billingResult:${billingResult.getResponseCode()} productDetails:${productDetails.size}")
if (billingResult.isResponseOk()) {
val item = productDetails.firstOrNull {
it.getProductId() == paymentIntent?.productId
}
productItem = item
if (item != null) {
tryLaunch()
} else {
callFailed(IPaymentClient.CODE_NOT_FOUND)
}
} else {
callFailed(IPaymentClient.CODE_NOT_FOUND)
}
}
private fun callSuccess(orderRecordId: String) {
logD("callSuccess() orderRecordId:${orderRecordId} productId:${paymentIntent?.productId}")
paymentIntent?.let {
it.listener.onResponse(PaymentResult.PaymentSuccess(it.productId, orderRecordId))
}
paymentIntent = null
dialogManager.dismissDialog()
}
private fun callFailed(code: Int, throwable: Throwable? = null) {
throwable?.printStackTrace()
logD("callFailed() code:${code} throwable:${throwable?.message}")
throwable?.let {
SingleToastUtil.showToast(
it.message
)
}
paymentIntent?.let {
it.listener.onResponse(PaymentResult.PaymentFailed(it.productId, code, throwable))
}
paymentIntent = null
dialogManager.dismissDialog()
}
private fun getCompositeDisposable(): CompositeDisposable {
var disposable = compositeDisposable
if (disposable == null) {
disposable = CompositeDisposable()
compositeDisposable = disposable
}
return disposable
}
private fun addDisposable(disposable: Disposable) {
getCompositeDisposable().add(disposable)
}
override fun onCleared() {
logD("onCleared()")
paymentIntent = null
compositeDisposable?.dispose()
compositeDisposable = null
dialogManager.dismissDialog()
}
override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event) {
logD("onStateChanged() event:$event")
when (event) {
Lifecycle.Event.ON_RESUME -> {
if (_billingService?.isServiceConnected() == true) {
_billingService?.onQueryPurchases()
}
}
Lifecycle.Event.ON_DESTROY -> {
(activity as? LifecycleOwner)?.lifecycle?.removeObserver(this)
onCleared()
}
else -> {
}
}
}
}

View File

@@ -0,0 +1,33 @@
package com.chwl.app.ui.wallet.payment
import com.example.lib_utils.ICleared
interface IPaymentClient : ICleared {
companion object {
// 支付成功
const val CODE_SUCCESS = 200
// 未知异常原因
const val CODE_OTHER = 0
// 服务不可用
const val CODE_UNAVAILABLE = 1
// 查询订单信息失败
const val CODE_NOT_FOUND = 2
// 预下单失败
const val CODE_PLACE_ORDER_FAILED = 3
// 验证订单失败
const val CODE_VERIFY_ORDER_FAILED = 4
}
fun launchPayment(intent: PaymentIntent)
override fun onCleared()
interface Listener {
fun onResponse(result: PaymentResult)
}
}

View File

@@ -0,0 +1,4 @@
package com.chwl.app.ui.wallet.payment
class PaymentIntent(val productId: String, val listener: IPaymentClient.Listener) {
}

View File

@@ -0,0 +1,12 @@
package com.chwl.app.ui.wallet.payment
sealed class PaymentResult {
data class PaymentSuccess(val productId: String, val orderId: String) : PaymentResult()
data class PaymentFailed(
val productId: String,
val code: Int,
val exception: Throwable? = null
) : PaymentResult()
}

View File

@@ -91,6 +91,8 @@ public class CommonWebViewActivity extends BaseActivity {
private static final String POSITION = "position";
private int mPosition;
private JSInterface jsInterface;
public static void start(Context context, String url) {
Intent intent = new Intent(context, CommonWebViewActivity.class);
intent.putExtra("url", url);
@@ -194,7 +196,7 @@ public class CommonWebViewActivity extends BaseActivity {
webView.getSettings().setMixedContentMode(WebSettings.MIXED_CONTENT_COMPATIBILITY_MODE);
}
webView.getSettings().setTextZoom(100);
JSInterface jsInterface = new JSInterface(webView, this);
jsInterface = new JSInterface(webView, this);
jsInterface.setPosition(mPosition);
webView.addJavascriptInterface(jsInterface, "androidJsObj");
webView.getSettings().setCacheMode(WebSettings.LOAD_NO_CACHE);
@@ -441,6 +443,9 @@ public class CommonWebViewActivity extends BaseActivity {
@Override
protected void onDestroy() {
if (jsInterface != null) {
jsInterface.onCleared();
}
EventBus.getDefault().unregister(this);
if (webViewCallBack != null) {

View File

@@ -1,8 +1,6 @@
package com.chwl.app.ui.webview;
import android.content.DialogInterface;
import android.content.Intent;
import android.net.Uri;
import android.net.http.SslError;
import android.os.Build;
import android.text.TextUtils;
@@ -16,7 +14,6 @@ import androidx.appcompat.app.AlertDialog;
import com.orhanobut.logger.Logger;
import com.chwl.app.R;
import com.chwl.app.base.BaseBindingFragment;
import com.chwl.app.common.widget.dialog.BaseAlertDialogBuilder;
import com.chwl.app.databinding.FragmentCommonWebViewBinding;
import com.chwl.library.annatation.ActLayoutRes;
import com.chwl.library.utils.ResUtil;
@@ -26,6 +23,7 @@ public class CommonWebViewFragment extends BaseBindingFragment<FragmentCommonWeb
private WebView webView;
protected String url;
private JSInterface jsInterface;
@Override
public void initiate() {
@@ -37,7 +35,7 @@ public class CommonWebViewFragment extends BaseBindingFragment<FragmentCommonWeb
webView.getSettings().setMixedContentMode(WebSettings.MIXED_CONTENT_COMPATIBILITY_MODE);
}
webView.getSettings().setTextZoom(100);
JSInterface jsInterface = new JSInterface(webView, getActivity());
jsInterface = new JSInterface(webView, getActivity());
webView.addJavascriptInterface(jsInterface, "androidJsObj");
webView.setWebViewClient(new WebViewClient() {
@@ -113,4 +111,12 @@ public class CommonWebViewFragment extends BaseBindingFragment<FragmentCommonWeb
ShowWebView(url);
}
}
@Override
public void onDestroy() {
super.onDestroy();
if (jsInterface != null) {
jsInterface.onCleared();
}
}
}

View File

@@ -14,13 +14,21 @@ import android.util.Log;
import android.webkit.JavascriptInterface;
import android.webkit.WebView;
import androidx.annotation.NonNull;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.chwl.app.earn.activity.EarnRecordActivity;
import com.chwl.app.ui.invite.InviteImageHelper;
import com.chwl.app.ui.invite.ShareInviteDialog;
import com.chwl.app.ui.invite.ShareInviteInfo;
import com.chwl.app.ui.wallet.payment.GPaymentClient;
import com.chwl.app.ui.wallet.payment.IPaymentClient;
import com.chwl.app.ui.wallet.payment.PaymentIntent;
import com.chwl.app.ui.wallet.payment.PaymentResult;
import com.chwl.library.language.LanguageHelper;
import com.chwl.library.utils.json.JsonUtils;
import com.example.lib_utils.ICleared;
import com.google.gson.Gson;
import com.netease.nim.uikit.common.util.log.LogUtil;
import com.orhanobut.logger.Logger;
@@ -66,7 +74,7 @@ import java.util.HashMap;
* <p> html js 与webview 交互接口</p>
* Created by ${user} on 2017/11/6.
*/
public class JSInterface {
public class JSInterface implements ICleared {
private static final String TAG = JSInterface.class.getSimpleName();
private WebView mWebView;
private CommonWebViewActivity mActivity;
@@ -75,6 +83,7 @@ public class JSInterface {
private MediaRecorder recorder;
private File myRecAudioFile;
private ExtAudioRecorder extAudioRecorder;
private GPaymentClient paymentClient;
public JSInterface(WebView webView, CommonWebViewActivity activity) {
mWebView = webView;
@@ -87,6 +96,68 @@ public class JSInterface {
this.context = context;
}
private void loadUrl(String url) {
com.example.lib_utils.log.LogUtil.d("JSInterface", "loadUrl url:" + url, false);
if (Looper.myLooper() == Looper.getMainLooper()) {
if (mWebView != null) {
mWebView.loadUrl(url);
}
} else {
if (mActivity != null) {
mActivity.runOnUiThread(() -> {
if (mWebView != null) {
mWebView.loadUrl(url);
}
});
}
}
}
private void callJsWithJson(String name, Object params) {
if (name == null) {
return;
}
if (params != null) {
String jsonStr = JsonUtils.toJson(params);
loadUrl("javascript:" + name + "(" + jsonStr + ")");
} else {
loadUrl("javascript:" + name + "()");
}
}
/**
* 拉起本地支付
*/
@JavascriptInterface
public void openPayment(String productId) {
com.example.lib_utils.log.LogUtil.d("JSInterface", "openPayment productId:" + productId, false);
if (mActivity == null || TextUtils.isEmpty(productId)) {
return;
}
mActivity.runOnUiThread(() -> {
if (paymentClient == null) {
paymentClient = new GPaymentClient(mActivity);
}
PaymentIntent paymentIntent = new PaymentIntent(productId, new IPaymentClient.Listener() {
@Override
public void onResponse(@NonNull PaymentResult result) {
HashMap<String, Object> map = new HashMap<>();
if (result instanceof PaymentResult.PaymentSuccess) {
map.put("orderId", ((PaymentResult.PaymentSuccess) result).getOrderId());
map.put("productId", ((PaymentResult.PaymentSuccess) result).getProductId());
map.put("code", 200);
} else if (result instanceof PaymentResult.PaymentFailed) {
map.put("code", ((PaymentResult.PaymentFailed) result).getCode());
map.put("productId", ((PaymentResult.PaymentFailed) result).getProductId());
}
callJsWithJson("openPaymentCallback", map);
}
});
paymentClient.launchPayment(paymentIntent);
});
}
/**
* 调转个人主页
*
@@ -122,7 +193,7 @@ public class JSInterface {
map.put(IReportConstants.MODULE, IReportConstants.MOLISTAR_PAY);
ReportManager.get().reportEvent(IReportConstants.PAYPAGE_SHOW, map);
// if (AppMetaDataUtil.getChannelID().equals(Constants.GOOGLE)) {
ChargeActivity.start(context);
ChargeActivity.start(context);
// } else {
// CommonWebViewActivity.start(
// context, UriProvider.getOfficialPay(
@@ -175,7 +246,7 @@ public class JSInterface {
if (activity == null) {
return;
}
ShareInviteInfo info = new Gson().fromJson(json,ShareInviteInfo.class);
ShareInviteInfo info = new Gson().fromJson(json, ShareInviteInfo.class);
if (info.getType() != null) {
if (info.getType() == 1) {
activity.runOnUiThread(() -> {
@@ -556,4 +627,12 @@ public class JSInterface {
PraiseModel.get().praise(Long.parseLong(uid), true).subscribe();
NimP2PMessageActivity.start(context, uid);
}
@Override
public void onCleared() {
ICleared.super.onCleared();
if (paymentClient != null) {
paymentClient.onCleared();
}
}
}

View File

@@ -27,6 +27,8 @@ import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.chwl.app.utils.AvatarHelper;
import com.chwl.library.widget.SVGAView;
import com.google.android.flexbox.FlexboxLayout;
import com.netease.nim.uikit.common.util.sys.ScreenUtil;
import com.netease.nimlib.sdk.chatroom.ChatRoomMessageBuilder;
@@ -119,7 +121,7 @@ public class UserInfoDialog extends AppCompatDialog implements View.OnClickListe
private UserInfo userInfo;
private ImageView closeImage;
private FrameLayout avatarLayout;
private ImageView ivAvatarHeadWear;
private SVGAView ivAvatarHeadWear;
private ImageView avatar;
/**
* 头像高斯模糊背景
@@ -246,6 +248,7 @@ public class UserInfoDialog extends AppCompatDialog implements View.OnClickListe
inNamePlate = findViewById(R.id.in_nameplate);
ivAvatarHeadWear = findViewById(R.id.iv_avatar_head_wear);
ivAvatarHeadWear.bindCache(AVRoomActivity.getSvgaCache());
ivBadge = findViewById(R.id.iv_badge);
ivBadge.setVisibility(View.GONE);
ivOfficialView = findViewById(R.id.iv_user_official);
@@ -678,9 +681,12 @@ public class UserInfoDialog extends AppCompatDialog implements View.OnClickListe
HeadWearInfo userHeadwear = userInfo.getUserHeadwear();
boolean havaHead = false;
// 设置普通人
if (userHeadwear != null && !TextUtils.isEmpty(userHeadwear.getPic())) {
havaHead = true;
NobleUtil.loadHeadWear(userHeadwear.getEffect() != null ? userHeadwear.getEffect() : userHeadwear.getPic(), ivAvatarHeadWear);
if (userHeadwear != null) {
String avatarFrame = userHeadwear.getFirstUrl();
if (!TextUtils.isEmpty(avatarFrame)) {
havaHead = true;
AvatarHelper.loadAvatarFrame(ivAvatarHeadWear, avatarFrame, userHeadwear.getType());
}
}
if (nobleInfo == null || TextUtils.isEmpty(nobleInfo.getCardBg())) {

View File

@@ -0,0 +1,42 @@
package com.chwl.app.utils
import androidx.core.view.isVisible
import com.chwl.app.R
import com.chwl.library.widget.SVGAView
import com.chwl.core.decoration.headwear.bean.HeadWearInfo
import com.chwl.core.noble.NobleUtil
object AvatarHelper {
/**
* 加载头饰
*/
@JvmStatic
fun loadAvatarFrame(view: SVGAView, headWearInfo: HeadWearInfo?) {
loadAvatarFrame(view, headWearInfo?.firstUrl, headWearInfo?.type ?: 0)
}
/**
* 加载头饰
* @param type 头饰类型 0:图片、1:SVGA
*/
@JvmStatic
fun loadAvatarFrame(view: SVGAView, url: String?, type: Int) {
view.setTag(R.id.head_wear, url)
if (url.isNullOrEmpty()) {
view.clearAnimation()
view.stopAnimation()
view.setImageDrawable(null)
return
}
if (type == 1) {
view.clearAnimation()
view.loadUrl(url)
view.isVisible = true
} else {
view.stopAnimation()
NobleUtil.loadHeadWear(url, view, R.id.head_wear, url)
view.isVisible = true
}
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 367 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 591 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 119 KiB

After

Width:  |  Height:  |  Size: 107 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 132 KiB

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 890 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 941 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.1 KiB

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.4 KiB

After

Width:  |  Height:  |  Size: 9.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.3 KiB

After

Width:  |  Height:  |  Size: 9.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.4 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.9 KiB

After

Width:  |  Height:  |  Size: 9.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 40 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 37 KiB

After

Width:  |  Height:  |  Size: 26 KiB

View File

@@ -8,7 +8,7 @@
android:src="@drawable/splash_bg" />
</item>
<item android:top="@dimen/dp_148">
<item android:top="@dimen/dp_145">
<bitmap
android:dither="true"
android:filter="true"

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<corners android:radius="15dp" />
<solid android:color="#85F6D3" />
</shape>

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<corners android:radius="15dp" />
<solid android:color="#F3F5FA" />
</shape>

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<corners android:radius="7dp" />
<solid android:color="#F3F5FA" />
</shape>

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<corners android:radius="8dp" />
<solid android:color="#F3F5FA" />
</shape>

View File

@@ -1,71 +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="match_parent"
android:background="@color/bg_normal_1c1b22"
android:orientation="vertical"
tools:context="com.chwl.app.ui.setting.FeedbackActivity">
<com.chwl.app.base.TitleBar
android:id="@+id/title_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dp_30" />
<View
android:layout_width="match_parent"
android:layout_height="1px"
android:background="@color/line_353548" />
<TextView
android:layout_width="match_parent"
android:layout_height="44dp"
android:drawableStart="@drawable/feedback_point"
android:drawablePadding="4dp"
android:gravity="center_vertical"
android:paddingStart="15dp"
android:text="@string/layout_activity_feedback_01"
android:textColor="@color/text_title_color"
android:textSize="15sp" />
<EditText
android:id="@+id/edt_content"
android:layout_width="match_parent"
android:layout_height="161dp"
android:layout_marginStart="15dp"
android:layout_marginEnd="15dp"
android:background="@drawable/bg_secondary_radius_15"
android:gravity="start"
android:hint="@string/layout_activity_feedback_02"
android:padding="10dp"
android:textColor="@color/text_normal_c6c6e9"
android:textColorHint="@color/text_hint_555574"
android:textSize="14sp" />
<EditText
android:id="@+id/edt_contact"
android:layout_width="match_parent"
android:layout_height="44dp"
android:layout_marginStart="15dp"
android:layout_marginTop="10dp"
android:layout_marginEnd="15dp"
android:background="@drawable/bg_secondary_radius_15"
android:hint="@string/layout_activity_feedback_03"
android:padding="10dp"
android:textColor="@color/text_normal_c6c6e9"
android:textColorHint="@color/text_hint_555574"
android:textSize="14sp" />
<Button
android:id="@+id/btn_commit"
style="?android:attr/borderlessButtonStyle"
android:layout_width="310dp"
android:layout_height="45dp"
android:layout_gravity="center_horizontal"
android:layout_marginTop="45dp"
android:background="@drawable/base_selector_theme_30dp"
android:text="@string/layout_activity_feedback_04"
android:textColor="@color/base_selector_color_theme_btn"
android:textSize="15sp" />
</LinearLayout>

View File

@@ -14,6 +14,19 @@
android:src="@drawable/bg_theme_top"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/tv_feedback"
android:layout_width="wrap_content"
android:layout_height="48dp"
android:layout_marginTop="@dimen/dp_30"
android:layout_marginEnd="@dimen/dp_15"
android:gravity="center"
android:text="@string/feedback_title"
android:textColor="#000000"
android:textSize="@dimen/dp_14"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:id="@+id/iv_logo"
app:layout_constraintEnd_toEndOf="parent"

View File

@@ -80,8 +80,9 @@
app:strokeColor="@color/white"
app:strokeWidth="@dimen/dp_1" />
<ImageView
<com.chwl.library.widget.SVGAView
android:id="@+id/iv_head_wear"
android:scaleType="centerCrop"
android:layout_width="@dimen/dp_97"
android:layout_height="@dimen/dp_97"
app:layout_constraintBottom_toBottomOf="@id/iv_user_head"

View File

@@ -0,0 +1,45 @@
<?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"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.chwl.app.base.TitleBar
android:id="@+id/title_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dp_30"
app:layout_constraintTop_toTopOf="parent" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="0dp"
android:orientation="vertical"
android:overScrollMode="never"
android:scrollbars="none"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
app:layout_constraintBottom_toTopOf="@id/layout_bottom"
app:layout_constraintTop_toBottomOf="@id/title_bar" />
<LinearLayout
android:id="@+id/layout_bottom"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent">
<Button
android:id="@+id/btn_refresh_all"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="REFRESH-ALL" />
<Button
android:id="@+id/btn_refresh"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="REFRESH" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -0,0 +1,29 @@
<?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"
android:layout_width="match_parent"
android:layout_height="@dimen/dp_80"
android:layout_marginVertical="@dimen/dp_2">
<TextView
android:id="@+id/tv_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/dp_15"
android:textSize="@dimen/dp_18"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<com.chwl.library.widget.SVGAView
android:id="@+id/svga_view"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_marginStart="@dimen/dp_15"
android:scaleType="centerCrop"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintDimensionRatio="1:1"
app:layout_constraintStart_toEndOf="@id/tv_name"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -66,7 +66,7 @@
android:layout_height="55dp"
android:layout_gravity="center" />
<ImageView
<com.chwl.library.widget.SVGAView
android:id="@+id/iv_avatar_head_wear"
android:layout_width="73dp"
android:layout_height="73dp"

View File

@@ -0,0 +1,221 @@
<?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/color_FFFFFF">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/layout_title_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#EBECF3"
android:paddingTop="@dimen/dp_30"
app:layout_constraintTop_toTopOf="parent">
<com.chwl.app.base.TitleBar
android:id="@+id/title_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:id="@+id/iv_customer_service"
android:layout_width="@dimen/dp_30"
android:layout_height="@dimen/dp_30"
android:layout_marginEnd="@dimen/dp_9"
android:scaleType="centerInside"
android:src="@drawable/feedback_ic_customer_service"
app:layout_constraintBottom_toBottomOf="@id/title_bar"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@id/title_bar" />
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="@id/layout_title_bar">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/tv_type_title_prefix"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/dp_15"
android:layout_marginTop="@dimen/dp_29"
android:text="*"
android:textColor="#EB5C2C"
android:textSize="@dimen/dp_16"
android:textStyle="bold"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/tv_type_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/feedback_type_title"
android:textColor="#000000"
android:textSize="@dimen/dp_16"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="@id/tv_type_title_prefix"
app:layout_constraintStart_toEndOf="@id/tv_type_title_prefix"
app:layout_constraintTop_toTopOf="@id/tv_type_title_prefix" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_view_type"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="@dimen/dp_2"
android:layout_marginTop="@dimen/dp_9"
android:overScrollMode="never"
android:scrollbars="none"
app:layout_constraintTop_toBottomOf="@id/tv_type_title"
tools:itemCount="2"
tools:listitem="@layout/feedback_item_type" />
<TextView
android:id="@+id/tv_content_title_prefix"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dp_23"
android:text="*"
android:textColor="#EB5C2C"
android:textSize="@dimen/dp_16"
android:textStyle="bold"
app:layout_constraintStart_toStartOf="@id/tv_type_title_prefix"
app:layout_constraintTop_toBottomOf="@id/recycler_view_type" />
<TextView
android:id="@+id/tv_content_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/feedback_content_title"
android:textColor="#000000"
android:textSize="@dimen/dp_16"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="@id/tv_content_title_prefix"
app:layout_constraintStart_toEndOf="@id/tv_content_title_prefix"
app:layout_constraintTop_toTopOf="@id/tv_content_title_prefix" />
<EditText
android:id="@+id/et_content"
android:layout_width="match_parent"
android:layout_height="@dimen/dp_149"
android:layout_marginHorizontal="@dimen/dp_15"
android:layout_marginTop="@dimen/dp_16"
android:background="@drawable/shape_f3f5fa_7dp"
android:hint="@string/feedback_content_hint"
android:maxLength="300"
android:paddingHorizontal="@dimen/dp_9"
android:paddingTop="@dimen/dp_9"
android:paddingBottom="@dimen/dp_35"
android:textColor="#22252C"
android:textColorHint="#ACB0B7"
android:textSize="@dimen/dp_14"
app:layout_constraintTop_toBottomOf="@id/tv_content_title" />
<TextView
android:id="@+id/tv_content_count"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="@dimen/dp_13"
android:layout_marginBottom="@dimen/dp_14"
android:text="0/300"
android:textColor="#A7ACB3"
android:textSize="@dimen/dp_14"
app:layout_constraintBottom_toBottomOf="@id/et_content"
app:layout_constraintEnd_toEndOf="@id/et_content" />
<TextView
android:id="@+id/tv_image_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dp_23"
android:text="@string/feedback_image_title"
android:textColor="#000000"
android:textSize="@dimen/dp_16"
android:textStyle="bold"
app:layout_constraintStart_toStartOf="@id/tv_type_title_prefix"
app:layout_constraintTop_toBottomOf="@id/et_content" />
<com.google.android.material.imageview.ShapeableImageView
android:id="@+id/iv_image"
android:layout_width="@dimen/dp_76"
android:layout_height="@dimen/dp_76"
android:layout_marginStart="@dimen/dp_15"
android:layout_marginTop="@dimen/dp_16"
android:background="#F3F5FA"
android:scaleType="centerInside"
android:src="@drawable/feedback_ic_add"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_image_title"
app:shapeAppearance="@style/shape_corner_8dp" />
<TextView
android:id="@+id/tv_contact_title_prefix"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dp_30"
android:text="*"
android:textColor="#EB5C2C"
android:textSize="@dimen/dp_16"
android:textStyle="bold"
app:layout_constraintStart_toStartOf="@id/tv_type_title_prefix"
app:layout_constraintTop_toBottomOf="@id/iv_image" />
<TextView
android:id="@+id/tv_contact_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/feedback_contact_title"
android:textColor="#000000"
android:textSize="@dimen/dp_16"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="@id/tv_contact_title_prefix"
app:layout_constraintStart_toEndOf="@id/tv_contact_title_prefix"
app:layout_constraintTop_toTopOf="@id/tv_contact_title_prefix" />
<EditText
android:id="@+id/et_contact"
android:layout_width="match_parent"
android:layout_height="@dimen/dp_43"
android:layout_marginHorizontal="@dimen/dp_15"
android:layout_marginTop="@dimen/dp_16"
android:background="@drawable/shape_f3f5fa_8dp"
android:gravity="center_vertical"
android:hint="@string/feedback_contact_hint"
android:maxLength="100"
android:maxLines="1"
android:paddingHorizontal="@dimen/dp_9"
android:singleLine="true"
android:textColor="#22252C"
android:textColorHint="#ACB0B7"
android:textSize="@dimen/dp_14"
app:layout_constraintTop_toBottomOf="@id/tv_contact_title" />
<TextView
android:id="@+id/tv_submit"
android:layout_width="match_parent"
android:layout_height="@dimen/dp_49"
android:layout_marginHorizontal="@dimen/dp_36"
android:layout_marginTop="@dimen/dp_58"
android:layout_marginBottom="@dimen/dp_30"
android:background="@drawable/base_selector_theme_26dp"
android:enabled="false"
android:gravity="center"
android:text="@string/layout_activity_modify_pwd_07"
android:textColor="@color/base_selector_color_theme_btn"
android:textSize="@dimen/dp_17"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="@id/et_contact" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.core.widget.NestedScrollView>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -0,0 +1,48 @@
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:tools="http://schemas.android.com/tools">
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/layout_root"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="@dimen/dp_43"
android:background="@drawable/base_shape_ffffff_15o5dp"
android:clickable="true">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="@dimen/dp_22"
android:layout_marginTop="@dimen/dp_30"
android:orientation="vertical"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
app:layout_constraintHeight_max="@dimen/dp_350"
app:layout_constraintTop_toTopOf="parent"
tools:itemCount="3"
tools:listitem="@layout/feedback_customer_service_item" />
<TextView
android:id="@+id/tv_next"
android:layout_width="@dimen/dp_120"
android:layout_height="@dimen/dp_38"
android:layout_marginTop="@dimen/dp_20"
android:layout_marginBottom="@dimen/dp_15"
android:background="@drawable/base_shape_theme_19dp"
android:gravity="center"
android:text="@string/login_fragment_adduserinfofragment_04"
android:textColor="@color/base_selector_color_theme_btn"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/recycler_view" />
</androidx.constraintlayout.widget.ConstraintLayout>
</FrameLayout>
</layout>

View File

@@ -0,0 +1,43 @@
<?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="wrap_content">
<TextView
android:id="@+id/tv_content"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:ellipsize="end"
android:maxLines="3"
android:textColor="#333333"
android:textSize="@dimen/dp_16"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@id/layout_copy"
app:layout_constraintHorizontal_bias="0"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintWidth_default="wrap"
tools:text="meNameNameNaNmeNameNameNaNmeNameNameNaNameNameNameNameNaNameNameNameNameNaameNameNameNameNaNameNameNameNameNameNameNameNaNameNameNameNameNaNameNameNameNameNaameNameNameNameNaNameNameNameNameNa11" />
<FrameLayout
android:id="@+id/layout_copy"
android:layout_width="@dimen/dp_20"
android:layout_height="@dimen/dp_20"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/tv_content"
app:layout_constraintTop_toTopOf="parent">
<ImageView
android:id="@+id/iv_copy"
android:layout_width="@dimen/dp_13"
android:layout_height="@dimen/dp_13"
android:layout_gravity="center"
android:scaleType="fitCenter"
android:src="@drawable/feedback_ic_copy" />
</FrameLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<TextView 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/tv_name"
android:layout_width="wrap_content"
android:layout_height="@dimen/dp_31"
android:layout_marginHorizontal="@dimen/dp_12"
android:layout_marginVertical="@dimen/dp_7"
android:background="@drawable/shape_85f6d3_15dp"
android:gravity="center"
android:paddingHorizontal="@dimen/dp_10"
android:textColor="#22252C"
android:textSize="@dimen/dp_14"
tools:text="NAME" />

View File

@@ -10,7 +10,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
android:src="@drawable/bg_theme_top"
android:src="@drawable/bg_theme_top_home"
app:layout_constraintTop_toTopOf="parent" />
<androidx.constraintlayout.widget.ConstraintLayout

View File

@@ -49,7 +49,7 @@
android:visibility="invisible"
tools:visibility="visible" />
<ImageView
<com.chwl.library.widget.SVGAView
android:id="@+id/iv_head_wear"
android:layout_width="match_parent"
android:layout_height="match_parent"

View File

@@ -56,7 +56,7 @@
android:visibility="invisible"
tools:visibility="gone" />
<ImageView
<com.chwl.library.widget.SVGAView
android:id="@+id/iv_head_wear"
android:layout_width="match_parent"
android:layout_height="match_parent"

View File

@@ -1,59 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<data>
<import type="android.view.View" />
<variable
name="headWearInfo"
type="com.chwl.core.decoration.headwear.bean.HeadWearInfo" />
<variable
name="select_position"
type="Boolean" />
</data>
<LinearLayout
android:id="@+id/ll_root"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:background="@drawable/bg_item_select">
<RelativeLayout
android:id="@+id/rl_head_wear"
android:padding="5dp"
android:layout_width="match_parent"
android:layout_height="106dp"
android:layout_gravity="center_horizontal">
<ImageView
android:id="@+id/iv_head_wear"
android:layout_width="88dp"
android:layout_height="88dp"
android:layout_marginTop="6dp"
android:layout_marginStart="11dp"
android:layout_marginEnd="11dp"
android:layout_centerInParent="true" />
<ImageView
android:id="@+id/iv_tag"
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_alignParentTop="true"
tools:src="@drawable/ic_mark_limit"/>
</RelativeLayout>
<TextView
android:id="@+id/tv_head_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="5dp"
android:layout_marginBottom="14dp"
android:textColor="@{select_position?@color/appColor:@color/color_666666}"
android:textSize="14sp" />
</LinearLayout>
</layout>

View File

@@ -97,7 +97,7 @@
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
<com.chwl.library.widget.SVGAView
android:id="@+id/iv_head_wear"
android:layout_width="0dp"
android:layout_height="0dp"

View File

@@ -97,7 +97,7 @@
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
<com.chwl.library.widget.SVGAView
android:id="@+id/iv_head_wear"
android:layout_width="0dp"
android:layout_height="0dp"

View File

@@ -73,7 +73,7 @@
tools:visibility="visible" />
<ImageView
<com.chwl.library.widget.SVGAView
android:id="@+id/iv_head_wear"
android:layout_width="0dp"
android:layout_height="0dp"
@@ -92,6 +92,10 @@
android:gravity="center"
android:includeFontPadding="false"
android:text="@string/layout_item_micro_game_01"
app:autoSizeMaxTextSize="10dp"
app:autoSizeMinTextSize="5dp"
app:autoSizeStepGranularity="1px"
app:autoSizeTextType="uniform"
android:textColor="@color/white"
android:textSize="10dp"
android:visibility="gone"

View File

@@ -22,7 +22,7 @@
android:layout_height="60dp"
android:layout_gravity="center" />
<ImageView
<com.chwl.library.widget.SVGAView
android:id="@+id/iv_head_wear"
android:layout_width="52.8dp"
android:layout_height="52.8dp"

View File

@@ -23,7 +23,7 @@
android:background="@drawable/bg_secondary_radius_15"
android:gravity="center">
<ImageView
<com.chwl.library.widget.SVGAView
android:id="@+id/iv_car_cover"
android:layout_width="63dp"
android:layout_height="63dp"

View File

@@ -48,7 +48,7 @@
android:visibility="invisible"
tools:visibility="gone" />
<ImageView
<com.chwl.library.widget.SVGAView
android:id="@+id/iv_head_wear"
android:layout_width="match_parent"
android:layout_height="match_parent"

View File

@@ -52,7 +52,7 @@
android:visibility="invisible"
tools:visibility="gone" />
<ImageView
<com.chwl.library.widget.SVGAView
android:id="@+id/iv_head_wear"
tools:visibility="gone"
android:layout_width="match_parent"

View File

@@ -1,18 +1,94 @@
<?xml version="1.0" encoding="utf-8"?>
<layout>
<layout xmlns:app="http://schemas.android.com/apk/res-auto">
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/tv_headline_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dp_8"
android:background="@drawable/room_bg_headline"
android:paddingHorizontal="@dimen/dp_10"
android:paddingTop="@dimen/dp_9"
android:paddingBottom="@dimen/dp_9"
android:textColor="#FFF6E1"
android:textSize="@dimen/dp_13"
tools:text="Content" />
android:background="@drawable/room_bg_headline">
<com.google.android.material.imageview.ShapeableImageView
android:id="@+id/iv_avatar"
android:layout_width="@dimen/dp_20"
android:layout_height="@dimen/dp_20"
android:layout_marginStart="@dimen/dp_7_5"
android:layout_marginTop="@dimen/dp_7_5"
android:scaleType="centerCrop"
android:src="@drawable/default_avatar"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:shapeAppearance="@style/shape_circle" />
<ImageView
android:layout_width="@dimen/dp_23"
android:layout_height="@dimen/dp_23"
android:src="@drawable/room_bg_headline_avatar_frame"
app:layout_constraintBottom_toBottomOf="@id/iv_avatar"
app:layout_constraintEnd_toEndOf="@id/iv_avatar"
app:layout_constraintStart_toStartOf="@id/iv_avatar"
app:layout_constraintTop_toTopOf="@id/iv_avatar" />
<TextView
android:id="@+id/tv_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/dp_4"
android:ellipsize="end"
android:maxWidth="@dimen/dp_150"
android:maxLines="1"
android:textColor="#F5EA8E"
android:textSize="@dimen/dp_12"
app:layout_constraintBottom_toBottomOf="@id/iv_avatar"
app:layout_constraintStart_toEndOf="@id/iv_avatar"
app:layout_constraintTop_toTopOf="@id/iv_avatar"
tools:text="Name" />
<com.chwl.app.view.AutoMirroredImageView
android:id="@+id/iv_money_bg"
android:layout_width="@dimen/dp_40"
android:layout_height="@dimen/dp_15"
android:src="@drawable/room_bg_headline_money"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/tv_money"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="@dimen/dp_6"
android:maxLines="1"
android:text="0"
android:textColor="@color/white"
android:textSize="@dimen/dp_8"
app:layout_constraintBottom_toBottomOf="@id/iv_money_bg"
app:layout_constraintEnd_toEndOf="@id/iv_money_bg"
app:layout_constraintTop_toTopOf="@id/iv_money_bg" />
<ImageView
android:layout_width="@dimen/dp_10"
android:layout_height="@dimen/dp_10"
android:layout_marginEnd="@dimen/dp_2"
android:scaleType="fitCenter"
android:src="@drawable/icon_diamond"
app:layout_constraintBottom_toBottomOf="@id/iv_money_bg"
app:layout_constraintEnd_toStartOf="@id/tv_money"
app:layout_constraintTop_toTopOf="@id/iv_money_bg" />
<TextView
android:id="@+id/tv_headline_content"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dp_1"
android:layout_marginEnd="@dimen/dp_10"
android:layout_marginBottom="@dimen/dp_7"
android:textColor="#FFFFFF"
android:textSize="@dimen/dp_12"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="@id/tv_name"
app:layout_constraintTop_toBottomOf="@id/iv_avatar"
tools:text="Content" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>

Some files were not shown because too many files have changed in this diff Show More