diff --git a/app/build.gradle b/app/build.gradle index 0427bbeb3d..69e6ba3d3b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -353,7 +353,7 @@ dependencies { implementation "io.github.florent37:shapeofview:$shapeOfView" - implementation 'io.github.sinaweibosdk:core:11.6.0@aar' + implementation "io.github.sinaweibosdk:core:${weiboSDK}" implementation project(':libraries:LGLibrary') // implementation project(':libraries:MTA') diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index ff4be2731b..7e4ec48515 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -722,6 +722,10 @@ + + = ArrayList() + private var mEditText: EditText? = null + private var drawableNormal: Drawable? = null + private var drawableSelected: Drawable? = null + private var mContext: Context? = null + + + //输入过程监听 + private var mInputListener: InputListener? = null + //输入完成监听 + private var mInputCompleteListener: InputCompleteListener? = null + + /** + * view 添加到窗口时,延迟 500ms 弹出软键盘 + */ + override fun onAttachedToWindow() { + super.onAttachedToWindow() + mEditText?.postDelayed({ showSoftKeyBoard() }, 500) + } + + /** + * 设置背景 + * @param textView + * @param drawable + */ + private fun setTextViewBackground(textView: TextView, drawable: Drawable?) { + if (drawable != null) textView.background = drawable + } + + /** + * 获取当前输入的内容 + * + * @return + */ + val content: String + get() { + val text = mEditText?.text + return if (TextUtils.isEmpty(text)) "" else mEditText?.text.toString() + } + + /** + * 清除内容 + */ + fun clearContent() { + mEditText?.setText("") + for (i in mTextViewList.indices) { + val textView = mTextViewList[i] + textView.text = "" + setTextViewBackground(textView, drawableNormal) + } + } + + /** + * 设置默认的内容 + * + * @param content + */ + fun setDefaultContent(content: String) { + mEditText?.setText(content) + mEditText?.requestFocus() + val chars = content.toCharArray() + val min = chars.size.coerceAtMost(mTextViewList.size) + for (i in 0 until min) { + val aChar = chars[i] + val s = aChar.toString() + val textView = mTextViewList[i] + textView.text = s + setTextViewBackground(textView, drawableSelected) + } + if (mInputCompleteListener != null && min == mTextViewList.size) mInputCompleteListener?.onComplete( + content.substring(0, min) + ) + } + + /** + * 显示软键盘 + */ + private fun showSoftKeyBoard() { + val imm = mContext?.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager + imm.showSoftInput(mEditText, InputMethodManager.SHOW_FORCED) + } + + /** + * 添加输入完成的监听 + * + * @param inputCompleteListener + */ + fun addInputCompleteListener(inputCompleteListener: InputCompleteListener?) { + mInputCompleteListener = inputCompleteListener + val content = mEditText?.text + if (!TextUtils.isEmpty(content) && content.toString().length == mTextViewList.size) { + mInputCompleteListener?.onComplete(content.toString()) + } + } + + /** + * 添加输入过程的监听 + * + * @param inputListener + */ + fun addInputListener(inputListener: InputListener?) { + mInputListener = inputListener + mInputListener?.onChange(mEditText?.text.toString()) + } + + interface InputCompleteListener { + fun onComplete(content: String) + } + + interface InputListener { + fun onChange(content: String) + } + + private fun px2sp(context: Context, pxValue: Float): Int { + val fontScale = context.resources.displayMetrics.scaledDensity + return (pxValue / fontScale + 0.5f).toInt() + } + + private fun sp2px(context: Context, spValue: Float): Int { + val fontScale = context.resources.displayMetrics.scaledDensity + return (spValue * fontScale + 0.5f).toInt() + } + + companion object { + //默认 item 个数为 4 个 + private const val DEFAULT_ITEM_COUNT = 4 + + //默认每个 item 的宽度为 100 + private const val DEFAULT_ITEM_WIDTH = 100 + + //默认每个 item 的间距为 50 + private const val DEFAULT_ITEM_MARGIN = 50 + + //默认每个 item 的字体大小为 14 + private const val DEFAULT_ITEM_TEXT_SIZE = 14 + + //默认密码明文显示时间为 200ms,之后密文显示 + private const val DEFAULT_PASSWORD_VISIBLE_TIME = 200 + } + + init { + mContext = context + orientation = HORIZONTAL + gravity = Gravity.CENTER + @SuppressLint("CustomViewStyleable") val obtainStyledAttributes = + getContext().obtainStyledAttributes(attrs, R.styleable.verify_EditText) + drawableNormal = + obtainStyledAttributes.getDrawable(R.styleable.verify_EditText_verify_background_normal) + drawableSelected = + obtainStyledAttributes.getDrawable(R.styleable.verify_EditText_verify_background_selected) + val textColor = obtainStyledAttributes.getColor( + R.styleable.verify_EditText_verify_textColor, + ContextCompat.getColor(context, R.color.black) + ) + var count = obtainStyledAttributes.getInt( + R.styleable.verify_EditText_verify_count, + DEFAULT_ITEM_COUNT + ) + val inputType = obtainStyledAttributes.getInt( + R.styleable.verify_EditText_verify_inputType, + InputType.TYPE_CLASS_NUMBER + ) + val passwordVisibleTime = obtainStyledAttributes.getInt( + R.styleable.verify_EditText_verify_password_visible_time, + DEFAULT_PASSWORD_VISIBLE_TIME + ) + val width = obtainStyledAttributes.getDimension( + R.styleable.verify_EditText_verify_width, + DEFAULT_ITEM_WIDTH.toFloat() + ) + .toInt() + val height = + obtainStyledAttributes.getDimension(R.styleable.verify_EditText_verify_height, 0f) + .toInt() + val margin = obtainStyledAttributes.getDimension( + R.styleable.verify_EditText_verify_margin, + DEFAULT_ITEM_MARGIN.toFloat() + ) + .toInt() + val textSize = px2sp( + context, + obtainStyledAttributes.getDimension( + R.styleable.verify_EditText_verify_textSize, + sp2px(context, DEFAULT_ITEM_TEXT_SIZE.toFloat()).toFloat() + ) + ).toFloat() + val password = + obtainStyledAttributes.getBoolean(R.styleable.verify_EditText_verify_password, false) + obtainStyledAttributes.recycle() + if (count < 2) count = 2 //最少 2 个 item + mEditText = EditText(context) + mEditText?.inputType = inputType + mEditText?.layoutParams = LayoutParams(1, 1) + mEditText?.isCursorVisible = false + mEditText?.background = null + mEditText?.filters = arrayOf(LengthFilter(count)) //限制输入长度为 count + mEditText?.addTextChangedListener(object : TextWatcher { + override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {} + override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) { + val textView = mTextViewList[start] //获取对应的 textview + if (before == 0) { //输入 + val input = s.subSequence(start, s.length) //获取新输入的字 + textView.text = input + if (password) { //如果需要密文显示 + textView.transformationMethod = + HideReturnsTransformationMethod.getInstance() + //passwordVisibleTime 毫秒后设置为密文显示 + textView.postDelayed( + { + textView.transformationMethod = + PasswordTransformationMethod.getInstance() + }, + passwordVisibleTime.toLong() + ) + } + setTextViewBackground(textView, drawableSelected) + } else { //删除 + textView.text = "" + setTextViewBackground(textView, drawableNormal) + } + mInputListener?.onChange(s.toString()) + if (mInputCompleteListener != null && s.length == mTextViewList.size) mInputCompleteListener?.onComplete( + s.toString() + ) + } + + override fun afterTextChanged(s: Editable) {} + }) + addView(mEditText) + //点击弹出软键盘 + setOnClickListener { + mEditText?.requestFocus() + showSoftKeyBoard() + } + //遍历生成 textview + for (i in 0 until count) { + val textView = TextView(context) + textView.textSize = textSize + textView.gravity = Gravity.CENTER + textView.setTextColor(textColor) + val layoutParams = LayoutParams( + width, + if (height == 0) ViewGroup.LayoutParams.WRAP_CONTENT else height + ) + if (i == 0) layoutParams.leftMargin = -1 else layoutParams.leftMargin = margin + textView.layoutParams = layoutParams + setTextViewBackground(textView, drawableNormal) + addView(textView) + mTextViewList.add(textView) + } + } +} diff --git a/app/src/main/java/com/gh/gamecenter/SplashScreenActivity.java b/app/src/main/java/com/gh/gamecenter/SplashScreenActivity.java index 42e5b3af50..75ade42c29 100644 --- a/app/src/main/java/com/gh/gamecenter/SplashScreenActivity.java +++ b/app/src/main/java/com/gh/gamecenter/SplashScreenActivity.java @@ -378,7 +378,7 @@ public class SplashScreenActivity extends BaseActivity { private void prefetchData() { AppExecutor.getIoExecutor().execute(() -> { - if (HaloApp.getInstance().isBrandNewInstall) getTeenagerModel(); + if (HaloApp.getInstance().isBrandNewInstall) getTeenagerMode(); Config.getGhzsSettings(); deviceDialogSetting(); getFilterDetailTags(); @@ -412,19 +412,19 @@ public class SplashScreenActivity extends BaseActivity { } @SuppressLint("CheckResult") - private void getTeenagerModel() { + private void getTeenagerMode() { RetrofitManager.getInstance(HaloApp.getInstance().getApplication()) - .getApi().getTeenagerModel(HaloApp.getInstance().getGid()) + .getApi().getTeenagerMode(HaloApp.getInstance().getGid()) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new BiResponse() { @Override public void onSuccess(ResponseBody data) { try { - boolean preStatus = SPUtils.getBoolean(Constants.SP_TEENAGER_MODEL); + boolean preStatus = SPUtils.getBoolean(Constants.SP_TEENAGER_MODE); JSONObject object = new JSONObject(data.string()); boolean curStatus = "open".equals(object.getString("status")); - SPUtils.setBoolean(Constants.SP_TEENAGER_MODEL, curStatus); + SPUtils.setBoolean(Constants.SP_TEENAGER_MODE, curStatus); if (preStatus != curStatus) { EventBus.getDefault().post(new EBTeenagerModelStatus()); } diff --git a/app/src/main/java/com/gh/gamecenter/adapter/viewholder/DetailViewHolder.java b/app/src/main/java/com/gh/gamecenter/adapter/viewholder/DetailViewHolder.java index 0685379e04..3d40cf1634 100644 --- a/app/src/main/java/com/gh/gamecenter/adapter/viewholder/DetailViewHolder.java +++ b/app/src/main/java/com/gh/gamecenter/adapter/viewholder/DetailViewHolder.java @@ -49,6 +49,7 @@ import com.gh.gamecenter.eventbus.EBReuse; import com.gh.gamecenter.eventbus.EBScroll; import com.gh.gamecenter.gamedetail.GameDetailFragment; import com.gh.gamecenter.gamedetail.dialog.GamePermissionDialogFragment; +import com.gh.gamecenter.teenagermode.TeenagerModeActivity; import com.lightgame.download.DownloadEntity; import com.lightgame.download.FileUtils; import com.lightgame.utils.Utils; @@ -341,8 +342,7 @@ public class DetailViewHolder { DialogHelper.showCenterDialog( mViewHolder.context, "提示", "当前处于儿童/青少年模式, \n暂不提供游戏下载", "退出青少年模式", "关闭", - () -> { - }, + () -> mViewHolder.context.startActivity(TeenagerModeActivity.getIntent(mViewHolder.context)), () -> { } ); diff --git a/app/src/main/java/com/gh/gamecenter/fragment/SearchToolbarFragment.java b/app/src/main/java/com/gh/gamecenter/fragment/SearchToolbarFragment.java index df688b82b5..a7bc460c20 100644 --- a/app/src/main/java/com/gh/gamecenter/fragment/SearchToolbarFragment.java +++ b/app/src/main/java/com/gh/gamecenter/fragment/SearchToolbarFragment.java @@ -252,7 +252,7 @@ public class SearchToolbarFragment extends BaseLazyFragment implements View.OnCl mDownloadView.setVisibility(View.INVISIBLE); } - if (SPUtils.getBoolean(Constants.SP_TEENAGER_MODEL)) { + if (SPUtils.getBoolean(Constants.SP_TEENAGER_MODE)) { mTeenagerModelView.setVisibility(View.VISIBLE); mSearchContainerView.setVisibility(View.GONE); mSearchRightView.setVisibility(View.VISIBLE); diff --git a/app/src/main/java/com/gh/gamecenter/personal/PersonalFunctionAdapter.kt b/app/src/main/java/com/gh/gamecenter/personal/PersonalFunctionAdapter.kt index 8386b6e1f6..c322d14e6c 100644 --- a/app/src/main/java/com/gh/gamecenter/personal/PersonalFunctionAdapter.kt +++ b/app/src/main/java/com/gh/gamecenter/personal/PersonalFunctionAdapter.kt @@ -26,6 +26,7 @@ import com.gh.gamecenter.mygame.MyGameActivity import com.gh.gamecenter.qa.myqa.MyAskActivity import com.gh.gamecenter.security.SecurityActivity import com.gh.gamecenter.simulatorgame.SimulatorGameActivity +import com.gh.gamecenter.teenagermode.TeenagerModeActivity import com.gh.gamecenter.user.UserViewModel import com.gh.gamecenter.video.videomanager.VideoManagerActivity import com.halo.assistant.HaloApp @@ -289,6 +290,7 @@ class PersonalFunctionAdapter(val context: Context, val groupName: String, var m } } "青少年模式" -> { + context.startActivity(TeenagerModeActivity.getIntent(context)) } else -> { DirectUtils.directToLinkPage(context, linkEntity, "", "我的光环") diff --git a/app/src/main/java/com/gh/gamecenter/retrofit/service/ApiService.java b/app/src/main/java/com/gh/gamecenter/retrofit/service/ApiService.java index ab29dd9739..eba7788d80 100644 --- a/app/src/main/java/com/gh/gamecenter/retrofit/service/ApiService.java +++ b/app/src/main/java/com/gh/gamecenter/retrofit/service/ApiService.java @@ -3227,5 +3227,29 @@ public interface ApiService { * 获取青少年模式状态 */ @GET("api_go/teen_mode/status") - Single getTeenagerModel(@Query("android_id") String gid); + Single getTeenagerMode(@Query("android_id") String gid); + + /** + * 青少年模式加锁 + */ + @POST("api_go/teen_mode/lock") + Single postTeenModeLock(@Body RequestBody body); + + /** + * 青少年模式解锁 + */ + @POST("api_go/teen_mode/unlock") + Single postTeenModeUnlock(@Body RequestBody body); + + /** + * 退出青少年模式 + */ + @POST("api_go/teen_mode/logout") + Single postTeenModeLogout(@Body RequestBody body); + + /** + * 修改青少年模式密码 + */ + @PUT("api_go/teen_mode/password") + Single putTeenModePassword(@Body RequestBody body); } \ No newline at end of file diff --git a/app/src/main/java/com/gh/gamecenter/search/SearchGameIndexAdapter.kt b/app/src/main/java/com/gh/gamecenter/search/SearchGameIndexAdapter.kt index c9c1192fa8..40bc10f496 100644 --- a/app/src/main/java/com/gh/gamecenter/search/SearchGameIndexAdapter.kt +++ b/app/src/main/java/com/gh/gamecenter/search/SearchGameIndexAdapter.kt @@ -287,7 +287,7 @@ class SearchGameIndexAdapter(context: Context, } - if (SPUtils.getBoolean(Constants.SP_TEENAGER_MODEL)) { + if (SPUtils.getBoolean(Constants.SP_TEENAGER_MODE)) { binding.gameItemIncluded.downloadBtn.visibility = View.GONE } else { binding.gameItemIncluded.downloadBtn.visibility = View.VISIBLE diff --git a/app/src/main/java/com/gh/gamecenter/search/SearchGameResultAdapter.kt b/app/src/main/java/com/gh/gamecenter/search/SearchGameResultAdapter.kt index 0c40eba0fa..5c7c691018 100644 --- a/app/src/main/java/com/gh/gamecenter/search/SearchGameResultAdapter.kt +++ b/app/src/main/java/com/gh/gamecenter/search/SearchGameResultAdapter.kt @@ -347,7 +347,7 @@ class SearchGameResultAdapter(context: Context, } - if (SPUtils.getBoolean(Constants.SP_TEENAGER_MODEL)) { + if (SPUtils.getBoolean(Constants.SP_TEENAGER_MODE)) { binding.gameItemIncluded.downloadBtn.visibility = View.GONE } else { binding.gameItemIncluded.downloadBtn.visibility = View.VISIBLE diff --git a/app/src/main/java/com/gh/gamecenter/teenagermode/PasswordSettingFragment.kt b/app/src/main/java/com/gh/gamecenter/teenagermode/PasswordSettingFragment.kt new file mode 100644 index 0000000000..df4e43b63a --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/teenagermode/PasswordSettingFragment.kt @@ -0,0 +1,200 @@ +package com.gh.gamecenter.teenagermode + +import android.os.Bundle +import android.view.View +import androidx.lifecycle.ViewModelProvider +import com.gh.common.constant.Constants +import com.gh.common.util.SPUtils +import com.gh.common.util.isPublishEnv +import com.gh.common.util.toColor +import com.gh.common.view.VerifyEditText +import com.gh.gamecenter.GameDetailActivity +import com.gh.gamecenter.MainActivity +import com.gh.gamecenter.R +import com.gh.gamecenter.WebActivity +import com.gh.gamecenter.databinding.FragmentPasswordSettingBinding +import com.gh.gamecenter.normal.NormalFragment +import com.lightgame.utils.AppManager + +class PasswordSettingFragment : NormalFragment() { + + private var mBinding: FragmentPasswordSettingBinding? = null + private var mViewModel: TeenagerModeViewModel? = null + + private var mPassword = "" + private var mLastPassword = "" + + override fun getLayoutId(): Int = 0 + + override fun getInflatedLayout() = + FragmentPasswordSettingBinding.inflate(layoutInflater).apply { mBinding = this }.root + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + mViewModel = ViewModelProvider(this).get(TeenagerModeViewModel::class.java) + mBinding?.resetPwdTv?.setOnClickListener { + val url = if (isPublishEnv()) { + Constants.TEEN_MODE_RESET_PASSWORD + } else { + Constants.TEEN_MODE_RESET_PASSWORD_DEV + } + startActivity(WebActivity.getWebIntent(requireContext(), "找回密码", url)) + } + when (requireArguments().getString(TeenagerModeActivity.TYPE)) { + TeenagerModeActivity.TYPE_ENABLE -> showEnable() + TeenagerModeActivity.TYPE_DISABLE -> showDisable() + TeenagerModeActivity.TYPE_CHANGE_PWD -> showChangePwd() + } + } + + private fun showEnable() { + mBinding?.titleTv?.text = "设置密码" + mBinding?.hintTv?.text = "启动儿童/青少年模式,需要先设置独立密码" + mBinding?.resetPwdTv?.visibility = View.GONE + mBinding?.verifyEt?.run { + requestFocus() + addInputListener(object : VerifyEditText.InputListener { + override fun onChange(content: String) { + mBinding?.nextTv?.alpha = if (content.length < 4) 0.4F else 1F + if (content.length < 4) mBinding?.nextTv?.setOnClickListener(null) + } + }) + addInputCompleteListener(object : VerifyEditText.InputCompleteListener { + override fun onComplete(content: String) { + mBinding?.nextTv?.alpha = 1F + mBinding?.nextTv?.setOnClickListener { + mPassword = content + clearContent() + mBinding?.titleTv?.text = "确认密码" + mBinding?.hintTv?.text = "再次输入密码" + mBinding?.nextTv?.alpha = 0.4F + it.setOnClickListener(null) + addInputCompleteListener(object : VerifyEditText.InputCompleteListener { + override fun onComplete(content: String) { + mBinding?.nextTv?.alpha = 1F + it.setOnClickListener { + if (content == mPassword) { + mViewModel?.postTeenModeLock(mPassword) { + SPUtils.setBoolean(Constants.SP_TEENAGER_MODE, true) + toast("儿童/青少年模式已开启") + directToSplash() + } + } else { + mBinding?.hintTv?.text = "与第一次输入的密码不一致" + mBinding?.hintTv?.setTextColor(R.color.theme_red.toColor()) + clearContent() + } + } + } + }) + } + } + }) + } + } + + private fun showDisable() { + mBinding?.titleTv?.text = "关闭儿童/青少年模式" + mBinding?.hintTv?.text = "请输入密码确认" + mBinding?.resetPwdTv?.visibility = View.VISIBLE + mBinding?.verifyEt?.run { + requestFocus() + addInputListener(object : VerifyEditText.InputListener { + override fun onChange(content: String) { + mBinding?.nextTv?.alpha = if (content.length < 4) 0.4F else 1F + if (content.length < 4) mBinding?.nextTv?.setOnClickListener(null) + } + }) + addInputCompleteListener(object : VerifyEditText.InputCompleteListener { + override fun onComplete(content: String) { + mBinding?.nextTv?.alpha = 1F + mBinding?.nextTv?.setOnClickListener { + mViewModel?.postTeenModeLogout(content, { + SPUtils.setBoolean(Constants.SP_TEENAGER_MODE, false) + toast("儿童/青少年模式已关闭") + directToSplash() + }, { + clearContent() + mBinding?.hintTv?.text = "密码错误请重新输入" + mBinding?.hintTv?.setTextColor(R.color.theme_red.toColor()) + }) + } + } + }) + } + } + + private fun showChangePwd() { + mBinding?.titleTv?.text = "修改密码" + mBinding?.hintTv?.text = "请输入当前密码" + mBinding?.resetPwdTv?.visibility = View.VISIBLE + mBinding?.verifyEt?.run { + requestFocus() + addInputListener(object : VerifyEditText.InputListener { + override fun onChange(content: String) { + mBinding?.nextTv?.alpha = if (content.length < 4) 0.4F else 1F + if (content.length < 4) mBinding?.nextTv?.setOnClickListener(null) + } + }) + addInputCompleteListener(object : VerifyEditText.InputCompleteListener { + override fun onComplete(content: String) { + mBinding?.nextTv?.alpha = 1F + mBinding?.nextTv?.setOnClickListener { + mViewModel?.postTeenModeUnlock(content, { + mLastPassword = content + clearContent() + mBinding?.titleTv?.text = "请输入新密码" + mBinding?.hintTv?.text = "设置新的独立密码" + mBinding?.hintTv?.setTextColor(R.color.text_subtitle.toColor()) + addInputCompleteListener(object : VerifyEditText.InputCompleteListener { + override fun onComplete(content: String) { + mBinding?.nextTv?.alpha = 1F + mBinding?.nextTv?.setOnClickListener { + mPassword = content + clearContent() + mBinding?.titleTv?.text = "确认密码" + mBinding?.hintTv?.text = "再次输入密码" + mBinding?.nextTv?.alpha = 0.4F + it.setOnClickListener(null) + addInputCompleteListener(object : VerifyEditText.InputCompleteListener { + override fun onComplete(content: String) { + mBinding?.nextTv?.alpha = 1F + it.setOnClickListener { + if (content == mPassword) { + mViewModel?.putTeenModePwd(mLastPassword, mPassword, { + toast("设置成功") + requireActivity().onBackPressed() + }, { + toast("网络异常") + }) + } else { + mBinding?.hintTv?.text = "与第一次输入的密码不一致" + mBinding?.hintTv?.setTextColor(R.color.theme_red.toColor()) + clearContent() + } + } + } + }) + } + } + }) + }, { + clearContent() + mBinding?.hintTv?.text = "密码错误请重新输入" + mBinding?.hintTv?.setTextColor(R.color.theme_red.toColor()) + }) + } + } + }) + } + } + + private fun directToSplash() { + AppManager.getInstance().finishActivity(AppManager.getInstance().findActivity(MainActivity::class.java)) + AppManager.getInstance().finishActivity(AppManager.getInstance().findActivity(GameDetailActivity::class.java)) + startActivity(MainActivity.getMainIntent(requireActivity()).apply { + putExtra(MainActivity.SHOW_AD, true) + }) + requireActivity().finish() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/gh/gamecenter/teenagermode/TeenagerModeActivity.kt b/app/src/main/java/com/gh/gamecenter/teenagermode/TeenagerModeActivity.kt new file mode 100644 index 0000000000..3984ca9be7 --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/teenagermode/TeenagerModeActivity.kt @@ -0,0 +1,37 @@ +package com.gh.gamecenter.teenagermode + +import android.content.Context +import android.content.Intent +import android.os.Bundle +import androidx.fragment.app.Fragment +import com.gh.base.BaseActivity +import com.gh.gamecenter.R + +class TeenagerModeActivity : BaseActivity() { + + private var mContainerFragment: Fragment? = null + + override fun getLayoutId() = R.layout.activity_amway + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + mContainerFragment = supportFragmentManager.findFragmentByTag(TeenagerModeFragment::class.java.simpleName) + ?: TeenagerModeFragment().with(intent.extras) + supportFragmentManager.beginTransaction().replace(R.id.placeholder, mContainerFragment!!, TeenagerModeFragment::class.java.simpleName).commitAllowingStateLoss() + } + + override fun preventRecreateFragmentByFragmentManager(): Boolean = true + + companion object { + + const val TYPE = "type" + const val TYPE_ENABLE = "enable" + const val TYPE_DISABLE = "disable" + const val TYPE_CHANGE_PWD = "change_pwd" + + @JvmStatic + fun getIntent(context: Context): Intent { + return Intent(context, TeenagerModeActivity::class.java) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/gh/gamecenter/teenagermode/TeenagerModeFragment.kt b/app/src/main/java/com/gh/gamecenter/teenagermode/TeenagerModeFragment.kt new file mode 100644 index 0000000000..39aa8a4bed --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/teenagermode/TeenagerModeFragment.kt @@ -0,0 +1,82 @@ +package com.gh.gamecenter.teenagermode + +import android.os.Bundle +import android.view.View +import androidx.constraintlayout.widget.ConstraintLayout +import com.gh.common.constant.Constants +import com.gh.common.util.SPUtils +import com.gh.common.util.SpanBuilder +import com.gh.common.util.dip2px +import com.gh.common.util.isPublishEnv +import com.gh.common.view.CustomLinkMovementMethod +import com.gh.gamecenter.R +import com.gh.gamecenter.WebActivity +import com.gh.gamecenter.databinding.FragmentTeenagerModeBinding +import com.gh.gamecenter.normal.NormalFragment + +class TeenagerModeFragment : NormalFragment() { + + private var mBinding: FragmentTeenagerModeBinding? = null + + override fun getLayoutId(): Int = 0 + + override fun getInflatedLayout() = FragmentTeenagerModeBinding.inflate(layoutInflater).apply { mBinding = this }.root + + override fun onResume() { + super.onResume() + val bundle = Bundle() + if (SPUtils.getBoolean(Constants.SP_TEENAGER_MODE, false)) { + bundle.putString(TeenagerModeActivity.TYPE, TeenagerModeActivity.TYPE_DISABLE) + showDisable() + } else { + bundle.putString(TeenagerModeActivity.TYPE, TeenagerModeActivity.TYPE_ENABLE) + showEnable() + } + mBinding?.switchTv?.setOnClickListener { + val mContainerFragment = requireActivity().supportFragmentManager.findFragmentByTag(PasswordSettingFragment::class.java.simpleName) + ?: PasswordSettingFragment().with(bundle) + requireActivity().supportFragmentManager.beginTransaction().run { + addToBackStack(null) + add(R.id.placeholder, mContainerFragment!!, PasswordSettingFragment::class.java.simpleName).commitAllowingStateLoss() + } + } + } + + private fun showEnable() { + mBinding?.hintTv?.visibility = View.VISIBLE + mBinding?.changePwdTv?.visibility = View.GONE + mBinding?.titleTv?.text = "儿童/青少年模式" + mBinding?.switchTv?.text = "开启儿童/青少年模式" + val clickText = "《儿童/青少年使用须知》" + val hintText = "更多信息可阅读 $clickText" + mBinding?.hintTv?.text = SpanBuilder(hintText).click( + hintText.length - clickText.length, hintText.length, + R.color.theme_font, false + ) { + val url = if (isPublishEnv()) { + Constants.TEEN_MODE_RULE + } else { + Constants.TEEN_MODE_RULE_DEV + } + startActivity(WebActivity.getWebIntent(requireContext(), "儿童/青少年使用须知", url)) + }.build() + mBinding?.hintTv?.movementMethod = CustomLinkMovementMethod.getInstance() + } + + private fun showDisable() { + mBinding?.hintTv?.visibility = View.GONE + mBinding?.changePwdTv?.visibility = View.VISIBLE + mBinding?.titleTv?.text = "儿童/青少年模式已开启" + mBinding?.switchTv?.text = "关闭儿童/青少年模式" + mBinding?.switchTv?.layoutParams = (mBinding?.switchTv?.layoutParams as ConstraintLayout.LayoutParams).apply { setMargins(0, 0, 0, 68F.dip2px()) } + mBinding?.changePwdTv?.setOnClickListener { + val bundle = Bundle().apply { putString(TeenagerModeActivity.TYPE, TeenagerModeActivity.TYPE_CHANGE_PWD) } + val mContainerFragment = requireActivity().supportFragmentManager.findFragmentByTag(PasswordSettingFragment::class.java.simpleName) + ?: PasswordSettingFragment().with(bundle) + requireActivity().supportFragmentManager.beginTransaction().run { + addToBackStack(null) + add(R.id.placeholder, mContainerFragment!!, PasswordSettingFragment::class.java.simpleName).commitAllowingStateLoss() + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/gh/gamecenter/teenagermode/TeenagerModeViewModel.kt b/app/src/main/java/com/gh/gamecenter/teenagermode/TeenagerModeViewModel.kt new file mode 100644 index 0000000000..2a2ab09540 --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/teenagermode/TeenagerModeViewModel.kt @@ -0,0 +1,97 @@ +package com.gh.gamecenter.teenagermode + +import android.annotation.SuppressLint +import android.app.Application +import androidx.lifecycle.AndroidViewModel +import com.gh.common.util.createRequestBody +import com.gh.gamecenter.retrofit.BiResponse +import com.gh.gamecenter.retrofit.RetrofitManager +import com.halo.assistant.HaloApp +import io.reactivex.android.schedulers.AndroidSchedulers +import io.reactivex.schedulers.Schedulers +import okhttp3.ResponseBody + +class TeenagerModeViewModel(application: Application) : AndroidViewModel(application) { + + @SuppressLint("CheckResult") + fun postTeenModeLock(pwd: String, successCb: () -> Unit) { + val body = hashMapOf( + Pair("android_id", HaloApp.getInstance().gid), + Pair("password", pwd), + Pair("password_again", pwd) + ).createRequestBody() + RetrofitManager.getInstance(getApplication()).api.postTeenModeLock(body) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(object : BiResponse() { + override fun onSuccess(data: ResponseBody) { + successCb.invoke() + } + }) + } + + @SuppressLint("CheckResult") + fun postTeenModeUnlock(pwd: String, successCb: () -> Unit, failureCb: () -> Unit) { + val body = hashMapOf( + Pair("android_id", HaloApp.getInstance().gid), + Pair("password", pwd) + ).createRequestBody() + RetrofitManager.getInstance(getApplication()).api.postTeenModeUnlock(body) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(object : BiResponse() { + override fun onSuccess(data: ResponseBody) { + successCb.invoke() + } + + override fun onFailure(exception: Exception) { + super.onFailure(exception) + failureCb.invoke() + } + }) + } + + @SuppressLint("CheckResult") + fun postTeenModeLogout(pwd: String, successCb: () -> Unit, failureCb: () -> Unit) { + val body = hashMapOf( + Pair("android_id", HaloApp.getInstance().gid), + Pair("password", pwd) + ).createRequestBody() + RetrofitManager.getInstance(getApplication()).api.postTeenModeLogout(body) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(object : BiResponse() { + override fun onSuccess(data: ResponseBody) { + successCb.invoke() + } + + override fun onFailure(exception: Exception) { + super.onFailure(exception) + failureCb.invoke() + } + }) + } + + @SuppressLint("CheckResult") + fun putTeenModePwd(pwd: String, newPwd: String, successCb: () -> Unit, failureCb: () -> Unit) { + val body = hashMapOf( + Pair("last_password", pwd), + Pair("android_id", HaloApp.getInstance().gid), + Pair("password", newPwd), + Pair("password_again", newPwd) + ).createRequestBody() + RetrofitManager.getInstance(getApplication()).api.putTeenModePassword(body) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(object : BiResponse() { + override fun onSuccess(data: ResponseBody) { + successCb.invoke() + } + + override fun onFailure(exception: Exception) { + super.onFailure(exception) + failureCb.invoke() + } + }) + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable-xxxhdpi/teenager_mode_logo.webp b/app/src/main/res/drawable-xxxhdpi/teenager_mode_logo.webp new file mode 100644 index 0000000000..2f5116ba76 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/teenager_mode_logo.webp differ diff --git a/app/src/main/res/drawable/bg_verify_password.xml b/app/src/main/res/drawable/bg_verify_password.xml new file mode 100644 index 0000000000..03a0f28e6d --- /dev/null +++ b/app/src/main/res/drawable/bg_verify_password.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_password_setting.xml b/app/src/main/res/layout/fragment_password_setting.xml new file mode 100644 index 0000000000..a94392cbd6 --- /dev/null +++ b/app/src/main/res/layout/fragment_password_setting.xml @@ -0,0 +1,91 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_teenager_mode.xml b/app/src/main/res/layout/fragment_teenager_mode.xml new file mode 100644 index 0000000000..b1a1c47f21 --- /dev/null +++ b/app/src/main/res/layout/fragment_teenager_mode.xml @@ -0,0 +1,97 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/attrs.xml b/app/src/main/res/values/attrs.xml index cbded751b4..f705539dba 100644 --- a/app/src/main/res/values/attrs.xml +++ b/app/src/main/res/values/attrs.xml @@ -166,4 +166,62 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index a9fa252241..6e1403884e 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -863,4 +863,5 @@ 该游戏暂时仅提供试玩版本。试玩版资源来自第三方网站,可能存在bug或兼容性问题。敬请留意后续相关消息。 该游戏暂时仅提供试玩版本。试玩版可能存在bug或兼容性问题。敬请留意后续相关消息。 游戏停服更新维护中,为避免情绪化内容对游戏评分带来的影响,因此开启停服保护功能。在停服保护状态期间,所新增及修改发布的评分将不计入总分,所评分评论内容在展示上也会有文字提示告知其他玩家。\n\n感谢您的配合及谅解,祝您游戏愉快!\n\n光环助手会持续关注产品建议及反馈,如您在使用过程中有任何问题,欢迎向我们反馈。 + 开启青少年模式后,系统将自动关闭所有游戏的下载功能,需要输入密码才能恢复使用\n\n开启青少年模式,需要先设置独立密码,如忘记密码可联系客服申述重置\n\n青少年模式是光环助手响应国家政策,为促进青少年健康成长的一种模式,我们优先针对核心场景进行优化,也将继续致力于优化更多场景 diff --git a/dependencies.gradle b/dependencies.gradle index 1a9c4d661a..f1ae6959f7 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -52,8 +52,7 @@ ext { switchButton = "1.4.5" swipeLayout = "1.2.0@aar" autoScrollViewPager = "1.1.2" - weiboSDK = "2.0.3:openDefaultRelease@aar" - + weiboSDK = "11.6.0@aar" apkChannelPackage = "1.0.5" //Test