From 2a67cf72284a12c28cad21eb2d29e6d02009c598 Mon Sep 17 00:00:00 2001 From: 18401019693 Date: Wed, 10 Apr 2024 09:51:28 +0800 Subject: [PATCH 01/23] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/adapter/MainHomeFollowAdapter.java | 20 ++++++ .../adapter/MainHomeRemFollLiveAdapter.java | 15 ++++- .../main/res/layout/item_main_home_follow.xml | 63 ++++++++++++------- 3 files changed, 73 insertions(+), 25 deletions(-) diff --git a/main/src/main/java/com/yunbao/main/adapter/MainHomeFollowAdapter.java b/main/src/main/java/com/yunbao/main/adapter/MainHomeFollowAdapter.java index d7cbd14fd..33d8d091a 100644 --- a/main/src/main/java/com/yunbao/main/adapter/MainHomeFollowAdapter.java +++ b/main/src/main/java/com/yunbao/main/adapter/MainHomeFollowAdapter.java @@ -7,11 +7,13 @@ import android.text.TextUtils; import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; +import android.widget.RelativeLayout; import android.widget.TextView; import com.yunbao.common.Constants; import com.yunbao.common.adapter.RefreshAdapter; import com.yunbao.common.glide.ImgLoader; +import com.yunbao.common.utils.DpUtil; import com.yunbao.main.R; import com.yunbao.common.bean.LiveBean; import com.yunbao.main.utils.MainIconUtil; @@ -64,6 +66,7 @@ public class MainHomeFollowAdapter extends RefreshAdapter { TextView mTitle; TextView mNum; ImageView mType; + private View redPacket, dragon_money; public Vh(View itemView) { super(itemView); @@ -73,6 +76,8 @@ public class MainHomeFollowAdapter extends RefreshAdapter { mTitle = (TextView) itemView.findViewById(R.id.title); mNum = (TextView) itemView.findViewById(R.id.num); mType = (ImageView) itemView.findViewById(R.id.type); + redPacket = itemView.findViewById(R.id.red_packet); + dragon_money = itemView.findViewById(R.id.dragon_money); itemView.setOnClickListener(mOnClickListener); } @@ -101,6 +106,21 @@ public class MainHomeFollowAdapter extends RefreshAdapter { mType.setImageResource(MainIconUtil.getLiveTypeIcon(Constants.LIVE_TYPE_RESTING)); } // mType.setImageResource(MainIconUtil.getLiveTypeIcon(bean.getType())); + RelativeLayout.LayoutParams dragon_moneyLayoutParams = (RelativeLayout.LayoutParams) dragon_money.getLayoutParams(); + if (bean.getRedPacketStatus() == 1) { + dragon_moneyLayoutParams.topMargin = DpUtil.dp2px(55); + redPacket.setVisibility(View.VISIBLE); + } else { + dragon_moneyLayoutParams.topMargin = DpUtil.dp2px(25); + redPacket.setVisibility(View.GONE); + + } + if (bean.getSendMoneyLongStatus() == 1) { + dragon_money.setLayoutParams(dragon_moneyLayoutParams); + dragon_money.setVisibility(View.VISIBLE); + } else { + dragon_money.setVisibility(View.GONE); + } } } diff --git a/main/src/main/java/com/yunbao/main/adapter/MainHomeRemFollLiveAdapter.java b/main/src/main/java/com/yunbao/main/adapter/MainHomeRemFollLiveAdapter.java index db8c75f09..62fe73882 100644 --- a/main/src/main/java/com/yunbao/main/adapter/MainHomeRemFollLiveAdapter.java +++ b/main/src/main/java/com/yunbao/main/adapter/MainHomeRemFollLiveAdapter.java @@ -7,6 +7,7 @@ import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; import android.widget.LinearLayout; +import android.widget.RelativeLayout; import android.widget.TextView; import androidx.annotation.NonNull; @@ -19,6 +20,7 @@ import com.yunbao.common.Constants; import com.yunbao.common.adapter.RefreshAdapter; import com.yunbao.common.bean.LiveBean; import com.yunbao.common.glide.ImgLoader; +import com.yunbao.common.utils.DpUtil; import com.yunbao.common.utils.formatBigNum; import com.yunbao.main.R; import com.yunbao.main.utils.MainIconUtil; @@ -79,11 +81,12 @@ public class MainHomeRemFollLiveAdapter extends RefreshAdapter { ImageView dr_pk_ico; View views; ImageView bgs; - private View redPacket; + private View redPacket, dragon_money; public Vh(View itemView) { super(itemView); redPacket = itemView.findViewById(R.id.red_packet); + dragon_money = itemView.findViewById(R.id.dragon_money); live_info_view = (LinearLayout) itemView.findViewById(R.id.live_info_view); mCover = (ImageView) itemView.findViewById(R.id.cover); mName = (TextView) itemView.findViewById(R.id.name); @@ -222,10 +225,20 @@ public class MainHomeRemFollLiveAdapter extends RefreshAdapter { if (bean.getIs_week() != null && bean.getIs_week().equals("1")) { views.setVisibility(View.GONE); } + RelativeLayout.LayoutParams dragon_moneyLayoutParams = (RelativeLayout.LayoutParams) dragon_money.getLayoutParams(); if (bean.getRedPacketStatus() == 1) { + dragon_moneyLayoutParams.topMargin = DpUtil.dp2px(55); redPacket.setVisibility(View.VISIBLE); } else { + dragon_moneyLayoutParams.topMargin = DpUtil.dp2px(25); redPacket.setVisibility(View.GONE); + + } + if (bean.getSendMoneyLongStatus() == 1) { + dragon_money.setLayoutParams(dragon_moneyLayoutParams); + dragon_money.setVisibility(View.VISIBLE); + } else { + dragon_money.setVisibility(View.GONE); } } diff --git a/main/src/main/res/layout/item_main_home_follow.xml b/main/src/main/res/layout/item_main_home_follow.xml index 0810b7d82..68a7392f3 100644 --- a/main/src/main/res/layout/item_main_home_follow.xml +++ b/main/src/main/res/layout/item_main_home_follow.xml @@ -1,19 +1,17 @@ - + android:layout_marginTop="5dp"> + app:riv_corner_radius="5dp" /> + app:riv_corner_radius_bottom_right="5dp" /> + app:riv_oval="true" /> + app:dt_left_width="14dp" /> + android:textSize="14sp" /> + android:textStyle="bold" /> + android:scaleType="fitXY" /> + + + \ No newline at end of file From f88356cea2a9066771e860f67c4fb6b685211c0c Mon Sep 17 00:00:00 2001 From: 18401019693 Date: Wed, 10 Apr 2024 10:31:21 +0800 Subject: [PATCH 02/23] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/yunbao/common/dialog/GuardBuyTipsDialog.java | 6 +++--- common/src/main/res/values-en-rUS/string.xml | 2 +- common/src/main/res/values/strings.xml | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/common/src/main/java/com/yunbao/common/dialog/GuardBuyTipsDialog.java b/common/src/main/java/com/yunbao/common/dialog/GuardBuyTipsDialog.java index 04ebc92ec..25a7e4f61 100644 --- a/common/src/main/java/com/yunbao/common/dialog/GuardBuyTipsDialog.java +++ b/common/src/main/java/com/yunbao/common/dialog/GuardBuyTipsDialog.java @@ -73,10 +73,10 @@ public class GuardBuyTipsDialog { buyTypeTextView.setVisibility(View.GONE); content2.setVisibility(View.VISIBLE); - } else if (guardType == mGuardUserInfoModel.getGuardType()) { - content1.setVisibility(View.GONE); - } else { + } else if (TextUtils.equals(mGuardUserInfoModel.getIsOpen(), "1") && guardType > mGuardUserInfoModel.getGuardType()) { content1.setVisibility(View.VISIBLE); + } else { + content1.setVisibility(View.GONE); } } else { content1.setVisibility(View.GONE); diff --git a/common/src/main/res/values-en-rUS/string.xml b/common/src/main/res/values-en-rUS/string.xml index b1f00db6d..98f09ea64 100644 --- a/common/src/main/res/values-en-rUS/string.xml +++ b/common/src/main/res/values-en-rUS/string.xml @@ -1466,7 +1466,7 @@ Limited ride And limited avatar frame 6 month 12 month Quickly activate guardian for your favorite anchor! - Guardian Task + Guard tasks My level > No one is guarding the anchor yet, come and guard it now~ Contribution/week diff --git a/common/src/main/res/values/strings.xml b/common/src/main/res/values/strings.xml index 1a36a41c6..0d8d52e82 100644 --- a/common/src/main/res/values/strings.xml +++ b/common/src/main/res/values/strings.xml @@ -1469,7 +1469,7 @@ Limited ride And limited avatar frame 6 month 12 month Quickly activate guardian for your favorite anchor! - Guardian Task + Guard tasks My level > No one is guarding the anchor yet, come and guard it now~ Contribution/week From b29b0a1688b1d0fe3bf7e49f65b1a28d52d6f486 Mon Sep 17 00:00:00 2001 From: 18401019693 Date: Wed, 10 Apr 2024 13:31:40 +0800 Subject: [PATCH 03/23] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yunbao/live/views/LiveRoomViewHolder.java | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/live/src/main/java/com/yunbao/live/views/LiveRoomViewHolder.java b/live/src/main/java/com/yunbao/live/views/LiveRoomViewHolder.java index a5f9a9fe2..3d2cb2d03 100644 --- a/live/src/main/java/com/yunbao/live/views/LiveRoomViewHolder.java +++ b/live/src/main/java/com/yunbao/live/views/LiveRoomViewHolder.java @@ -1686,6 +1686,10 @@ public class LiveRoomViewHolder extends AbsViewHolder implements View.OnClickLis RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) dragonImmediateParticipation.getLayoutParams(); layoutParams.topMargin = DpUtil.dp2px(110); dragonImmediateParticipation.setLayoutParams(layoutParams); + } if (dragonImmediateParticipationTime.getVisibility() == View.VISIBLE) { + RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) dragonImmediateParticipation.getLayoutParams(); + layoutParams.topMargin = DpUtil.dp2px(110); + dragonImmediateParticipationTime.setLayoutParams(layoutParams); } anchorTimeHandler.removeCallbacks(anchorTimeRunnable); LiveNetManager.get(mContext). @@ -1718,6 +1722,20 @@ public class LiveRoomViewHolder extends AbsViewHolder implements View.OnClickLis layoutParams.topMargin = DpUtil.dp2px(190); dragonImmediateParticipation.setLayoutParams(layoutParams); } + if (dragonImmediateParticipationTime.getVisibility() == View.VISIBLE&&mContext instanceof LiveRyAnchorActivity) { + RelativeLayout.LayoutParams layoutParamsredPacket = (RelativeLayout.LayoutParams) redPacket.getLayoutParams(); + layoutParamsredPacket.topMargin = DpUtil.dp2px(110); + redPacket.setLayoutParams(layoutParamsredPacket); + + RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) dragonImmediateParticipationTime.getLayoutParams(); + layoutParams.topMargin = DpUtil.dp2px(190); + dragonImmediateParticipationTime.setLayoutParams(layoutParams); + } + if (dragonImmediateParticipationTime.getVisibility() == View.GONE&&mContext instanceof LiveRyAnchorActivity){ + RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) redPacket.getLayoutParams(); + layoutParams.topMargin = DpUtil.dp2px(110); + redPacket.setLayoutParams(layoutParams); + } if (redPacketModel.getCountdown() > 180) { redPacketQueue.setVisibility(View.GONE); redPacketCountdown.setVisibility(View.VISIBLE); @@ -1794,6 +1812,11 @@ public class LiveRoomViewHolder extends AbsViewHolder implements View.OnClickLis layoutParams.topMargin = DpUtil.dp2px(110); dragonImmediateParticipation.setLayoutParams(layoutParams); } + if (dragonImmediateParticipationTime.getVisibility() == View.VISIBLE) { + RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) dragonImmediateParticipationTime.getLayoutParams(); + layoutParams.topMargin = DpUtil.dp2px(110); + dragonImmediateParticipationTime.setLayoutParams(layoutParams); + } } public void setRedPacketInfoModel(RedPacketInfoModel redPacket) { @@ -3196,6 +3219,15 @@ public class LiveRoomViewHolder extends AbsViewHolder implements View.OnClickLis sendMoneyTime = Long.parseLong(sendMoneyLongModel.getCountdown()); participation_time.removeCallbacks(sendMoneyRunnable); dragonImmediateParticipationTime.setVisibility(View.VISIBLE); + if (redPacket.getVisibility() == View.VISIBLE) { + RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) dragonImmediateParticipation.getLayoutParams(); + layoutParams.topMargin = DpUtil.dp2px(190); + dragonImmediateParticipationTime.setLayoutParams(layoutParams); + } else { + RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) dragonImmediateParticipation.getLayoutParams(); + layoutParams.topMargin = DpUtil.dp2px(110); + dragonImmediateParticipationTime.setLayoutParams(layoutParams); + } String s1 = StringUtil.getDurationText(sendMoneyTime * 1000); participation_time.setText(s1); participation_time.post(sendMoneyRunnable); @@ -3217,6 +3249,15 @@ public class LiveRoomViewHolder extends AbsViewHolder implements View.OnClickLis public void onSendMoneyLongEndEvent(SendMoneyLongEndEvent moneyLongEndEvent) { if (mLiveUid.contains(String.valueOf(IMLoginManager.get(mContext).getUserInfo().getId()))) { dragonImmediateParticipationTime.setVisibility(View.GONE); + if (redPacket.getVisibility() == View.VISIBLE) { + RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) dragonImmediateParticipation.getLayoutParams(); + layoutParams.topMargin = DpUtil.dp2px(190); + dragonImmediateParticipationTime.setLayoutParams(layoutParams); + } else { + RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) dragonImmediateParticipation.getLayoutParams(); + layoutParams.topMargin = DpUtil.dp2px(110); + dragonImmediateParticipationTime.setLayoutParams(layoutParams); + } } else { dragonImmediateParticipation.setVisibility(View.GONE); From 320584769d9994400d0777f414107337db90a8fc Mon Sep 17 00:00:00 2001 From: 18401019693 Date: Thu, 11 Apr 2024 16:32:21 +0800 Subject: [PATCH 04/23] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- common/build.gradle | 2 +- .../java/com/yunbao/common/dialog/GuardUpgradePopup.java | 4 ++-- config.gradle | 4 ++-- .../main/java/com/yunbao/live/dialog/LiveGuardDialog.java | 8 ++++---- main/src/main/res/layout/view_main_home.xml | 4 ++-- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/common/build.gradle b/common/build.gradle index d59049c32..9e67d69a0 100644 --- a/common/build.gradle +++ b/common/build.gradle @@ -213,7 +213,7 @@ dependencies { api 'com.yanzhenjie.recyclerview:x:1.3.2' //华为支付插件包 - //api project(':lib_huawei') +// api project(':lib_huawei') //google插件包 api project(':lib_google') diff --git a/common/src/main/java/com/yunbao/common/dialog/GuardUpgradePopup.java b/common/src/main/java/com/yunbao/common/dialog/GuardUpgradePopup.java index 36b326d0c..1d1fc7334 100644 --- a/common/src/main/java/com/yunbao/common/dialog/GuardUpgradePopup.java +++ b/common/src/main/java/com/yunbao/common/dialog/GuardUpgradePopup.java @@ -149,11 +149,11 @@ public class GuardUpgradePopup extends CenterPopupView { IMLoginModel userInfo = IMLoginManager.get(getContext()).getUserInfo(); htmlUrl.append(CommonAppConfig.HOST) .append("/h5/Guard/level.html?") - .append("&token=") + .append("token=") .append(userInfo.getToken()) .append("&uid=") .append(userInfo.getId()) - .append("&&anchorUid=") + .append("&anchorUid=") .append(mLiveUid) .append("&isZh=") .append(((WordUtil.isNewZh()) ? "1" : "0")); diff --git a/config.gradle b/config.gradle index 72fe88cbe..516ec9bb3 100644 --- a/config.gradle +++ b/config.gradle @@ -4,7 +4,7 @@ ext { buildToolsVersion: "29.0.2", minSdkVersion : 21, targetSdkVersion : 33, - versionCode : 469, + versionCode : 468, versionName : "6.6.6" ] manifestPlaceholders = [ @@ -21,7 +21,7 @@ ext { baiduAppSecretKey: "nEVSgmuGpU0pjPr6VleEGGAl0hzGW52S", // true表示谷歌支付 false 0 链接包 1 谷歌包 2华为包 3 samsung包 - isGooglePlay : 0, + isGooglePlay : 3, //是否上报异常日志 isUploadLog : true, //是否打包成插件包模式 diff --git a/live/src/main/java/com/yunbao/live/dialog/LiveGuardDialog.java b/live/src/main/java/com/yunbao/live/dialog/LiveGuardDialog.java index 13721933c..638405778 100644 --- a/live/src/main/java/com/yunbao/live/dialog/LiveGuardDialog.java +++ b/live/src/main/java/com/yunbao/live/dialog/LiveGuardDialog.java @@ -291,11 +291,11 @@ public class LiveGuardDialog extends AbsDialogPopupWindow { IMLoginModel userInfo = IMLoginManager.get(mContext).getUserInfo(); htmlUrl.append(CommonAppConfig.HOST) .append("/h5/Guard/mission.html?") - .append("&token=") + .append("token=") .append(userInfo.getToken()) .append("&uid=") .append(userInfo.getId()) - .append("&&anchorUid=") + .append("&anchorUid=") .append(mLiveUid) .append("&isZh=") .append(((WordUtil.isNewZh()) ? "1" : "0")); @@ -317,11 +317,11 @@ public class LiveGuardDialog extends AbsDialogPopupWindow { IMLoginModel userInfo = IMLoginManager.get(mContext).getUserInfo(); htmlUrl.append(CommonAppConfig.HOST) .append("/h5/Guard/level.html?") - .append("&token=") + .append("token=") .append(userInfo.getToken()) .append("&uid=") .append(userInfo.getId()) - .append("&&anchorUid=") + .append("&anchorUid=") .append(mLiveUid) .append("&isZh=") .append(((WordUtil.isNewZh()) ? "1" : "0")); diff --git a/main/src/main/res/layout/view_main_home.xml b/main/src/main/res/layout/view_main_home.xml index 1e99b6ebd..dc97db9b1 100644 --- a/main/src/main/res/layout/view_main_home.xml +++ b/main/src/main/res/layout/view_main_home.xml @@ -51,8 +51,8 @@ android:paddingTop="1dp" android:text="@string/main_type_theater" android:textColor="#B1B1B1" - android:layout_marginBottom="3dp" - android:textSize="16dp" + android:layout_marginBottom="2dp" + android:textSize="17dp" android:textStyle="bold" /> From 11ba2c45f8bd4af21c458341ab9c4147a758cf23 Mon Sep 17 00:00:00 2001 From: 18401019693 Date: Fri, 12 Apr 2024 14:14:16 +0800 Subject: [PATCH 05/23] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- live/src/main/java/com/yunbao/live/activity/LiveActivity.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/live/src/main/java/com/yunbao/live/activity/LiveActivity.java b/live/src/main/java/com/yunbao/live/activity/LiveActivity.java index ae1212ba2..ba51c71eb 100644 --- a/live/src/main/java/com/yunbao/live/activity/LiveActivity.java +++ b/live/src/main/java/com/yunbao/live/activity/LiveActivity.java @@ -506,7 +506,7 @@ public abstract class LiveActivity extends AbsActivity implements SocketMessageL mLiveRoomViewHolder.onGuardInfoChanged(bean); LiveChatBean chatBean = new LiveChatBean(); chatBean.setContent(bean.getUserName()); - chatBean.setType(LiveChatBean.SYSTEM); + chatBean.setType(LiveChatBean.SYSTEM2); mLiveRoomViewHolder.insertChat(chatBean, 1); } } From d4d191fad64bab8c3553288aea41835186fba623 Mon Sep 17 00:00:00 2001 From: zlzw <583819556@qq.com> Date: Wed, 24 Apr 2024 16:26:47 +0800 Subject: [PATCH 06/23] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E5=B8=AE=E5=8A=A9?= =?UTF-8?q?=E4=B8=8E=E5=8F=8D=E9=A6=88=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yunbao/common/activity/AbsActivity.java | 27 +- .../com/yunbao/common/bean/AvatarBean.java | 25 ++ .../yunbao/common/http/CommonHttpUtil.java | 12 +- .../com/yunbao/common/http/PDLiveApi.java | 18 +- .../common/http/live/LiveNetManager.java | 64 ++++ .../interfaces/ImageResultCallback.java | 56 ++- .../com/yunbao/common/upload/UploadBean.java | 105 ++++++ .../yunbao/common/upload/UploadCallback.java | 11 + .../yunbao/common/upload/UploadQnImpl.java | 224 +++++++++++ .../yunbao/common/upload/UploadStrategy.java | 24 ++ .../yunbao/common/utils/ProcessImageUtil.java | 43 ++- .../com/yunbao/common/utils/RouteUtil.java | 7 + .../com/yunbao/common/utils/StringUtil.java | 12 + config.gradle | 4 +- main/src/main/AndroidManifest.xml | 3 + .../main/activity/FeedbackActivity.java | 48 +++ .../main/activity/FeedbackEditActivity.java | 351 ++++++++++++++++++ .../activity/FeedbackSuccessActivity.java | 29 ++ .../yunbao/main/activity/SettingActivity.java | 5 +- .../yunbao/main/views/MainMeViewHolder.java | 11 +- .../drawable/bg_btn_feedback_edit_tv_edit.xml | 9 + .../res/drawable/bg_btn_feedback_success.xml | 9 + .../src/main/res/layout/activity_feedback.xml | 61 +++ .../res/layout/activity_feedback_edit.xml | 198 ++++++++++ .../res/layout/activity_feedback_success.xml | 55 +++ .../icon_activity_feedback_edit_img_add.png | Bin 0 -> 6521 bytes .../icon_activity_feedback_success.png | Bin 0 -> 8600 bytes main/src/main/res/values-zh/strings.xml | 22 +- main/src/main/res/values/strings.xml | 22 +- 29 files changed, 1432 insertions(+), 23 deletions(-) create mode 100644 common/src/main/java/com/yunbao/common/bean/AvatarBean.java create mode 100644 common/src/main/java/com/yunbao/common/upload/UploadBean.java create mode 100644 common/src/main/java/com/yunbao/common/upload/UploadCallback.java create mode 100644 common/src/main/java/com/yunbao/common/upload/UploadQnImpl.java create mode 100644 common/src/main/java/com/yunbao/common/upload/UploadStrategy.java create mode 100644 main/src/main/java/com/yunbao/main/activity/FeedbackActivity.java create mode 100644 main/src/main/java/com/yunbao/main/activity/FeedbackEditActivity.java create mode 100644 main/src/main/java/com/yunbao/main/activity/FeedbackSuccessActivity.java create mode 100644 main/src/main/res/drawable/bg_btn_feedback_edit_tv_edit.xml create mode 100644 main/src/main/res/drawable/bg_btn_feedback_success.xml create mode 100644 main/src/main/res/layout/activity_feedback.xml create mode 100644 main/src/main/res/layout/activity_feedback_edit.xml create mode 100644 main/src/main/res/layout/activity_feedback_success.xml create mode 100644 main/src/main/res/mipmap-xxhdpi/icon_activity_feedback_edit_img_add.png create mode 100644 main/src/main/res/mipmap-xxhdpi/icon_activity_feedback_success.png diff --git a/common/src/main/java/com/yunbao/common/activity/AbsActivity.java b/common/src/main/java/com/yunbao/common/activity/AbsActivity.java index 59851d060..7b9c9ba53 100644 --- a/common/src/main/java/com/yunbao/common/activity/AbsActivity.java +++ b/common/src/main/java/com/yunbao/common/activity/AbsActivity.java @@ -6,6 +6,7 @@ import android.content.Intent; import android.content.res.Configuration; import android.content.res.Resources; import android.graphics.Rect; +import android.graphics.Typeface; import android.os.Build; import android.os.Bundle; import android.provider.Settings; @@ -30,7 +31,6 @@ import com.yunbao.common.glide.ImgLoader; import com.yunbao.common.interfaces.LifeCycleListener; import com.yunbao.common.manager.IMLoginManager; import com.yunbao.common.utils.ClickUtil; -import com.yunbao.common.utils.ToastUtil; import java.util.ArrayList; import java.util.List; @@ -92,7 +92,8 @@ public abstract class AbsActivity extends AppCompatActivity { protected void main() { } - protected void create(){ + + protected void create() { } @@ -107,6 +108,17 @@ public abstract class AbsActivity extends AppCompatActivity { } } + protected void setTitleBold(boolean bold) { + TextView titleView = (TextView) findViewById(R.id.titleView); + if (titleView != null) { + if (bold) { + titleView.setTypeface(Typeface.DEFAULT_BOLD); + } else { + titleView.setTypeface(Typeface.DEFAULT); + } + } + } + public void backClick(View v) { if (v.getId() == R.id.btn_back) { onBackPressed(); @@ -181,14 +193,14 @@ public abstract class AbsActivity extends AppCompatActivity { //友盟统计 // MobclickAgent.onResume(this); MobclickAgent.onPageStart(this.mTag); - Log.e("MobclickAgent","MobclickAgent:_onResume_"+this.mTag); + Log.e("MobclickAgent", "MobclickAgent:_onResume_" + this.mTag); } @Override protected void onPause() { super.onPause(); MobclickAgent.onPageEnd(this.mTag); - Log.e("MobclickAgent","MobclickAgent:_onPause_"+this.mTag); + Log.e("MobclickAgent", "MobclickAgent:_onPause_" + this.mTag); if (mLifeCycleListeners != null) { for (LifeCycleListener listener : mLifeCycleListeners) { listener.onPause(); @@ -382,11 +394,12 @@ public abstract class AbsActivity extends AppCompatActivity { break; } } - public boolean isKefu(String url){ - if(url.contains("kefu")){ + + public boolean isKefu(String url) { + if (url.contains("kefu")) { return true; } - if(url.contains("https://newkf.yaoulive.com/")){ + if (url.contains("https://newkf.yaoulive.com/")) { return true; } return url.startsWith("https://kefu.yaoulive.com"); diff --git a/common/src/main/java/com/yunbao/common/bean/AvatarBean.java b/common/src/main/java/com/yunbao/common/bean/AvatarBean.java new file mode 100644 index 000000000..2fec7a998 --- /dev/null +++ b/common/src/main/java/com/yunbao/common/bean/AvatarBean.java @@ -0,0 +1,25 @@ +package com.yunbao.common.bean; + +public class AvatarBean extends BaseModel { + private String avatar; + private String avatarThumb; + + public AvatarBean() { + } + + public String getAvatar() { + return avatar; + } + + public void setAvatar(String avatar) { + this.avatar = avatar; + } + + public String getAvatarThumb() { + return avatarThumb; + } + + public void setAvatarThumb(String avatarThumb) { + this.avatarThumb = avatarThumb; + } +} diff --git a/common/src/main/java/com/yunbao/common/http/CommonHttpUtil.java b/common/src/main/java/com/yunbao/common/http/CommonHttpUtil.java index f7ed008c6..c4444841e 100644 --- a/common/src/main/java/com/yunbao/common/http/CommonHttpUtil.java +++ b/common/src/main/java/com/yunbao/common/http/CommonHttpUtil.java @@ -42,7 +42,7 @@ import java.util.Locale; */ public class CommonHttpUtil { - + public static final String GET_UPLOAD_QI_NIU_TOKEN = "getUploadQiNiuToken"; /** * 初始化 @@ -450,6 +450,16 @@ public class CommonHttpUtil { public static void getUserBaseinfo(String touid, HttpCallback callback) { HttpClient.getInstance().get("User.getUserBaseinfo", CommonHttpConsts.GET_USER_BASEINFO).params("touid", touid).execute(callback); } + /** + * 上传文件 获取七牛云token的接口 + */ + public static void getUploadQiNiuToken(HttpCallback callback, boolean isImg) { + HttpClient.getInstance().get("Pdluserhome.getQiNiuToken", "Pdluserhome.getQiNiuToken") + .params("uid", CommonAppConfig.getInstance().getUid()) + .params("token", CommonAppConfig.getInstance().getToken()) + .params("ext", isImg ? ".jpeg" : ".mp4") + .execute(callback); + } // // //埋点唯一性 // public static void setAdvertisingChannels(String operation, HttpCallback callback) { diff --git a/common/src/main/java/com/yunbao/common/http/PDLiveApi.java b/common/src/main/java/com/yunbao/common/http/PDLiveApi.java index ab4c92838..bd5f82b96 100644 --- a/common/src/main/java/com/yunbao/common/http/PDLiveApi.java +++ b/common/src/main/java/com/yunbao/common/http/PDLiveApi.java @@ -4,6 +4,7 @@ import com.alibaba.fastjson.JSONObject; import com.yunbao.common.bean.ActiveModel; import com.yunbao.common.bean.AnchorRecommendItemModel; import com.yunbao.common.bean.AnchorRecommendModel; +import com.yunbao.common.bean.AvatarBean; import com.yunbao.common.bean.BaseModel; import com.yunbao.common.bean.BattlePassPoints; import com.yunbao.common.bean.BattlePassTask; @@ -82,10 +83,13 @@ import java.util.List; import java.util.Map; import io.reactivex.Observable; +import okhttp3.MultipartBody; import retrofit2.http.Field; import retrofit2.http.FormUrlEncoded; import retrofit2.http.GET; +import retrofit2.http.Multipart; import retrofit2.http.POST; +import retrofit2.http.Part; import retrofit2.http.Query; import retrofit2.http.QueryMap; @@ -111,7 +115,7 @@ public interface PDLiveApi { @Field("uuid_Device") String uuidDevice, @Field("pushid") String pushid, @Field("lastlogindevice") String lastlogindevice, - @Field("langue")String langue + @Field("langue") String langue ); /** @@ -1186,10 +1190,20 @@ public interface PDLiveApi { @GET("/api/public/?service=Guard.participateMoneyLong") Observable> participateMoneyLong(@Query("liveuid") String liveUid, @Query("send_money_long_key") String sendMoneyLongKey); + @GET("/api/public/?service=Guard.endSendMoneyLong") Observable> endSendMoneyLong(@Query("liveuid") String liveUid, @Query("send_money_long_key") String sendMoneyLongKey); + @GET("/api/public/?service=Guard.checkUpgrades") Observable> checkUpgrades(@Query("liveuid") String liveUid); + @GET("/api/public/?service=Guard.getRewards") - Observable> guardGetRewards(@Query("guard_level") String guardLevel,@Query("liveuid") String liveUid); + Observable> guardGetRewards(@Query("guard_level") String guardLevel, @Query("liveuid") String liveUid); + + @Multipart + @POST("/api/public/?service=Pdlinfos.updateAvatar") + Observable> updateFile(@Part MultipartBody.Part file, @Query("uid") String uid, @Query("token") String token); + + @GET("/api/public/?service=User.userFeedback") + Observable>> feedback(@Query("problem_description") String content, @Query("problem_image") String images, @Query("contact_information") String ci); } diff --git a/common/src/main/java/com/yunbao/common/http/live/LiveNetManager.java b/common/src/main/java/com/yunbao/common/http/live/LiveNetManager.java index 974ab71af..31e79f49d 100644 --- a/common/src/main/java/com/yunbao/common/http/live/LiveNetManager.java +++ b/common/src/main/java/com/yunbao/common/http/live/LiveNetManager.java @@ -4,9 +4,12 @@ import android.content.Context; import android.text.TextUtils; import android.util.Log; +import com.alibaba.fastjson.JSONArray; +import com.yunbao.common.CommonAppConfig; import com.yunbao.common.Constants; import com.yunbao.common.R; import com.yunbao.common.bean.ActiveModel; +import com.yunbao.common.bean.AvatarBean; import com.yunbao.common.bean.BaseModel; import com.yunbao.common.bean.BattlePassPoints; import com.yunbao.common.bean.BattlePassTask; @@ -79,6 +82,7 @@ import com.yunbao.common.http.base.CheckLiveCallBack; import com.yunbao.common.http.base.HttpCallback; import com.yunbao.common.utils.WordUtil; +import java.io.File; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -88,6 +92,9 @@ import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.disposables.Disposable; import io.reactivex.functions.Consumer; import io.reactivex.schedulers.Schedulers; +import okhttp3.MediaType; +import okhttp3.MultipartBody; +import okhttp3.RequestBody; /** @@ -3160,6 +3167,63 @@ public class LiveNetManager { } + public void updateFile(File file, HttpCallback callback) { + MultipartBody.Part uploadFile = createUploadFile(file); + API.get().pdLiveApi(mContext) + .updateFile(uploadFile, CommonAppConfig.getInstance().getUid(), CommonAppConfig.getInstance().getToken()) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(new Consumer>() { + @Override + public void accept(ResponseModel model) throws Exception { + if (callback != null) { + callback.onSuccess(model.getData().getInfo()); + } + } + }, new Consumer() { + @Override + public void accept(Throwable throwable) throws Exception { + if (callback != null) { + callback.onError(mContext.getString(com.yunbao.common.R.string.net_error)); + } + } + }).isDisposed(); + } + + public void feedback( + String content, + JSONArray images, + String ci + , HttpCallback callback) { + API.get().pdLiveApi(mContext) + .feedback(content, images.toString(), ci) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(new Consumer>>() { + @Override + public void accept(ResponseModel> responseModel) { + if (callback != null) { + HttpCallbackModel model = new HttpCallbackModel(); + model.setCode(responseModel.getData().getCode()); + model.setMsg(responseModel.getData().getMsg()); + callback.onSuccess(model); + } + } + }, new Consumer() { + @Override + public void accept(Throwable throwable) throws Exception { + if (callback != null) { + callback.onError(mContext.getString(com.yunbao.common.R.string.net_error)); + } + } + }).isDisposed(); + } + + private MultipartBody.Part createUploadFile(File file) { + RequestBody requestBody = RequestBody.create(MediaType.parse("multipart/form-data"), file); + return MultipartBody.Part.createFormData("file", file.getName(), requestBody); + } + /** * 直播间取消网络请求 */ diff --git a/common/src/main/java/com/yunbao/common/interfaces/ImageResultCallback.java b/common/src/main/java/com/yunbao/common/interfaces/ImageResultCallback.java index ed482704e..9615ffbe2 100644 --- a/common/src/main/java/com/yunbao/common/interfaces/ImageResultCallback.java +++ b/common/src/main/java/com/yunbao/common/interfaces/ImageResultCallback.java @@ -1,16 +1,62 @@ package com.yunbao.common.interfaces; +import android.content.Context; + +import com.yunbao.common.CommonAppContext; +import com.yunbao.common.bean.AvatarBean; +import com.yunbao.common.http.live.LiveNetManager; +import com.yunbao.common.upload.UploadBean; +import com.yunbao.common.upload.UploadCallback; +import com.yunbao.common.upload.UploadQnImpl; + import java.io.File; +import java.util.ArrayList; +import java.util.List; /** * Created by cxf on 2018/9/29. */ -public interface ImageResultCallback { +public abstract class ImageResultCallback { //跳转相机前执行 - void beforeCamera(); + public void beforeCamera() { + } - void onSuccess(File file); + public void onSuccess(File file) { + } - void onFailure(); -} + public void onFailure() { + } + + public void onSuccessToUrl(File file, OnItemClickListener listener) { + LiveNetManager.get(CommonAppContext.getTopActivity()) + .updateFile(file, new com.yunbao.common.http.base.HttpCallback() { + @Override + public void onSuccess(AvatarBean data) { + listener.onItemClick(data.getAvatar(), 0); + } + + @Override + public void onError(String error) { + listener.onItemClick(error, -1); + } + }); + } + + public void onSuccessToQiNiuUrl(Context mContext, File file, OnItemClickListener listener) { + UploadQnImpl mUploadStrategy = new UploadQnImpl(mContext); + List beans = new ArrayList<>(); + beans.add(new UploadBean(file, UploadBean.IMG)); + mUploadStrategy.upload(beans, false, new UploadCallback() { + @Override + public void onFinish(List list, boolean success) { + if (success) { + listener.onItemClick("https://downs.yaoulive.com/" + list.get(0).getRemoteAccessUrl(), 0); + } else { + listener.onItemClick(null, -1); + } + } + }, true); + + } +} \ No newline at end of file diff --git a/common/src/main/java/com/yunbao/common/upload/UploadBean.java b/common/src/main/java/com/yunbao/common/upload/UploadBean.java new file mode 100644 index 000000000..920f3a570 --- /dev/null +++ b/common/src/main/java/com/yunbao/common/upload/UploadBean.java @@ -0,0 +1,105 @@ +package com.yunbao.common.upload; + +import java.io.File; + +/** + * Created by cxf on 2019/4/16. + */ + +public class UploadBean { + + public static final int IMG = 0; + public static final int VIDEO = 1; + public static final int VOICE = 2; + private File mOriginFile;//要被上传的源文件 + private File mCompressFile;//压缩后的图片文件 + private String mRemoteFileName;//上传成功后在云存储上的文件名字 + private String mRemoteAccessUrl;//上传成功后在云存储上的访问地址 + private boolean mSuccess;//是否上传成功了 + private int mType; + private Object mTag; + + public UploadBean() { + } + + public UploadBean(File originFile, int type) { + mOriginFile = originFile; + mType = type; + } + + public File getOriginFile() { + return mOriginFile; + } + + public void setOriginFile(File originFile) { + mOriginFile = originFile; + } + + public String getRemoteFileName() { + return mRemoteFileName; + } + + public void setRemoteFileName(String remoteFileName) { + mRemoteFileName = remoteFileName; + } + + public String getRemoteAccessUrl() { + return mRemoteAccessUrl; + } + + public void setRemoteAccessUrl(String remoteAccessUrl) { + mRemoteAccessUrl = remoteAccessUrl; + } + + public File getCompressFile() { + return mCompressFile; + } + + public void setCompressFile(File compressFile) { + mCompressFile = compressFile; + } + + public boolean isSuccess() { + return mSuccess; + } + + public void setSuccess(boolean success) { + mSuccess = success; + } + + + public void setEmpty() { + mOriginFile = null; + mRemoteFileName = null; + mRemoteAccessUrl = null; + } + + public boolean isEmpty() { + return mOriginFile == null && mRemoteFileName == null && mRemoteAccessUrl == null; + } + + public int getType() { + return mType; + } + + public Object getTag() { + return mTag; + } + + public void setTag(Object tag) { + mTag = tag; + } + + @Override + public String toString() { + return "UploadBean{" + + "mOriginFile=" + mOriginFile + + ", mCompressFile=" + mCompressFile + + ", mRemoteFileName='" + mRemoteFileName + '\'' + + ", mRemoteAccessUrl='" + mRemoteAccessUrl + '\'' + + ", mSuccess=" + mSuccess + + ", mType=" + mType + + ", mTag=" + mTag + + '}'; + } +} diff --git a/common/src/main/java/com/yunbao/common/upload/UploadCallback.java b/common/src/main/java/com/yunbao/common/upload/UploadCallback.java new file mode 100644 index 000000000..8676964fa --- /dev/null +++ b/common/src/main/java/com/yunbao/common/upload/UploadCallback.java @@ -0,0 +1,11 @@ +package com.yunbao.common.upload; + +import java.util.List; + +/** + * Created by cxf on 2019/4/16. + */ + +public interface UploadCallback { + void onFinish(List list, boolean success); +} diff --git a/common/src/main/java/com/yunbao/common/upload/UploadQnImpl.java b/common/src/main/java/com/yunbao/common/upload/UploadQnImpl.java new file mode 100644 index 000000000..6b1134b26 --- /dev/null +++ b/common/src/main/java/com/yunbao/common/upload/UploadQnImpl.java @@ -0,0 +1,224 @@ +package com.yunbao.common.upload; + +import android.content.Context; +import android.text.TextUtils; + +import com.qiniu.android.common.ServiceAddress; +import com.qiniu.android.common.Zone; +import com.qiniu.android.http.ResponseInfo; +import com.qiniu.android.storage.Configuration; +import com.qiniu.android.storage.UpCompletionHandler; +import com.qiniu.android.storage.UploadManager; +import com.yunbao.common.http.CommonHttpUtil; +import com.yunbao.common.http.HttpCallback; +import com.yunbao.common.utils.L; +import com.yunbao.common.utils.StringUtil; + +import org.json.JSONException; +import org.json.JSONObject; + +import java.io.File; +import java.util.List; + +import top.zibin.luban.Luban; + +/** + * Created by cxf on 2019/4/16. + * 七牛上传文件 + */ + +public class UploadQnImpl implements UploadStrategy { + + private static final String TAG = "UploadQnImpl"; + private Context mContext; + private List mList; + private int mIndex; + private boolean mNeedCompress; + private UploadCallback mUploadCallback; + private HttpCallback mGetUploadTokenCallback; + private String mToken; + private UploadManager mUploadManager; + private UpCompletionHandler mCompletionHandler;//上传回调 + private Luban.Builder mLubanBuilder; + + public UploadQnImpl(Context context) { + mContext = context; + mCompletionHandler = new UpCompletionHandler() { + @Override + public void complete(String key, ResponseInfo info, JSONObject response) { + System.out.println("UploadQnImpl 上传-----ok----> " + info.isOK() + "--key---> " + "---response---> " + (response != null ? response.toString() : null)); + //L.e("UploadQnImpl 上传-----ok----> " + info.isOK() + "--key---> " + "---response---> " + (response != null ? response.toString() : null)); + try { + assert response != null; + mList.get(mIndex).setRemoteAccessUrl(response.getString("key")); + } catch (JSONException e) { + throw new RuntimeException(e); + } + if (mList == null || mList.size() == 0) { + if (mUploadCallback != null) { + mUploadCallback.onFinish(mList, false); + } + return; + } + UploadBean uploadBean = mList.get(mIndex); + if (info.isOK()) { + uploadBean.setSuccess(true); + if (uploadBean.getType() == UploadBean.IMG && mNeedCompress) { + //上传完成后把 压缩后的图片 删掉 + File compressedFile = uploadBean.getCompressFile(); + if (compressedFile != null && compressedFile.exists()) { + File originFile = uploadBean.getOriginFile(); + if (originFile != null && !compressedFile.getAbsolutePath().equals(originFile.getAbsolutePath())) { + compressedFile.delete(); + } + } + } + mIndex++; + if (mIndex < mList.size()) { + uploadNext(); + } else { + if (mUploadCallback != null) { + mUploadCallback.onFinish(mList, true); + } + } + } else { + upload(mList.get(mIndex));//上传失败后 重新上传 + } + } + }; + } + + @Override + public void upload(List list, boolean needCompress, UploadCallback callback, boolean isImg) { + System.err.println("-------upload------>" + list.size()); + if (callback == null) { + return; + } + if (list == null || list.size() == 0) { + callback.onFinish(list, false); + return; + } + boolean hasFile = false; + for (UploadBean bean : list) { + if (bean.getOriginFile() != null) { + hasFile = true; + break; + } + } + if (!hasFile) { + callback.onFinish(list, true); + return; + } + mList = list; + mNeedCompress = needCompress; + mUploadCallback = callback; + mIndex = 0; + + if (mGetUploadTokenCallback == null) { + mGetUploadTokenCallback = new HttpCallback() { + @Override + public void onSuccess(int code, String msg, String[] info) { + if (code == 0 && info.length > 0) { + mToken = info[0]; + System.err.println("-------上传的token------>" + mToken); + L.e(TAG, "-------上传的token------>" + mToken); + uploadNext(); + } + } + }; + } + CommonHttpUtil.getUploadQiNiuToken(mGetUploadTokenCallback, isImg); + } + + @Override + public void cancelUpload() { + CommonHttpUtil.cancel(CommonHttpUtil.GET_UPLOAD_QI_NIU_TOKEN); + if (mList != null) { + mList.clear(); + } + mUploadCallback = null; + } + + private void uploadNext() { + UploadBean bean = null; + while (mIndex < mList.size() && (bean = mList.get(mIndex)).getOriginFile() == null) { + mIndex++; + } + System.err.println("-------mIndex >= mList.size() mIndex------>" + mIndex); + if (mIndex >= mList.size()) { + System.err.println("-------mIndex >= mList.size()------>" + mList.size()); + if (mUploadCallback != null) { + mUploadCallback.onFinish(mList, true); + } + System.err.println("-------mIndex >= mList.returnreturnreturnreturn------>" + mList.size()); + return; + } + if (bean.getType() == UploadBean.IMG) { + bean.setRemoteFileName(StringUtil.contact(StringUtil.generateFileName(), ".jpg")); + } else if (bean.getType() == UploadBean.VIDEO) { + bean.setRemoteFileName(StringUtil.contact(StringUtil.generateFileName(), ".mp4")); + } else if (bean.getType() == UploadBean.VOICE) { + bean.setRemoteFileName(StringUtil.contact(StringUtil.generateFileName(), ".m4a")); + } + System.err.println("-------mIndex >= bean.getType() == UploadBean.IMG------>" + bean); + upload(bean); + /*if (bean.getType() == UploadBean.IMG && mNeedCompress) { + System.err.println("-------UploadBean.IMG && mNeedCompress------>" + bean + "UploadBean.IMG:" + UploadBean.IMG + "__mNeedCompress" + mNeedCompress); + if (mLubanBuilder == null) { + mLubanBuilder = Luban.with(mContext).ignoreBy(8)//8k以下不压缩 + .setTargetDir(CommonAppConfig.INNER_PATH).setRenameListener(new OnRenameListener() { + @Override + public String rename(String filePath) { + return mList.get(mIndex).getRemoteFileName(); + } + }).setCompressListener(new OnCompressListener() { + @Override + public void onStart() { + } + + @Override + public void onSuccess(File file) { + UploadBean uploadBean = mList.get(mIndex); + uploadBean.setCompressFile(file); + upload(uploadBean); + } + + @Override + public void onError(Throwable e) { + upload(mList.get(mIndex)); + } + }); + } + mLubanBuilder.load(bean.getOriginFile()).launch(); + } else { + System.err.println("-------bean.getType() == UploadBean.IMG && mNeedCompress else"); + upload(bean); + }*/ + } + + private void upload(UploadBean bean) { + System.err.println("-------upload(UploadBean bean)------>" + bean); + if (bean != null && !TextUtils.isEmpty(mToken) && mCompletionHandler != null) { + System.err.println("bean != null && !TextUtils.isEmpty(mToken) && mCompletionHandler != null"); + if (mUploadManager == null) { + Zone zone = new Zone(new ServiceAddress("http://upload-z0.qiniup.com"), new ServiceAddress("http://up-z0.qiniup.com")); + Configuration configuration = new Configuration.Builder().zone(zone).build(); + mUploadManager = new UploadManager(configuration); + } + File uploadFile = bean.getOriginFile(); + if (bean.getType() == UploadBean.IMG && mNeedCompress) { + File compressedFile = bean.getCompressFile(); + if (compressedFile != null && compressedFile.exists()) { + uploadFile = compressedFile; + } + } + mUploadManager.put(uploadFile, bean.getRemoteFileName(), mToken, mCompletionHandler, null); + } else { + System.err.println("else bean != null && !TextUtils.isEmpty(mToken) && mCompletionHandler != null"); + if (mUploadCallback != null) { + mUploadCallback.onFinish(mList, false); + } + } + } + +} diff --git a/common/src/main/java/com/yunbao/common/upload/UploadStrategy.java b/common/src/main/java/com/yunbao/common/upload/UploadStrategy.java new file mode 100644 index 000000000..e61427909 --- /dev/null +++ b/common/src/main/java/com/yunbao/common/upload/UploadStrategy.java @@ -0,0 +1,24 @@ +package com.yunbao.common.upload; + +import java.util.List; + +/** + * Created by cxf on 2019/4/16. + */ + +public interface UploadStrategy { + + /** + * 执行上传 + * + * @param list 被上传的文件列表 + * @param needCompress 是否需要压缩 + * @param callback 上传回调 + */ + void upload(List list, boolean needCompress, UploadCallback callback,boolean isImg); + + /** + * 取消上传 + */ + void cancelUpload(); +} diff --git a/common/src/main/java/com/yunbao/common/utils/ProcessImageUtil.java b/common/src/main/java/com/yunbao/common/utils/ProcessImageUtil.java index c58ad32ee..6a750bd1d 100644 --- a/common/src/main/java/com/yunbao/common/utils/ProcessImageUtil.java +++ b/common/src/main/java/com/yunbao/common/utils/ProcessImageUtil.java @@ -1,15 +1,25 @@ package com.yunbao.common.utils; +import static com.yalantis.ucrop.util.FileUtils.getDataColumn; + import android.Manifest; +import android.content.ContentUris; import android.content.Context; import android.content.Intent; +import android.database.Cursor; import android.net.Uri; import android.os.Build; +import android.os.Environment; +import android.provider.DocumentsContract; +import android.provider.DocumentsProvider; import android.provider.MediaStore; + +import androidx.documentfile.provider.DocumentFile; import androidx.fragment.app.FragmentActivity; import androidx.core.content.FileProvider; import com.yalantis.ucrop.UCrop; +import com.yalantis.ucrop.util.FileUtils; import com.yunbao.common.CommonAppConfig; import com.yunbao.common.R; import com.yunbao.common.interfaces.ActivityResultCallback; @@ -98,12 +108,33 @@ public class ProcessImageUtil extends ProcessResultUtil { mAlumbResultCallback = new ActivityResultCallback() { @Override public void onSuccess(Intent intent) { + if (!mNeedCrop) { + if (mResultCallback != null) { + if (intent.getData() == null) { + if (mResultCallback != null) { + mResultCallback.onFailure(); + } + return; + } + String path = FileUtils.getPath(mContext, intent.getData()); + File file = new File(path); + if (file.exists()) { + mResultCallback.onSuccess(file); + } else { + mResultCallback.onFailure(); + } + } + return; + } crop(intent.getData()); } @Override public void onFailure() { ToastUtil.show(mContext.getString(R.string.img_alumb_cancel)); + if (mResultCallback != null) { + mResultCallback.onFailure(); + } } }; mCropResultCallback = new ActivityResultCallback() { @@ -117,6 +148,9 @@ public class ProcessImageUtil extends ProcessResultUtil { @Override public void onFailure() { ToastUtil.show(mContext.getString(R.string.img_crop_cancel)); + if (mResultCallback != null) { + mResultCallback.onFailure(); + } } }; } @@ -143,6 +177,11 @@ public class ProcessImageUtil extends ProcessResultUtil { requestPermissions(mAlumbPermissions, mAlumbPermissionCallback); } + public void getImageByAlumb(boolean needCrop) { + this.mNeedCrop = needCrop; + requestPermissions(mAlumbPermissions, mAlumbPermissionCallback); + } + /** * 开启摄像头,执行照相 @@ -163,7 +202,9 @@ public class ProcessImageUtil extends ProcessResultUtil { } intent.putExtra(MediaStore.EXTRA_OUTPUT, uri); startActivityForResult(intent, mCameraResultCallback); - }catch (Exception e){e.printStackTrace();} + } catch (Exception e) { + e.printStackTrace(); + } } private File getNewFile() { diff --git a/common/src/main/java/com/yunbao/common/utils/RouteUtil.java b/common/src/main/java/com/yunbao/common/utils/RouteUtil.java index 281357214..513597413 100644 --- a/common/src/main/java/com/yunbao/common/utils/RouteUtil.java +++ b/common/src/main/java/com/yunbao/common/utils/RouteUtil.java @@ -50,6 +50,9 @@ public class RouteUtil { public static final String PATH_BattlePassActivity="/main/BattlePassActivity"; public static final String PATH_SudGameActivity="/live/SudGameActivity"; public static final String PATH_COMMUNITY_Activity="/main/MainHomeCommunityActivity"; + public static final String PATH_FEEDBACK_SUCCESS_ACTIVITY = "/main/FeedbackSuccessActivity"; + public static final String PATH_FEEDBACK_ACTIVITY = "/main/FeedbackActivity"; + public static final String PATH_FEEDBACK_EDIT_ACTIVITY = "/main/FeedbackEditActivity"; public static void forwardCommunityActivity() { @@ -355,4 +358,8 @@ public class RouteUtil { ARouter.getInstance().build(PATH_BattlePassActivity) .navigation(); } + public static void forwardActivity(String path){ + ARouter.getInstance().build(path) + .navigation(); + } } diff --git a/common/src/main/java/com/yunbao/common/utils/StringUtil.java b/common/src/main/java/com/yunbao/common/utils/StringUtil.java index b6bbc577a..c58e8170c 100644 --- a/common/src/main/java/com/yunbao/common/utils/StringUtil.java +++ b/common/src/main/java/com/yunbao/common/utils/StringUtil.java @@ -6,6 +6,7 @@ import java.io.File; import java.math.RoundingMode; import java.text.DecimalFormat; import java.util.Random; +import java.util.UUID; import java.util.regex.Pattern; /** @@ -160,4 +161,15 @@ public class StringUtil { } return false; } + + /** + * 获取随机文件名 + */ + public static String generateFileName() { + return contact("android_", + CommonAppConfig.getInstance().getUid(), + "_", + DateFormatUtil.getVideoCurTimeString(), + UUID.randomUUID().toString()); + } } diff --git a/config.gradle b/config.gradle index 516ec9bb3..3136158c6 100644 --- a/config.gradle +++ b/config.gradle @@ -9,9 +9,9 @@ ext { ] manifestPlaceholders = [ //正式、 - serverHost : "https://napi.yaoulive.com", +// serverHost : "https://napi.yaoulive.com", // 测试 -// serverHost : "https://ceshi.yaoulive.com", + serverHost : "https://ceshi.yaoulive.com", //百度语音识别 diff --git a/main/src/main/AndroidManifest.xml b/main/src/main/AndroidManifest.xml index eff290185..99d1147e3 100644 --- a/main/src/main/AndroidManifest.xml +++ b/main/src/main/AndroidManifest.xml @@ -162,6 +162,9 @@ + + + \ No newline at end of file diff --git a/main/src/main/java/com/yunbao/main/activity/FeedbackActivity.java b/main/src/main/java/com/yunbao/main/activity/FeedbackActivity.java new file mode 100644 index 000000000..66e2242b5 --- /dev/null +++ b/main/src/main/java/com/yunbao/main/activity/FeedbackActivity.java @@ -0,0 +1,48 @@ +package com.yunbao.main.activity; + +import com.alibaba.android.arouter.facade.annotation.Route; +import com.yunbao.common.activity.AbsActivity; +import com.yunbao.common.http.HttpCallback; +import com.yunbao.common.utils.RouteUtil; +import com.yunbao.common.utils.WordUtil; +import com.yunbao.common.views.weight.ViewClicksAntiShake; +import com.yunbao.main.R; +import com.yunbao.main.http.MainHttpUtil; + +@Route(path = RouteUtil.PATH_FEEDBACK_ACTIVITY) +public class FeedbackActivity extends AbsActivity { + @Override + protected int getLayoutId() { + return R.layout.activity_feedback; + } + + @Override + protected void main() { + super.main(); + setTitle(WordUtil.getNewString(R.string.activity_feedback_top_title)); + setTitleBold(true); + ViewClicksAntiShake.clicksAntiShake(findViewById(R.id.btn_cs), new ViewClicksAntiShake.ViewClicksCallBack() { + @Override + public void onViewClicks() { + //TODO 客服 + MainHttpUtil.getCustomerService(new HttpCallback() { + @Override + public void onSuccess(int code, String msg, String[] info) { + if (info.length == 1) { + String url = info[0]; + RouteUtil.forwardCustomerService(url); + } + } + }); + + } + }); + ViewClicksAntiShake.clicksAntiShake(findViewById(R.id.btn_feedback), new ViewClicksAntiShake.ViewClicksCallBack() { + @Override + public void onViewClicks() { + //TODO 意见反馈 + RouteUtil.forwardActivity(RouteUtil.PATH_FEEDBACK_EDIT_ACTIVITY); + } + }); + } +} diff --git a/main/src/main/java/com/yunbao/main/activity/FeedbackEditActivity.java b/main/src/main/java/com/yunbao/main/activity/FeedbackEditActivity.java new file mode 100644 index 000000000..60febc607 --- /dev/null +++ b/main/src/main/java/com/yunbao/main/activity/FeedbackEditActivity.java @@ -0,0 +1,351 @@ +package com.yunbao.main.activity; + +import android.app.Dialog; +import android.graphics.Color; +import android.text.Editable; +import android.text.InputFilter; +import android.text.TextWatcher; +import android.util.SparseArray; +import android.view.View; +import android.widget.Button; +import android.widget.EditText; +import android.widget.ImageView; +import android.widget.TextView; + +import com.alibaba.android.arouter.facade.annotation.Route; +import com.alibaba.fastjson.JSONArray; +import com.yunbao.common.activity.AbsActivity; +import com.yunbao.common.bean.HttpCallbackModel; +import com.yunbao.common.glide.ImgLoader; +import com.yunbao.common.http.base.HttpCallback; +import com.yunbao.common.http.live.LiveNetManager; +import com.yunbao.common.interfaces.ImageResultCallback; +import com.yunbao.common.interfaces.OnItemClickListener; +import com.yunbao.common.utils.DialogUitl; +import com.yunbao.common.utils.ProcessImageUtil; +import com.yunbao.common.utils.RouteUtil; +import com.yunbao.common.utils.ToastUtil; +import com.yunbao.common.utils.WordUtil; +import com.yunbao.common.views.weight.ViewClicksAntiShake; +import com.yunbao.main.R; + +import java.io.File; +import java.util.Locale; + +@Route(path = RouteUtil.PATH_FEEDBACK_EDIT_ACTIVITY) +public class FeedbackEditActivity extends AbsActivity { + EditText feedbackEdit; + ImageView img1, img2, img3; + EditText ciEdit; + Button submit; + TextView editNumber; + ProcessImageUtil imageUtil; + Dialog loadingDialog = null; + int clickImage = 0; + + @Override + protected int getLayoutId() { + return R.layout.activity_feedback_edit; + } + + @Override + protected void main() { + super.main(); + setTitle(WordUtil.getNewString(R.string.activity_feedback_edit_feedback_top)); + setTitleBold(true); + initView(); + imageUtil = new ProcessImageUtil(this); + feedbackEdit.setFilters(new InputFilter[]{new InputFilter.LengthFilter(500)}); + ciEdit.setFilters(new InputFilter[]{new InputFilter.LengthFilter(30)}); + feedbackEdit.addTextChangedListener(new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) { + + } + + @Override + public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) { + if (charSequence.length() == 500) { + ToastUtil.show(R.string.activity_feedback_edit_submit_tip2); + editNumber.setTextColor(Color.parseColor("#FF5656")); + } else { + editNumber.setTextColor(Color.parseColor("#333333")); + } + editNumber.setText(String.format(Locale.getDefault(), "%d", charSequence.length())); + } + + @Override + public void afterTextChanged(Editable editable) { + + } + }); + ViewClicksAntiShake.clicksAntiShake(img1, new ViewClicksAntiShake.ViewClicksCallBack() { + @Override + public void onViewClicks() { + SparseArray list; + if (img1.getTag() == null) { + list = getImageType1(100); + } else { + list = getImageType2(110); + } + showUploadImage(list); + } + }); + ViewClicksAntiShake.clicksAntiShake(img2, new ViewClicksAntiShake.ViewClicksCallBack() { + @Override + public void onViewClicks() { + SparseArray list; + if (img2.getTag() == null) { + list = getImageType1(200); + } else { + list = getImageType2(210); + } + showUploadImage(list); + } + }); + ViewClicksAntiShake.clicksAntiShake(img3, new ViewClicksAntiShake.ViewClicksCallBack() { + @Override + public void onViewClicks() { + SparseArray list; + if (img3.getTag() == null) { + list = getImageType1(300); + } else { + list = getImageType2(310); + } + showUploadImage(list); + + } + }); + ViewClicksAntiShake.clicksAntiShake(submit, new ViewClicksAntiShake.ViewClicksCallBack() { + @Override + public void onViewClicks() { + if (feedbackEdit.getText().length() == 0) { + ToastUtil.show(R.string.activity_feedback_edit_submit_tip1); + return; + } + JSONArray images = new JSONArray(); + if (img1.getTag() != null) { + images.add((String) img1.getTag()); + } + if (img2.getTag() != null) { + images.add((String) img2.getTag()); + } + if (img3.getTag() != null) { + images.add((String) img3.getTag()); + } + LiveNetManager.get(mContext) + .feedback(feedbackEdit.getText().toString(), + images, + ciEdit.getText().toString(), + new HttpCallback() { + @Override + public void onSuccess(HttpCallbackModel data) { + finish(); + RouteUtil.forwardActivity(RouteUtil.PATH_FEEDBACK_SUCCESS_ACTIVITY); + } + + @Override + public void onError(String error) { + ToastUtil.show(error); + } + } + ); + + } + }); + img1.setOnLongClickListener(new View.OnLongClickListener() { + @Override + public boolean onLongClick(View view) { + ToastUtil.show("1"); + return true; + } + }); + img2.setOnLongClickListener(new View.OnLongClickListener() { + @Override + public boolean onLongClick(View view) { + ToastUtil.show("2"); + return true; + } + }); + img3.setOnLongClickListener(new View.OnLongClickListener() { + @Override + public boolean onLongClick(View view) { + ToastUtil.show("3"); + return true; + } + }); + imageUtil.setImageResultCallback(new ImageResultCallback() { + + + @Override + public void onSuccess(File file) { + ToastUtil.show("图片地址:" + file.getAbsolutePath()); + onSuccessToQiNiuUrl(mContext, file, new OnItemClickListener() { + @Override + public void onItemClick(String bean, int position) { + if (loadingDialog != null) { + loadingDialog.dismiss(); + loadingDialog = null; + } + switch (clickImage) { + case 101: + case 112: + ImgLoader.display(mContext, bean, img1); + img1.setTag(bean); + if (img2.getTag() == null) { + img2.setImageResource(R.mipmap.icon_activity_feedback_edit_img_add); + img2.setVisibility(View.VISIBLE); + } else if (img3.getTag() == null) { + img3.setVisibility(View.VISIBLE); + img3.setImageResource(R.mipmap.icon_activity_feedback_edit_img_add); + } + break; + case 201: + case 212: + ImgLoader.display(mContext, bean, img2); + img2.setTag(bean); + if (img3.getTag() == null) { + img3.setVisibility(View.VISIBLE); + img3.setImageResource(R.mipmap.icon_activity_feedback_edit_img_add); + } + break; + case 301: + case 312: + ImgLoader.display(mContext, bean, img3); + img3.setTag(bean); + break; + } + } + }); + } + + @Override + public void onFailure() { + super.onFailure(); + if (loadingDialog != null) { + loadingDialog.dismiss(); + loadingDialog = null; + } + } + }); + } + + private void showUploadImage(SparseArray list) { + DialogUitl.showStringArrayDialog(mContext, list, new DialogUitl.StringArrayDialogCallback() { + @Override + public void onItemClick(String text, int tag) { + clickImage = tag; + switch (tag) { + case 101: + uploadImage(img1); + break; + case 201: + uploadImage(img2); + break; + case 301: + uploadImage(img3); + break; + case 111: + deleteImage(1); + break; + case 211: + deleteImage(2); + break; + case 311: + deleteImage(3); + break; + case 112: + changeImage(img1); + break; + case 212: + changeImage(img2); + break; + case 312: + changeImage(img3); + break; + } + } + }); + } + + private void uploadImage(ImageView imageView) { + if (loadingDialog != null) { + loadingDialog.dismiss(); + loadingDialog = null; + } + loadingDialog = DialogUitl.loadingDialog(mContext); + loadingDialog.show(); + imageUtil.getImageByAlumb(false); + } + + private void deleteImage(int index) { + if (index == 1) { + if (img2.getTag() != null) { + img1.setTag(img2.getTag()); + ImgLoader.display(mContext, (String) img1.getTag(), img1); + if (img3.getTag() != null) { + img2.setTag(img3.getTag()); + ImgLoader.display(mContext, (String) img2.getTag(), img2); + img3.setTag(null); + img3.setImageResource(R.mipmap.icon_activity_feedback_edit_img_add); + } else { + img2.setTag(null); + img2.setImageResource(R.mipmap.icon_activity_feedback_edit_img_add); + img3.setTag(null); + img3.setVisibility(View.GONE); + } + } else { + img1.setTag(null); + img1.setImageResource(R.mipmap.icon_activity_feedback_edit_img_add); + img2.setTag(null); + img2.setVisibility(View.GONE); + img3.setTag(null); + img3.setVisibility(View.GONE); + } + } else if (index == 2) { + if (img3.getTag() != null) { + img2.setTag(img3.getTag()); + ImgLoader.display(mContext, (String) img2.getTag(), img2); + img3.setTag(null); + img3.setImageResource(R.mipmap.icon_activity_feedback_edit_img_add); + } else { + img2.setTag(null); + img2.setImageResource(R.mipmap.icon_activity_feedback_edit_img_add); + img3.setTag(null); + img3.setVisibility(View.GONE); + } + } else if (index == 3) { + img3.setTag(null); + img3.setImageResource(R.mipmap.icon_activity_feedback_edit_img_add); + } + + } + + private void changeImage(ImageView imageView) { + uploadImage(imageView); + } + + private SparseArray getImageType1(int key) { + SparseArray array = new SparseArray<>(); + array.put(key + 1, WordUtil.getNewString(R.string.activity_feedback_edit_img_type1_upload)); + return array; + } + + private SparseArray getImageType2(int key) { + SparseArray array = new SparseArray<>(); + array.put(key + 1, WordUtil.getNewString(R.string.activity_feedback_edit_img_type2_delete)); + array.put(key + 2, WordUtil.getNewString(R.string.activity_feedback_edit_img_type2_change)); + return array; + } + + private void initView() { + feedbackEdit = findViewById(R.id.tv_feedback); + ciEdit = findViewById(R.id.edit_ci); + img1 = findViewById(R.id.img1); + img2 = findViewById(R.id.img2); + img3 = findViewById(R.id.img3); + submit = findViewById(R.id.btn_sub); + editNumber = findViewById(R.id.tv_number); + editNumber.setTextColor(Color.parseColor("#333333")); + } +} diff --git a/main/src/main/java/com/yunbao/main/activity/FeedbackSuccessActivity.java b/main/src/main/java/com/yunbao/main/activity/FeedbackSuccessActivity.java new file mode 100644 index 000000000..c44e85a2a --- /dev/null +++ b/main/src/main/java/com/yunbao/main/activity/FeedbackSuccessActivity.java @@ -0,0 +1,29 @@ +package com.yunbao.main.activity; + +import com.alibaba.android.arouter.facade.annotation.Route; +import com.yunbao.common.activity.AbsActivity; +import com.yunbao.common.utils.RouteUtil; +import com.yunbao.common.utils.WordUtil; +import com.yunbao.common.views.weight.ViewClicksAntiShake; +import com.yunbao.main.R; + +@Route(path = RouteUtil.PATH_FEEDBACK_SUCCESS_ACTIVITY) +public class FeedbackSuccessActivity extends AbsActivity { + @Override + protected int getLayoutId() { + return R.layout.activity_feedback_success; + } + + @Override + protected void main() { + super.main(); + setTitleBold(true); + setTitle(WordUtil.getNewString(R.string.activity_feedback_edit_feedback_top)); + ViewClicksAntiShake.clicksAntiShake(findViewById(R.id.sub), new ViewClicksAntiShake.ViewClicksCallBack() { + @Override + public void onViewClicks() { + finish(); + } + }); + } +} diff --git a/main/src/main/java/com/yunbao/main/activity/SettingActivity.java b/main/src/main/java/com/yunbao/main/activity/SettingActivity.java index b34529661..8e3f01053 100644 --- a/main/src/main/java/com/yunbao/main/activity/SettingActivity.java +++ b/main/src/main/java/com/yunbao/main/activity/SettingActivity.java @@ -316,12 +316,15 @@ public class SettingActivity extends AbsActivity implements OnItemClickListener< .show(); } + }else if(bean.getId()==17){ + RouteUtil.forwardActivity(RouteUtil.PATH_FEEDBACK_ACTIVITY); } } else { if (bean.getId() == 17) {//意见反馈要在url上加版本号和设备号 href += "&version=" + android.os.Build.VERSION.RELEASE + "&model=" + android.os.Build.MODEL; } - WebViewActivity.forward(mContext, href,false); + // WebViewActivity.forward(mContext, href,false); + RouteUtil.forwardActivity(RouteUtil.PATH_FEEDBACK_ACTIVITY); } } diff --git a/main/src/main/java/com/yunbao/main/views/MainMeViewHolder.java b/main/src/main/java/com/yunbao/main/views/MainMeViewHolder.java index 2cd1816ed..72ac75dc5 100644 --- a/main/src/main/java/com/yunbao/main/views/MainMeViewHolder.java +++ b/main/src/main/java/com/yunbao/main/views/MainMeViewHolder.java @@ -355,7 +355,7 @@ public class MainMeViewHolder extends AbsMainViewHolder implements OnItemClickLi if (u.getDress().getMedal() != null) { Log.e("tag", u.getDress().getMedal()); - ImgLoader.displayWithError(mContext, u.getDress().getMedal(), user_noble_ico,R.mipmap.icon_vip_gold); + ImgLoader.displayWithError(mContext, u.getDress().getMedal(), user_noble_ico, R.mipmap.icon_vip_gold); } else { user_noble_ico.setImageResource(R.mipmap.icon_vip_gold); } @@ -468,6 +468,10 @@ public class MainMeViewHolder extends AbsMainViewHolder implements OnItemClickLi MobclickAgent.onEvent(mContext, "my_room", "个人中心点房间管理"); forwardRoomManage(); break; + case 26: + case 17: + RouteUtil.forwardActivity(RouteUtil.PATH_FEEDBACK_ACTIVITY); + break; } } else { //21 在线客服 @@ -506,7 +510,10 @@ public class MainMeViewHolder extends AbsMainViewHolder implements OnItemClickLi if (bean.getId() == 24) { MobclickAgent.onEvent(mContext, "my_pack", "个人中心点包裹"); } - WebViewActivity.forward(mContext, url, false); + if (bean.getId() == 17) { + RouteUtil.forwardActivity(RouteUtil.PATH_FEEDBACK_ACTIVITY); + } else + WebViewActivity.forward(mContext, url, false); } } diff --git a/main/src/main/res/drawable/bg_btn_feedback_edit_tv_edit.xml b/main/src/main/res/drawable/bg_btn_feedback_edit_tv_edit.xml new file mode 100644 index 000000000..0d58b3038 --- /dev/null +++ b/main/src/main/res/drawable/bg_btn_feedback_edit_tv_edit.xml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/main/src/main/res/drawable/bg_btn_feedback_success.xml b/main/src/main/res/drawable/bg_btn_feedback_success.xml new file mode 100644 index 000000000..cb81e4f44 --- /dev/null +++ b/main/src/main/res/drawable/bg_btn_feedback_success.xml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/main/src/main/res/layout/activity_feedback.xml b/main/src/main/res/layout/activity_feedback.xml new file mode 100644 index 000000000..85e8bdf23 --- /dev/null +++ b/main/src/main/res/layout/activity_feedback.xml @@ -0,0 +1,61 @@ + + + + + + + + + +