Răsfoiți Sursa

feat: 举报,帮助中心,bugfix

DoggyZhang 3 luni în urmă
părinte
comite
7a5cc9d25a
33 a modificat fișierele cu 420 adăugiri și 125 ștergeri
  1. 0 6
      app/src/main/java/com/adealink/weparty/module/profile/Router.kt
  2. 6 1
      app/src/main/java/com/adealink/weparty/update/IUpdateManager.kt
  3. 21 1
      app/src/main/java/com/adealink/weparty/update/UpdateManager.kt
  4. 8 0
      app/src/main/java/com/adealink/weparty/update/listener/IUpdateListener.kt
  5. 3 3
      module/im/src/main/java/com/adealink/weparty/im/session/dialog/SessionSettingDialog.kt
  6. 2 1
      module/playmate/src/main/java/com/adealink/weparty/playmate/detail/comp/PlaymateDetailBottomComp.kt
  7. 3 2
      module/playmate/src/main/java/com/adealink/weparty/playmate/detail/comp/PlaymateToolBarViewComp.kt
  8. 4 1
      module/playmate/src/main/res/layout/activity_playmate_detail.xml
  9. 0 4
      module/profile/src/main/AndroidManifest.xml
  10. 3 2
      module/profile/src/main/java/com/adealink/weparty/profile/comp/ProfileToolBarViewComp.kt
  11. 24 0
      module/profile/src/main/java/com/adealink/weparty/profile/edit/EditProfileActivity.kt
  12. 5 5
      module/profile/src/main/java/com/adealink/weparty/profile/relation/viewmodel/RelationShipTab.kt
  13. 0 45
      module/profile/src/main/java/com/adealink/weparty/profile/report/ReportActivity.kt
  14. 0 15
      module/profile/src/main/res/layout/activity_profile_report.xml
  15. 1 0
      module/profile/src/main/res/values-in/strings.xml
  16. 1 0
      module/profile/src/main/res/values-zh/strings.xml
  17. 1 0
      module/profile/src/main/res/values/strings.xml
  18. 32 1
      module/setting/src/main/java/com/adealink/weparty/setting/SettingActivity.kt
  19. 13 0
      module/setting/src/main/java/com/adealink/weparty/setting/datasource/remote/SettingHttpService.kt
  20. 30 6
      module/setting/src/main/java/com/adealink/weparty/setting/helpcenter/HelpCenterActivity.kt
  21. 2 5
      module/setting/src/main/java/com/adealink/weparty/setting/helpcenter/data/HelpCenterData.kt
  22. 58 5
      module/setting/src/main/java/com/adealink/weparty/setting/helpcenter/viewmodel/HelpCenterViewModel.kt
  23. 34 7
      module/setting/src/main/java/com/adealink/weparty/setting/report/ReportActivity.kt
  24. 15 0
      module/setting/src/main/java/com/adealink/weparty/setting/report/ReportData.kt
  25. 56 8
      module/setting/src/main/java/com/adealink/weparty/setting/report/viewmodel/ReportViewModel.kt
  26. 60 1
      module/setting/src/main/java/com/adealink/weparty/setting/viewmodel/SettingViewModel.kt
  27. 31 0
      module/setting/src/main/res/layout/activity_setting.xml
  28. 1 1
      module/setting/src/main/res/values-in/strings.xml
  29. 1 1
      module/setting/src/main/res/values-zh/strings.xml
  30. 2 1
      module/setting/src/main/res/values/strings.xml
  31. 1 1
      module/wallet/src/main/res/values-in/strings.xml
  32. 1 1
      module/wallet/src/main/res/values-zh/strings.xml
  33. 1 1
      module/wallet/src/main/res/values/strings.xml

+ 0 - 6
app/src/main/java/com/adealink/weparty/module/profile/Router.kt

@@ -41,12 +41,6 @@ interface Profile {
         }
     }
 
-    interface Report {
-        companion object {
-            const val PATH = "${Common.PATH}/report"
-        }
-    }
-
     interface BlackList {
         companion object {
             const val PATH = "${Common.PATH}/black_list"

+ 6 - 1
app/src/main/java/com/adealink/weparty/update/IUpdateManager.kt

@@ -1,7 +1,12 @@
 package com.adealink.weparty.update
 
 import androidx.fragment.app.FragmentActivity
+import com.adealink.frame.frame.IBaseFrame
+import com.adealink.weparty.update.listener.IUpdateListener
+
+interface IUpdateManager : IBaseFrame<IUpdateListener> {
+
+    fun hasNewVersionUpdate(): Boolean
 
-interface IUpdateManager {
     fun checkUpdate(activity: FragmentActivity)
 }

+ 21 - 1
app/src/main/java/com/adealink/weparty/update/UpdateManager.kt

@@ -2,6 +2,7 @@ package com.adealink.weparty.update
 
 import androidx.fragment.app.FragmentActivity
 import com.adealink.frame.aab.util.getCompatString
+import com.adealink.frame.frame.BaseFrame
 import com.adealink.frame.log.Log
 import com.adealink.frame.util.AppUtil
 import com.adealink.frame.util.PackageUtil
@@ -9,6 +10,7 @@ import com.adealink.frame.util.differentDays
 import com.adealink.weparty.R
 import com.adealink.weparty.commonui.widget.CommonDialog
 import com.adealink.weparty.storage.AppPref
+import com.adealink.weparty.update.listener.IUpdateListener
 import com.google.android.play.core.appupdate.AppUpdateInfo
 import com.google.android.play.core.appupdate.AppUpdateManagerFactory
 import com.google.android.play.core.install.InstallStateUpdatedListener
@@ -22,7 +24,9 @@ import kotlin.math.min
 
 val updateManager: IUpdateManager by lazy { UpdateManager() }
 
-class UpdateManager : IUpdateManager {
+class UpdateManager : BaseFrame<IUpdateListener>(), IUpdateManager {
+
+    private var hasNewVersion = false
     private val appUpdateManager by lazy { AppUpdateManagerFactory.create(AppUtil.appContext) }
     private var activityWeakReference: WeakReference<FragmentActivity>? = null
     private val forceUpdateVersionCodeSet = mutableSetOf<Int>()
@@ -34,6 +38,11 @@ class UpdateManager : IUpdateManager {
         }
     }
 
+    override fun hasNewVersionUpdate(): Boolean {
+        return hasNewVersion
+    }
+
+
     override fun checkUpdate(activity: FragmentActivity) {
         activityWeakReference = WeakReference(activity)
         appUpdateManager.appUpdateInfo.addOnSuccessListener { appUpdateInfo ->
@@ -41,6 +50,17 @@ class UpdateManager : IUpdateManager {
                 TAG_UPDATE,
                 "check update success, availableVersionCode:${appUpdateInfo.availableVersionCode()}"
             )
+            val installStatus = appUpdateInfo.installStatus()
+            val updateAvailability = appUpdateInfo.updateAvailability()
+            if (installStatus == InstallStatus.DOWNLOADED
+                || updateAvailability == UpdateAvailability.UPDATE_AVAILABLE
+            ) {
+                hasNewVersion = true
+                dispatch {
+                    it.notifyHasNewVersion(true)
+                }
+            }
+
             if (appUpdateInfo.installStatus() == InstallStatus.DOWNLOADED) {
                 showCompleteUpdateDialog()
                 return@addOnSuccessListener

+ 8 - 0
app/src/main/java/com/adealink/weparty/update/listener/IUpdateListener.kt

@@ -0,0 +1,8 @@
+package com.adealink.weparty.update.listener
+
+import com.adealink.frame.frame.IListener
+
+
+interface IUpdateListener : IListener {
+    fun notifyHasNewVersion(newVersion: Boolean)
+}

+ 3 - 3
module/im/src/main/java/com/adealink/weparty/im/session/dialog/SessionSettingDialog.kt

@@ -12,8 +12,8 @@ import com.adealink.weparty.im.R
 import com.adealink.weparty.im.databinding.DialogSessionSettingBinding
 import com.adealink.weparty.im.session.viewmodel.SessionSettingViewModel
 import com.adealink.weparty.im.viewmodel.IMViewModelFactory
-import com.adealink.weparty.module.profile.Profile
 import com.adealink.weparty.module.profile.ProfileModule
+import com.adealink.weparty.module.setting.Setting
 import com.tencent.qcloud.tuikit.tuichat.bean.ChatInfo
 import com.adealink.weparty.R as APP_R
 
@@ -98,8 +98,8 @@ class SessionSettingDialog : BottomDialogFragment(R.layout.dialog_session_settin
 
     private fun goReport() {
         val act = activity ?: return
-        Router.build(act, Profile.Report.PATH)
-            .putExtra(Profile.Common.EXTRA_UID, uid)
+        Router.build(act, Setting.Report.PATH)
+            .putExtra(Setting.Report.EXTRA_UID, uid)
             .start()
     }
 }

+ 2 - 1
module/playmate/src/main/java/com/adealink/weparty/playmate/detail/comp/PlaymateDetailBottomComp.kt

@@ -13,6 +13,7 @@ import com.adealink.weparty.commonui.ext.show
 import com.adealink.weparty.module.im.IMModule
 import com.adealink.weparty.module.order.Order
 import com.adealink.weparty.module.playmate.data.PlaymateDetailData
+import com.adealink.weparty.module.profile.ProfileModule
 import com.adealink.weparty.playmate.databinding.LayoutPlaymateDetailBottomBinding
 import com.adealink.weparty.playmate.detail.viewmodel.PlaymateDetailViewModel
 import com.adealink.weparty.playmate.viewmodel.PlaymateViewModelFactory
@@ -52,7 +53,7 @@ class PlaymateDetailBottomComp(
     }
 
     private fun updateBottom(data: PlaymateDetailData?) {
-        if (data == null) {
+        if (data == null || data.uid == ProfileModule.getMyUid()) {
             binding.vPrice.gone()
         } else {
             binding.vPrice.show()

+ 3 - 2
module/playmate/src/main/java/com/adealink/weparty/playmate/detail/comp/PlaymateToolBarViewComp.kt

@@ -29,6 +29,7 @@ import com.adealink.weparty.commonui.widget.CommonDialog
 import com.adealink.weparty.module.profile.Profile
 import com.adealink.weparty.module.profile.ProfileModule
 import com.adealink.weparty.module.profile.data.isFollowed
+import com.adealink.weparty.module.setting.Setting
 import com.adealink.weparty.playmate.R
 import com.adealink.weparty.playmate.databinding.ActivityPlaymateDetailBinding
 import com.adealink.weparty.playmate.detail.viewmodel.PlaymateDetailViewModel
@@ -267,8 +268,8 @@ class PlaymateToolBarViewComp(
     private fun clickReport() {
         val uid = uid ?: return
         val act = activity ?: return
-        Router.build(act, Profile.Report.PATH)
-            .putExtra(Profile.Common.EXTRA_UID, uid)
+        Router.build(act, Setting.Report.PATH)
+            .putExtra(Setting.Report.EXTRA_UID, uid)
             .start()
     }
 

+ 4 - 1
module/playmate/src/main/res/layout/activity_playmate_detail.xml

@@ -1,6 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 <androidx.coordinatorlayout.widget.CoordinatorLayout 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/black">
@@ -54,6 +55,8 @@
         layout="@layout/layout_playmate_detail_bottom"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:layout_gravity="bottom" />
+        android:layout_gravity="bottom"
+        android:visibility="gone"
+        tools:visibility="visible" />
 
 </androidx.coordinatorlayout.widget.CoordinatorLayout>

+ 0 - 4
module/profile/src/main/AndroidManifest.xml

@@ -28,10 +28,6 @@
             android:name=".search.SearchActivity"
             android:screenOrientation="portrait"
             android:theme="@style/AppTheme" />
-        <activity
-            android:name=".report.ReportActivity"
-            android:screenOrientation="portrait"
-            android:theme="@style/AppTheme" />
         <activity
             android:name=".blacklist.BlackListActivity"
             android:screenOrientation="portrait"

+ 3 - 2
module/profile/src/main/java/com/adealink/weparty/profile/comp/ProfileToolBarViewComp.kt

@@ -26,6 +26,7 @@ import com.adealink.weparty.commonui.widget.CommonDialog
 import com.adealink.weparty.module.profile.Profile
 import com.adealink.weparty.module.profile.ProfileModule
 import com.adealink.weparty.module.profile.data.isFollowed
+import com.adealink.weparty.module.setting.Setting
 import com.adealink.weparty.module.share.Share
 import com.adealink.weparty.profile.databinding.ActivityUserProfileBinding
 import com.adealink.weparty.profile.relation.viewmodel.BlackViewModel
@@ -291,8 +292,8 @@ class ProfileToolBarViewComp(
 
     private fun clickReport() {
         activity?.let { act ->
-            Router.build(act, Profile.Report.PATH)
-                .putExtra(Profile.Common.EXTRA_UID, userUid)
+            Router.build(act, Setting.Report.PATH)
+                .putExtra(Setting.Report.EXTRA_UID, userUid)
                 .start()
         }
     }

+ 24 - 0
module/profile/src/main/java/com/adealink/weparty/profile/edit/EditProfileActivity.kt

@@ -16,8 +16,10 @@ import com.adealink.weparty.commonui.BaseActivity
 import com.adealink.weparty.commonui.ext.dp
 import com.adealink.weparty.commonui.toast.util.showFailedToast
 import com.adealink.weparty.commonui.toast.util.showToast
+import com.adealink.weparty.commonui.widget.CommonDialog
 import com.adealink.weparty.module.profile.Profile
 import com.adealink.weparty.module.profile.ProfileModule
+import com.adealink.weparty.profile.R
 import com.adealink.weparty.profile.databinding.ActivityEditProfileBinding
 import com.adealink.weparty.profile.edit.comp.EditAvatarComp
 import com.adealink.weparty.profile.edit.comp.EditPersonComp
@@ -54,6 +56,9 @@ class EditProfileActivity : BaseActivity() {
         binding.clContent.setPadding(
             16.dp(), 0, 16.dp(), naviBarHeight() + 24.dp()
         )
+        binding.ivClose.onClick {
+            clickClose()
+        }
         binding.btnSave.onClick {
             saveEdit()
         }
@@ -70,6 +75,25 @@ class EditProfileActivity : BaseActivity() {
     override fun loadData() {
         super.loadData()
         editViewModel.setUserInfo(ProfileModule.getMyUserInfo())
+        editViewModel.editUserInfoLD.observe(this) { edit ->
+            binding.btnSave.isEnabled = edit.isEdited
+        }
+    }
+
+    private fun clickClose() {
+        val editUserInfo = editViewModel.getEditUserInfo()
+        if (editUserInfo.isEdited) {
+            CommonDialog.Builder()
+                .message(getCompatString(R.string.profile_edit_not_save_tips))
+                .positiveText(getCompatString(APP_R.string.commonui_confirm))
+                .setShowDefaultCancel(true)
+                .onPositive {
+                    finish()
+                }
+                .show(supportFragmentManager, "CloseConfirm")
+            return
+        }
+        finish()
     }
 
     private fun saveEdit() {

+ 5 - 5
module/profile/src/main/java/com/adealink/weparty/profile/relation/viewmodel/RelationShipTab.kt

@@ -5,15 +5,15 @@ import com.adealink.weparty.profile.relation.FansFragment
 import com.adealink.weparty.profile.relation.FollowFragment
 
 enum class RelationShipTab(val index: Int) {
-    /**
-     * 关注
-     */
-    FOLLOW(0),
 
     /**
      * 粉丝
      */
-    FANS(1);
+    FANS(0),
+    /**
+     * 关注
+     */
+    FOLLOW(1),
 }
 
 data class Tab(

+ 0 - 45
module/profile/src/main/java/com/adealink/weparty/profile/report/ReportActivity.kt

@@ -1,45 +0,0 @@
-package com.adealink.weparty.profile.report
-
-import androidx.constraintlayout.widget.ConstraintLayout
-import androidx.core.view.updateLayoutParams
-import com.adealink.frame.aab.util.getCompatDimension
-import com.adealink.frame.mvvm.view.viewBinding
-import com.adealink.frame.router.Router
-import com.adealink.frame.router.annotation.BindExtra
-import com.adealink.frame.router.annotation.RouterUri
-import com.adealink.frame.util.statusBarHeight
-import com.adealink.weparty.commonui.BaseActivity
-import com.adealink.weparty.module.profile.Profile
-import com.adealink.weparty.profile.databinding.ActivityProfileReportBinding
-import com.adealink.weparty.R as APP_R
-
-@RouterUri(
-    path = [Profile.Report.PATH],
-    desc = "举报"
-)
-class ReportActivity : BaseActivity() {
-
-    @BindExtra(name = Profile.Common.EXTRA_UID)
-    var userUid: String = ""
-
-    private val binding by viewBinding(ActivityProfileReportBinding::inflate)
-
-    override fun onBeforeCreate() {
-        super.onBeforeCreate()
-        Router.bind(this)
-    }
-
-    override fun initViews() {
-        super.initViews()
-        setContentView(binding.root)
-        val statusBarHeight = this@ReportActivity.statusBarHeight()
-        binding.topBar.setPadding(0, statusBarHeight, 0, 0)
-        binding.topBar.updateLayoutParams<ConstraintLayout.LayoutParams> {
-            height =
-                getCompatDimension(APP_R.dimen.common_top_bar_height).toInt() + this@ReportActivity.statusBarHeight()
-        }
-
-    }
-
-
-}

+ 0 - 15
module/profile/src/main/res/layout/activity_profile_report.xml

@@ -1,15 +0,0 @@
-<?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.adealink.weparty.commonui.widget.CommonTopBar
-        android:id="@+id/top_bar"
-        android:layout_width="match_parent"
-        android:layout_height="@dimen/common_top_bar_height"
-        app:layout_constraintTop_toTopOf="parent"
-        app:top_bar_title="@string/common_report" />
-
-
-</androidx.constraintlayout.widget.ConstraintLayout>

+ 1 - 0
module/profile/src/main/res/values-in/strings.xml

@@ -69,4 +69,5 @@
     <string name="profile_playmate_charm_star">Kesan yang baik</string>
     <string name="profile_edit_interest">Learn more about you</string>
     <string name="profile_edit_interest_tips">Select to find more compatible friends</string>
+    <string name="profile_edit_not_save_tips">Perubahan tidak tersimpan, konfirmasi keluar?</string>
 </resources>

+ 1 - 0
module/profile/src/main/res/values-zh/strings.xml

@@ -69,4 +69,5 @@
     <string name="profile_playmate_charm_star">给好感度</string>
     <string name="profile_edit_interest">了解你更多</string>
     <string name="profile_edit_interest_tips">选择后,帮你找到更合拍的朋友</string>
+    <string name="profile_edit_not_save_tips">修改未保存,确认退出?</string>
 </resources>

+ 1 - 0
module/profile/src/main/res/values/strings.xml

@@ -70,4 +70,5 @@
     <string name="profile_playmate_charm_star">Good impression</string>
     <string name="profile_edit_interest">Learn more about you</string>
     <string name="profile_edit_interest_tips">Select to find more compatible friends</string>
+    <string name="profile_edit_not_save_tips">Edits not saved, confirm exit?</string>
 </resources>

+ 32 - 1
module/setting/src/main/java/com/adealink/weparty/setting/SettingActivity.kt

@@ -1,5 +1,7 @@
 package com.adealink.weparty.setting
 
+import android.annotation.SuppressLint
+import androidx.activity.viewModels
 import androidx.constraintlayout.widget.ConstraintLayout
 import androidx.core.view.updateLayoutParams
 import com.adealink.frame.aab.util.getCompatDimension
@@ -21,6 +23,8 @@ import com.adealink.weparty.module.setting.Setting
 import com.adealink.weparty.module.webview.Web
 import com.adealink.weparty.setting.databinding.ActivitySettingBinding
 import com.adealink.weparty.setting.language.LanguageSettingDialog
+import com.adealink.weparty.setting.viewmodel.SettingViewModel
+import com.adealink.weparty.setting.viewmodel.SettingViewModelFactory
 import com.adealink.weparty.url.UrlConfig
 import com.adealink.weparty.R as APP_R
 
@@ -32,6 +36,8 @@ class SettingActivity : BaseActivity() {
 
     private val binding by viewBinding(ActivitySettingBinding::inflate)
 
+    private val settingViewModel by viewModels<SettingViewModel> { SettingViewModelFactory() }
+
     override fun onBeforeCreate() {
         super.onBeforeCreate()
         Router.bind(this)
@@ -75,20 +81,45 @@ class SettingActivity : BaseActivity() {
         }
     }
 
+    override fun observeViewModel() {
+        super.observeViewModel()
+        settingViewModel.newVersionLD.observe(this) {
+            binding.tvNewVersion.show(it)
+        }
+    }
+
+    override fun loadData() {
+        super.loadData()
+        settingViewModel.checkAppUpdate(this)
+        settingViewModel.getCacheSize().observe(this) { totalSize ->
+            binding.tvCacheSize.text = when {
+                totalSize <= 0 -> {
+                    "0MB"
+                }
+
+                else -> {
+                    "${totalSize / 1024 / 1024}MB"
+                }
+            }
+        }
+    }
+
     private fun clickLanguage() {
         LanguageSettingDialog().show(supportFragmentManager, Setting.Language.PATH)
     }
 
+    @SuppressLint("SetTextI18n")
     private fun clearCache() {
         CommonDialog.Builder()
             .title(getCompatString(R.string.setting_clear_cache_confirm_title))
-            .message(getCompatString(R.string.setting_clear_cache_confirm_desc))
             .showTopClosetButton(false)
             .canceledOnTouchOutside(true)
             .cancelable(true)
             .setShowDefaultCancel(true)
             .onPositive {
                 showToast(getCompatString(APP_R.string.common_success))
+                settingViewModel.clearCache()
+                binding.tvCacheSize.text = "0MB"
             }
             .show(supportFragmentManager, "ClearCache")
     }

+ 13 - 0
module/setting/src/main/java/com/adealink/weparty/setting/datasource/remote/SettingHttpService.kt

@@ -1,5 +1,18 @@
 package com.adealink.weparty.setting.datasource.remote
 
+import com.adealink.frame.base.Rlt
+import com.adealink.frame.network.data.Res
+import com.adealink.weparty.setting.report.FeedbackReq
+import com.adealink.weparty.setting.report.ReportReq
+import retrofit2.http.Body
+import retrofit2.http.POST
+
 interface SettingHttpService {
 
+    @POST("report/user")
+    suspend fun report(@Body req: ReportReq): Rlt<Res<Any>>
+
+
+    @POST("feedback/submit")
+    suspend fun feedback(@Body req: FeedbackReq): Rlt<Res<Any>>
 }

+ 30 - 6
module/setting/src/main/java/com/adealink/weparty/setting/helpcenter/HelpCenterActivity.kt

@@ -8,6 +8,8 @@ import androidx.constraintlayout.widget.ConstraintLayout
 import androidx.core.view.updateLayoutParams
 import androidx.recyclerview.widget.GridLayoutManager
 import com.adealink.frame.aab.util.getCompatDimension
+import com.adealink.frame.aab.util.getCompatString
+import com.adealink.frame.base.Rlt
 import com.adealink.frame.base.fastLazy
 import com.adealink.frame.mvvm.view.viewBinding
 import com.adealink.frame.router.Router
@@ -18,14 +20,17 @@ import com.adealink.weparty.commonui.BaseActivity
 import com.adealink.weparty.commonui.ext.dp
 import com.adealink.weparty.commonui.recycleview.adapter.MultiTypeListAdapter
 import com.adealink.weparty.commonui.recycleview.itemdecoration.GridSpacingItemDecoration
+import com.adealink.weparty.commonui.toast.util.showFailedToast
+import com.adealink.weparty.commonui.toast.util.showToast
 import com.adealink.weparty.imageselect.comp.TakeFromAlbumComp
+import com.adealink.weparty.module.image.data.PhotoData
 import com.adealink.weparty.module.setting.Setting
+import com.adealink.weparty.setting.R
 import com.adealink.weparty.setting.databinding.ActivityHelpCenterBinding
 import com.adealink.weparty.setting.helpcenter.adapter.AddPictureItemViewBinder
 import com.adealink.weparty.setting.helpcenter.adapter.PictureItemViewBinder
 import com.adealink.weparty.setting.helpcenter.data.AddPictureItemData
 import com.adealink.weparty.setting.helpcenter.data.BasePictureItemData
-import com.adealink.weparty.setting.helpcenter.data.PictureData
 import com.adealink.weparty.setting.helpcenter.viewmodel.HelpCenterViewModel
 import com.adealink.weparty.util.goImagePreviewActivity
 import com.qmuiteam.qmui.widget.util.QMUIKeyboardHelper
@@ -158,22 +163,41 @@ class HelpCenterActivity : BaseActivity() {
         takeFromAlbumComp.takeFromAlbum()
     }
 
-    private fun previewPicture(data: PictureData) {
-        if (data.uri.isNullOrEmpty()) {
+    private fun previewPicture(data: PhotoData) {
+        val uri = data.uri
+        if (uri.isNullOrEmpty()) {
             return
         }
         goImagePreviewActivity(
             this,
-            arrayListOf(data.uri)
+            arrayListOf(uri)
         )
     }
 
-    private fun deletePicture(data: PictureData) {
+    private fun deletePicture(data: PhotoData) {
         viewModel.removePicture(data)
     }
 
     private fun submit() {
-        viewModel.submit()
+        val content = binding.etInput.text?.trim()?.toString()
+        if (content.isNullOrEmpty()) {
+            showToast(getCompatString(R.string.setting_feedback_input_content))
+            return
+        }
+        showLoading()
+        viewModel.submit(content).observe(this) { rlt ->
+            dismissLoading()
+            when (rlt) {
+                is Rlt.Failed -> {
+                    showFailedToast(rlt)
+                }
+
+                is Rlt.Success -> {
+                    showToast(APP_R.string.common_success)
+                    finish()
+                }
+            }
+        }
     }
 
     override fun onDestroy() {

+ 2 - 5
module/setting/src/main/java/com/adealink/weparty/setting/helpcenter/data/HelpCenterData.kt

@@ -1,16 +1,13 @@
 package com.adealink.weparty.setting.helpcenter.data
 
 import com.adealink.weparty.commonui.recycleview.diffutil.BaseListItemData
+import com.adealink.weparty.module.image.data.PhotoData
 
-data class PictureData(
-    val path: String?,
-    val uri: String?
-)
 
 sealed class BasePictureItemData : BaseListItemData
 
 object AddPictureItemData : BasePictureItemData()
 
 data class PictureItemData(
-    val data: PictureData
+    val data: PhotoData
 ) : BasePictureItemData()

+ 58 - 5
module/setting/src/main/java/com/adealink/weparty/setting/helpcenter/viewmodel/HelpCenterViewModel.kt

@@ -1,27 +1,43 @@
 package com.adealink.weparty.setting.helpcenter.viewmodel
 
+import androidx.lifecycle.LiveData
 import androidx.lifecycle.MutableLiveData
+import com.adealink.frame.base.Rlt
+import com.adealink.frame.base.fastLazy
+import com.adealink.frame.mvvm.livedata.OnceMutableLiveData
 import com.adealink.frame.mvvm.viewmodel.BaseViewModel
+import com.adealink.weparty.App
+import com.adealink.weparty.image.EVIDENCE_IMAGE_MAX_HEIGHT
+import com.adealink.weparty.image.EVIDENCE_IMAGE_MAX_SIZE_KB
+import com.adealink.weparty.image.EVIDENCE_IMAGE_MAX_WIDTH
+import com.adealink.weparty.image.EVIDENCE_IMAGE_MIN_QUALITY
+import com.adealink.weparty.module.image.data.PhotoData
+import com.adealink.weparty.setting.datasource.remote.SettingHttpService
 import com.adealink.weparty.setting.helpcenter.data.AddPictureItemData
 import com.adealink.weparty.setting.helpcenter.data.BasePictureItemData
-import com.adealink.weparty.setting.helpcenter.data.PictureData
 import com.adealink.weparty.setting.helpcenter.data.PictureItemData
+import com.adealink.weparty.setting.report.FeedbackReq
+import com.adealink.weparty.util.uploadPhotos
 import kotlinx.coroutines.launch
 
 class HelpCenterViewModel : BaseViewModel() {
 
-    val pictureList = mutableListOf<PictureData>()
+    private val reportHttpService by fastLazy {
+        App.instance.networkService.getHttpService(SettingHttpService::class.java)
+    }
+
+    val pictureList = mutableListOf<PhotoData>()
 
     val pictureItemListLD = MutableLiveData<List<BasePictureItemData>>()
 
     fun addPicture(path: String?, uri: String?) {
         viewModelScope.launch {
-            pictureList.add(PictureData(path, uri))
+            pictureList.add(PhotoData(null, path, uri))
             onPictureListChanged()
         }
     }
 
-    fun removePicture(data: PictureData) {
+    fun removePicture(data: PhotoData) {
         viewModelScope.launch {
             pictureList.remove(data)
             onPictureListChanged()
@@ -42,8 +58,45 @@ class HelpCenterViewModel : BaseViewModel() {
         pictureItemListLD.send(itemList)
     }
 
-    fun submit() {
+    fun submit(
+        content: String?
+    ): LiveData<Rlt<Any>> {
+        val liveData = OnceMutableLiveData<Rlt<Any>>()
+        viewModelScope.launch {
+
+            val uploadImages = mutableListOf<PhotoData>()
+            pictureList.forEach { picture ->
+                if (picture.isLocal()) {
+                    uploadImages.add(picture)
+                }
+            }
+            //上传证据
+            val uploadRlt = uploadPhotos(
+                uploadImages,
+                EVIDENCE_IMAGE_MAX_WIDTH,
+                EVIDENCE_IMAGE_MAX_HEIGHT,
+                EVIDENCE_IMAGE_MAX_SIZE_KB,
+                EVIDENCE_IMAGE_MIN_QUALITY
+            )
+            when (uploadRlt) {
+                is Rlt.Failed -> {
+                    liveData.send(uploadRlt)
+                    return@launch
+                }
+
+                is Rlt.Success<List<PhotoData>> -> {
 
+                }
+            }
+            val rlt = reportHttpService.feedback(
+                FeedbackReq(
+                    content ?: "",
+                    pictureList.mapNotNull { it.url }
+                )
+            )
+            liveData.send(rlt)
+        }
+        return liveData
     }
 
 }

+ 34 - 7
module/setting/src/main/java/com/adealink/weparty/setting/report/ReportActivity.kt

@@ -8,6 +8,8 @@ import androidx.constraintlayout.widget.ConstraintLayout
 import androidx.core.view.updateLayoutParams
 import androidx.recyclerview.widget.GridLayoutManager
 import com.adealink.frame.aab.util.getCompatDimension
+import com.adealink.frame.aab.util.getCompatString
+import com.adealink.frame.base.Rlt
 import com.adealink.frame.base.fastLazy
 import com.adealink.frame.mvvm.view.viewBinding
 import com.adealink.frame.router.Router
@@ -20,8 +22,10 @@ import com.adealink.weparty.commonui.BaseActivity
 import com.adealink.weparty.commonui.ext.dp
 import com.adealink.weparty.commonui.recycleview.adapter.MultiTypeListAdapter
 import com.adealink.weparty.commonui.recycleview.itemdecoration.GridSpacingItemDecoration
+import com.adealink.weparty.commonui.toast.util.showFailedToast
 import com.adealink.weparty.commonui.toast.util.showToast
 import com.adealink.weparty.imageselect.comp.TakeFromAlbumComp
+import com.adealink.weparty.module.image.data.PhotoData
 import com.adealink.weparty.module.setting.Setting
 import com.adealink.weparty.setting.R
 import com.adealink.weparty.setting.databinding.ActivityReportBinding
@@ -29,7 +33,6 @@ import com.adealink.weparty.setting.helpcenter.adapter.AddPictureItemViewBinder
 import com.adealink.weparty.setting.helpcenter.adapter.PictureItemViewBinder
 import com.adealink.weparty.setting.helpcenter.data.AddPictureItemData
 import com.adealink.weparty.setting.helpcenter.data.BasePictureItemData
-import com.adealink.weparty.setting.helpcenter.data.PictureData
 import com.adealink.weparty.setting.report.viewmodel.ReportViewModel
 import com.adealink.weparty.util.goImagePreviewActivity
 import com.qmuiteam.qmui.widget.util.QMUIKeyboardHelper
@@ -144,6 +147,9 @@ class ReportActivity : BaseActivity() {
 
     override fun loadData() {
         super.loadData()
+        if (uid.isNullOrEmpty()) {
+            finish()
+        }
         pictureAdapter.submitList(
             listOf(AddPictureItemData)
         )
@@ -166,23 +172,44 @@ class ReportActivity : BaseActivity() {
         takeFromAlbumComp.takeFromAlbum()
     }
 
-    private fun previewPicture(data: PictureData) {
-        if (data.uri.isNullOrEmpty()) {
+    private fun previewPicture(data: PhotoData) {
+        val uri = data.uri
+        if (uri.isNullOrEmpty()) {
             return
         }
         goImagePreviewActivity(
             this,
-            arrayListOf(data.uri)
+            arrayListOf(uri)
         )
     }
 
-    private fun deletePicture(data: PictureData) {
+    private fun deletePicture(data: PhotoData) {
         viewModel.removePicture(data)
     }
 
     private fun submit() {
-        viewModel.submit().observe(this) {
-            showToast(R.string.setting_report_submit_success)
+        val uid = uid
+        if (uid.isNullOrEmpty()) {
+            return
+        }
+        val content = binding.etInput.text?.trim()?.toString()
+        if (content.isNullOrEmpty()) {
+            showToast(getCompatString(R.string.setting_report_input_content))
+            return
+        }
+        showLoading()
+        viewModel.submit(uid, content).observe(this) { rlt ->
+            dismissLoading()
+            when (rlt) {
+                is Rlt.Failed -> {
+                    showFailedToast(rlt)
+                }
+
+                is Rlt.Success -> {
+                    showToast(R.string.setting_report_submit_success)
+                    finish()
+                }
+            }
         }
     }
 

+ 15 - 0
module/setting/src/main/java/com/adealink/weparty/setting/report/ReportData.kt

@@ -0,0 +1,15 @@
+package com.adealink.weparty.setting.report
+
+import com.google.gson.annotations.SerializedName
+
+data class ReportReq(
+    @SerializedName("userNo") val uid: String,
+    @SerializedName("content") val content: String,
+    @SerializedName("images") val images: List<String>
+)
+
+
+data class FeedbackReq(
+    @SerializedName("content") val content: String,
+    @SerializedName("images") val images: List<String>
+)

+ 56 - 8
module/setting/src/main/java/com/adealink/weparty/setting/report/viewmodel/ReportViewModel.kt

@@ -3,28 +3,41 @@ package com.adealink.weparty.setting.report.viewmodel
 import androidx.lifecycle.LiveData
 import androidx.lifecycle.MutableLiveData
 import com.adealink.frame.base.Rlt
+import com.adealink.frame.base.fastLazy
 import com.adealink.frame.mvvm.livedata.OnceMutableLiveData
 import com.adealink.frame.mvvm.viewmodel.BaseViewModel
+import com.adealink.weparty.App
+import com.adealink.weparty.image.EVIDENCE_IMAGE_MAX_HEIGHT
+import com.adealink.weparty.image.EVIDENCE_IMAGE_MAX_SIZE_KB
+import com.adealink.weparty.image.EVIDENCE_IMAGE_MAX_WIDTH
+import com.adealink.weparty.image.EVIDENCE_IMAGE_MIN_QUALITY
+import com.adealink.weparty.module.image.data.PhotoData
+import com.adealink.weparty.setting.datasource.remote.SettingHttpService
 import com.adealink.weparty.setting.helpcenter.data.AddPictureItemData
 import com.adealink.weparty.setting.helpcenter.data.BasePictureItemData
-import com.adealink.weparty.setting.helpcenter.data.PictureData
 import com.adealink.weparty.setting.helpcenter.data.PictureItemData
+import com.adealink.weparty.setting.report.ReportReq
+import com.adealink.weparty.util.uploadPhotos
 import kotlinx.coroutines.launch
 
 class ReportViewModel : BaseViewModel() {
 
-    val pictureList = mutableListOf<PictureData>()
+    private val reportHttpService by fastLazy {
+        App.instance.networkService.getHttpService(SettingHttpService::class.java)
+    }
+
+    val pictureList = mutableListOf<PhotoData>()
 
     val pictureItemListLD = MutableLiveData<List<BasePictureItemData>>()
 
     fun addPicture(path: String?, uri: String?) {
         viewModelScope.launch {
-            pictureList.add(PictureData(path, uri))
+            pictureList.add(PhotoData(null, path, uri))
             onPictureListChanged()
         }
     }
 
-    fun removePicture(data: PictureData) {
+    fun removePicture(data: PhotoData) {
         viewModelScope.launch {
             pictureList.remove(data)
             onPictureListChanged()
@@ -38,17 +51,52 @@ class ReportViewModel : BaseViewModel() {
                 PictureItemData(it)
             }
         )
-        //小于9张图片,可以继续添加图片
-        if (pictureList.size < 9) {
+        //小于6张图片,可以继续添加图片
+        if (pictureList.size < 6) {
             itemList.add(AddPictureItemData)
         }
         pictureItemListLD.send(itemList)
     }
 
-    fun submit(): LiveData<Rlt<Any>> {
+    fun submit(
+        uid: String,
+        content: String?
+    ): LiveData<Rlt<Any>> {
         val liveData = OnceMutableLiveData<Rlt<Any>>()
         viewModelScope.launch {
-            liveData.send(Rlt.Success(Any()))
+
+            val uploadImages = mutableListOf<PhotoData>()
+            pictureList.forEach { picture ->
+                if (picture.isLocal()) {
+                    uploadImages.add(picture)
+                }
+            }
+            //上传证据
+            val uploadRlt = uploadPhotos(
+                uploadImages,
+                EVIDENCE_IMAGE_MAX_WIDTH,
+                EVIDENCE_IMAGE_MAX_HEIGHT,
+                EVIDENCE_IMAGE_MAX_SIZE_KB,
+                EVIDENCE_IMAGE_MIN_QUALITY
+            )
+            when (uploadRlt) {
+                is Rlt.Failed -> {
+                    liveData.send(uploadRlt)
+                    return@launch
+                }
+
+                is Rlt.Success<List<PhotoData>> -> {
+
+                }
+            }
+            val rlt = reportHttpService.report(
+                ReportReq(
+                    uid,
+                    content ?: "",
+                    pictureList.mapNotNull { it.url }
+                )
+            )
+            liveData.send(rlt)
         }
         return liveData
     }

+ 60 - 1
module/setting/src/main/java/com/adealink/weparty/setting/viewmodel/SettingViewModel.kt

@@ -1,8 +1,67 @@
 package com.adealink.weparty.setting.viewmodel
 
+import androidx.fragment.app.FragmentActivity
+import androidx.lifecycle.LiveData
+import androidx.lifecycle.MutableLiveData
+import com.adealink.frame.coroutine.dispatcher.Dispatcher
+import com.adealink.frame.image.imageService
+import com.adealink.frame.log.XLogHelper
+import com.adealink.frame.mvvm.livedata.OnceMutableLiveData
 import com.adealink.frame.mvvm.viewmodel.BaseViewModel
+import com.adealink.weparty.imageselect.util.clearAllProcessedImage
+import com.adealink.weparty.imageselect.util.getProcessedImageCacheSize
 import com.adealink.weparty.module.activity.viewmodel.IActivityViewModel
+import com.adealink.weparty.module.webview.WebModule
+import com.adealink.weparty.update.listener.IUpdateListener
+import com.adealink.weparty.update.updateManager
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.withContext
 
-class SettingViewModel : BaseViewModel(), IActivityViewModel {
+class SettingViewModel : BaseViewModel(), IActivityViewModel, IUpdateListener {
 
+    init {
+        updateManager.addListener(this)
+    }
+
+    override fun onCleared() {
+        super.onCleared()
+        updateManager.removeListener(this)
+    }
+
+    val newVersionLD = MutableLiveData<Boolean>()
+    fun checkAppUpdate(activity: FragmentActivity) {
+        viewModelScope.launch {
+            newVersionLD.send(updateManager.hasNewVersionUpdate())
+            updateManager.checkUpdate(activity)
+        }
+    }
+
+    fun getCacheSize(): LiveData<Long> {
+        val liveData: LiveData<Long> = OnceMutableLiveData()
+        viewModelScope.launch {
+            withContext(Dispatcher.WENEXT_THREAD_POOL) {
+                var totalSize: Long = 0
+                totalSize += imageService.getCacheSize()
+                totalSize += getProcessedImageCacheSize()
+                totalSize += WebModule.getCacheSize()
+                liveData.send(totalSize)
+            }
+        }
+        return liveData
+    }
+
+    fun clearCache() {
+        viewModelScope.launch {
+            withContext(Dispatcher.WENEXT_THREAD_POOL) {
+                imageService.clearCache()
+                clearAllProcessedImage()
+                XLogHelper.clearLogFiles()
+                WebModule.clearCache()
+            }
+        }
+    }
+
+    override fun notifyHasNewVersion(newVersion: Boolean) {
+        newVersionLD.send(newVersion)
+    }
 }

+ 31 - 0
module/setting/src/main/res/layout/activity_setting.xml

@@ -106,6 +106,20 @@
                         app:layout_constraintStart_toStartOf="parent"
                         app:layout_constraintTop_toTopOf="parent" />
 
+                    <androidx.appcompat.widget.AppCompatTextView
+                        android:id="@+id/tv_cache_size"
+                        android:layout_width="wrap_content"
+                        android:layout_height="wrap_content"
+                        android:layout_marginStart="20dp"
+                        android:layout_marginEnd="20dp"
+                        android:includeFontPadding="false"
+                        android:textColor="@color/color_FF1D2129"
+                        android:textSize="12sp"
+                        app:layout_constraintBottom_toBottomOf="parent"
+                        app:layout_constraintEnd_toEndOf="parent"
+                        app:layout_constraintTop_toTopOf="parent"
+                        tools:text="100MB" />
+
                     <androidx.appcompat.widget.AppCompatImageView
                         android:layout_width="16dp"
                         android:layout_height="16dp"
@@ -147,6 +161,23 @@
                         app:layout_constraintStart_toStartOf="parent"
                         app:layout_constraintTop_toTopOf="parent" />
 
+                    <androidx.appcompat.widget.AppCompatTextView
+                        android:id="@+id/tv_new_version"
+                        android:layout_width="wrap_content"
+                        android:layout_height="16dp"
+                        android:layout_marginEnd="20dp"
+                        android:background="@drawable/common_button_bg"
+                        android:paddingHorizontal="6dp"
+                        android:text="@string/common_new"
+                        android:textColor="@color/white"
+                        android:textSize="12sp"
+                        android:visibility="gone"
+                        app:common_button_type="normal"
+                        app:layout_constraintBottom_toBottomOf="parent"
+                        app:layout_constraintEnd_toEndOf="parent"
+                        app:layout_constraintTop_toTopOf="parent"
+                        tools:visibility="visible" />
+
                     <androidx.appcompat.widget.AppCompatImageView
                         android:layout_width="16dp"
                         android:layout_height="16dp"

+ 1 - 1
module/setting/src/main/res/values-in/strings.xml

@@ -14,10 +14,10 @@
     <string name="setting_help_picture_title">Bukti gambar (hingga 9 gambar)</string>
     <string name="setting_help_picture_desc">Unggah gambar untuk menampilkan bukti Anda</string>
     <string name="setting_clear_cache_confirm_title">Bersihkan Cache</string>
-    <string name="setting_clear_cache_confirm_desc">Permintaan untuk Membersihkan Cache</string>
     <string name="setting_logout_confirm_title">Keluar?</string>
     <string name="setting_report_content">Silakan isi konten laporan terperinci</string>
     <string name="setting_report_evidence">Bukti gambar (maksimum 6 gambar)</string>
     <string name="setting_report_evidence_desc">Unggah gambar untuk menampilkan bukti Anda</string>
     <string name="setting_report_submit_success">Anda telah mengirimkan laporan. Tim resmi akan memverifikasi situasi dan melanjutkan sesuai dengan prosedur</string>
+    <string name="setting_report_input_content">Silakan masukkan masalah yang ingin Anda laporkan.</string>
 </resources>

+ 1 - 1
module/setting/src/main/res/values-zh/strings.xml

@@ -14,10 +14,10 @@
     <string name="setting_help_picture_title">图片证据(最多9张)</string>
     <string name="setting_help_picture_desc">上传图片以展示您的证据</string>
     <string name="setting_clear_cache_confirm_title">清理缓存</string>
-    <string name="setting_clear_cache_confirm_desc">清理缓存提示词</string>
     <string name="setting_logout_confirm_title">是否退出登录?</string>
     <string name="setting_report_content">请填写详细的举报内容</string>
     <string name="setting_report_evidence">图片证明(最多6张)</string>
     <string name="setting_report_evidence_desc">上传图片显示你的证据</string>
     <string name="setting_report_submit_success">您已提交举报,待官方核实情况后会周青进行</string>
+    <string name="setting_report_input_content">请输入你要举报的问题</string>
 </resources>

+ 2 - 1
module/setting/src/main/res/values/strings.xml

@@ -14,10 +14,11 @@
     <string name="setting_help_picture_title">Picture proof (up to 9 images)</string>
     <string name="setting_help_picture_desc">Upload a picture to display your evidence</string>
     <string name="setting_clear_cache_confirm_title">Clear Cache</string>
-    <string name="setting_clear_cache_confirm_desc">Clear Cache Prompt</string>
     <string name="setting_logout_confirm_title">Logout?</string>
     <string name="setting_report_content">Please fill in the detailed report content</string>
     <string name="setting_report_evidence">Image proof (maximum 6 images)</string>
     <string name="setting_report_evidence_desc">Upload images to display your evidence</string>
     <string name="setting_report_submit_success">You have submitted a report. The official team will verify the situation and proceed accordingly</string>
+    <string name="setting_report_input_content">Please enter the issue you wish to report.</string>
+    <string name="setting_feedback_input_content">Please enter the issue you wish to feedback.</string>
 </resources>

+ 1 - 1
module/wallet/src/main/res/values-in/strings.xml

@@ -17,7 +17,7 @@
     <string name="wallet_withdraw_cash"><![CDATA[Penarikan Tunai >]]></string>
     <string name="wallet_recharge_instruction_title">Instruksi Isi Ulang</string>
     <string name="wallet_recharge_instruction_1">1. Setelah isi ulang berhasil, pasti akan ada penundaan dalam kedatangan dana di akun Anda. Mohon bersabar.</string>
-    <string name="wallet_recharge_instruction_2">2. Jika Anda mengalami masalah selama proses pengisian ulang, silakan klik "Umpan Balik".</string>
+    <string name="wallet_recharge_instruction_2">2. Jika Anda mengalami masalah selama proses pengisian ulang, Silakan kunjungi \"Pusat Bantuan\" untuk memberikan masukan..</string>
     <string name="wallet_recharge_not_selected">Silakan pilih paket pengisian ulang.</string>
     <string name="wallet_convert_currency_title">Konversi ke %s</string>
     <string name="wallet_all_convert_button">Semua</string>

+ 1 - 1
module/wallet/src/main/res/values-zh/strings.xml

@@ -17,7 +17,7 @@
     <string name="wallet_withdraw_cash"><![CDATA[提现 >]]></string>
     <string name="wallet_recharge_instruction_title">充值说明</string>
     <string name="wallet_recharge_instruction_1">1.充值成功后,账户会有延迟到账,请耐心等待;</string>
-    <string name="wallet_recharge_instruction_2">2.如果您在充值过程中遇到任何问题,请点击“反馈”</string>
+    <string name="wallet_recharge_instruction_2">2.如果您在充值过程中遇到任何问题,请前往“帮助中心”反馈</string>
     <string name="wallet_recharge_not_selected">请选择充值套餐</string>
     <string name="wallet_convert_currency_title">兑换为 %s</string>
     <string name="wallet_all_convert_button">全部兑换</string>

+ 1 - 1
module/wallet/src/main/res/values/strings.xml

@@ -17,7 +17,7 @@
     <string name="wallet_withdraw_cash"><![CDATA[Withdraw Crash >]]></string>
     <string name="wallet_recharge_instruction_title">Recharge Instructions</string>
     <string name="wallet_recharge_instruction_1">1. After a successful top-up, there will definitely be a delay in the funds arriving in your account. Please wait patiently.</string>
-    <string name="wallet_recharge_instruction_2">2. If you encounter any problems during the recharge process, please click "Feedback".</string>
+    <string name="wallet_recharge_instruction_2">2. If you encounter any problems during the recharge process, please go to \"Help Center\" to feedback.</string>
     <string name="wallet_recharge_not_selected">Please select recharge package.</string>
     <string name="wallet_convert_currency_title">Convert to %s</string>
     <string name="wallet_all_convert_button">All</string>