Compare commits

..

1 Commits

151 changed files with 280 additions and 6044 deletions

View File

@ -72,8 +72,6 @@ android_build:
only:
- dev
- release
- feat/GHZSCY-6976
- feat/GHZSCY-6976-log
# 代码检查
sonarqube_analysis:
@ -105,8 +103,6 @@ sonarqube_analysis:
only:
- dev
- release
- feat/GHZSCY-6976
- feat/GHZSCY-6976-log
## 发送简易检测结果报告
send_sonar_report:
@ -125,8 +121,6 @@ send_sonar_report:
only:
- dev
- release
- feat/GHZSCY-6976
- feat/GHZSCY-6976-log
oss-upload&send-email:
tags:
@ -163,5 +157,3 @@ oss-upload&send-email:
only:
- dev
- release
- feat/GHZSCY-6976
- feat/GHZSCY-6976-log

View File

@ -402,7 +402,7 @@ dependencies {
exclude module: "gsyvideoplayer-androidvideocache"
exclude group: "tv.danmaku.ijk.media"
})
implementation("com.github.CarGuo.GSYVideoPlayer:gsyVideoPlayer-exo_player2:$gsyVideo") {
implementation ("com.github.CarGuo.GSYVideoPlayer:gsyVideoPlayer-exo_player2:$gsyVideo") {
exclude group: 'com.google.android.exoplayer', module: 'extension-rtmp'
}
@ -526,18 +526,6 @@ dependencies {
debugImplementation 'com.bytedance.android:shadowhook:1.0.9'
debugImplementation 'io.github.shiqos:wytrace:1.0.1'
if (!gradle.ext.excludeOptionalModules || gradle.ext.enableAccelerator) {
implementation(project(":feature:accelerator"))
}
if (!gradle.ext.excludeOptionalModules || gradle.ext.enableAliPay) {
implementation(project(":feature:ali_pay"))
}
if(!gradle.ext.excludeOptionalModules || gradle.ext.enableWechatPay){
implementation(project(":feature:wechat_pay"))
}
}
File propFile = file('sign.properties')

View File

@ -10,9 +10,9 @@
<queries>
<package android:name="com.gh.toolmap" />
<intent>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="ghtoolmap" />
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.BROWSABLE"/>
<data android:scheme="ghtoolmap"/>
</intent>
</queries>
@ -197,9 +197,7 @@
android:name="io.sentry.breadcrumbs.system-events"
android:value="false" />
<meta-data
android:name="module_version"
android:value="${VA_VERSION_NAME}" />
<meta-data android:name="module_version" android:value="${VA_VERSION_NAME}" />
<service android:name="com.gh.ndownload.NDownloadService" />
@ -816,14 +814,6 @@
android:name=".video.poster.PosterEditActivity"
android:screenOrientation="portrait" />
<activity
android:name="com.halo.assistant.member.MemberActivity"
android:screenOrientation="portrait" />
<activity
android:name=".BatchRegisterActivity"
android:screenOrientation="portrait" />
<!-- <activity-->
<!-- android:name="${applicationId}.douyinapi.DouYinEntryActivity"-->
<!-- android:launchMode="singleTask"-->

View File

@ -4,7 +4,6 @@ import android.annotation.SuppressLint
import android.app.Activity
import android.content.Context
import android.content.SharedPreferences
import android.graphics.drawable.Animatable
import android.os.Message
import android.text.TextUtils
import android.view.View
@ -14,13 +13,11 @@ import android.widget.TextView
import androidx.appcompat.content.res.AppCompatResources
import androidx.fragment.app.Fragment
import com.therouter.TheRouter
import com.facebook.drawee.controller.BaseControllerListener
import com.facebook.drawee.view.SimpleDraweeView
import com.facebook.imagepipeline.image.ImageInfo
import com.gh.common.exposure.ExposureManager
import com.gh.common.util.DirectUtils.directToLinkPage
import com.gh.common.util.LogUtils
import com.gh.common.util.NewFlatLogUtils
import com.gh.common.util.NewFlatLogUtils.logOpenScreenAdSkip
import com.gh.common.util.PackageUtils
import com.gh.gamecenter.BuildConfig
import com.gh.gamecenter.MainActivity
@ -62,8 +59,6 @@ object AdDelegateHelper {
private val mGameSearchAdList: ArrayList<AdConfig> by lazy { arrayListOf() }
private var mVGameLaunchAd: AdConfig? = null
private var ownerSplashAdLoadTime = 0L
val vGameLaunchAd: AdConfig?
get() = mVGameLaunchAd
@ -81,7 +76,6 @@ object AdDelegateHelper {
}
var isShowingSplashAd = false // 是否正在显示开屏广告
var isOwnerSplashAdShown = false // 自有开屏广告是否展示
var gameSearchKeyword = ""
fun initAdSdk(context: Context) {
@ -308,7 +302,6 @@ object AdDelegateHelper {
) {
val hideCallback = {
isShowingSplashAd = false
isOwnerSplashAdShown = false
hideAction.invoke()
}
if (mSplashAd != null) {
@ -581,8 +574,6 @@ object AdDelegateHelper {
handler: BaseActivity.BaseHandler,
hideCallback: () -> Unit
) {
isOwnerSplashAdShown = false
val jumpBtn = startAdContainer.findViewById<TextView>(R.id.jumpBtn)
val jumpDetailBtn: TextView = startAdContainer.findViewById(R.id.jumpDetailBtn)
val adImage: SimpleDraweeView = startAdContainer.findViewById(R.id.adImage)
@ -601,62 +592,38 @@ object AdDelegateHelper {
)
adImage.visibleIf(true)
ImageUtils.displayWithCallback(adImage, ad.img, true, object : BaseControllerListener<ImageInfo>() {
override fun onSubmit(id: String?, callerContext: Any?) {
super.onSubmit(id, callerContext)
adImage.post {
ownerSplashAdLoadTime = System.currentTimeMillis()
NewFlatLogUtils.logSplashAdLoad(ad.id)
}
}
override fun onFinalImageSet(id: String?, imageInfo: ImageInfo?, animatable: Animatable?) {
isOwnerSplashAdShown = true
adImage.post {
NewFlatLogUtils.logSplashAdShow(ad.id, System.currentTimeMillis() - ownerSplashAdLoadTime)
}
}
override fun onFailure(id: String?, throwable: Throwable?) {
super.onFailure(id, throwable)
NewFlatLogUtils.logSplashAdFail(ad.id, "启动广告图加载失败")
}
})
ImageUtils.display(adImage, ad.img)
if (ad.isImageType) {
adVideo.visibleIf(false)
} else {
adVideo.visibleIf(true)
adVideo.startPlay(ad.video.url)
}
startAdContainer.setOnClickListener {
// 拦截点击事件传递
}
jumpBtn.setOnClickListener {
it.debounceActionWithInterval(1000L) {
if (!isOwnerSplashAdShown) {
NewFlatLogUtils.logSplashAdFail(ad.id, "加载过程中点击跳过广告")
}
handler.removeMessages(MainActivity.COUNTDOWN_AD)
hideCallback.invoke()
val linkEntity = ad.jump
NewFlatLogUtils.logOpenScreenAdSkip(
ad.id,
(if (linkEntity.text != null) linkEntity.text else "")!!,
(if (linkEntity.type != null) linkEntity.type else "")!!,
(if (linkEntity.link != null) linkEntity.link else "")!!
)
SensorsBridge.trackEvent(
"SplashAdOwnSkip",
"splash_ad_id",
ad.id,
"link_type",
linkEntity.type ?: "",
"link_id",
linkEntity.link ?: "",
"link_text",
linkEntity.text ?: ""
)
}
handler.removeMessages(MainActivity.COUNTDOWN_AD)
hideCallback.invoke()
val linkEntity = ad.jump
logOpenScreenAdSkip(
ad.id,
(if (linkEntity.text != null) linkEntity.text else "")!!,
(if (linkEntity.type != null) linkEntity.type else "")!!,
(if (linkEntity.link != null) linkEntity.link else "")!!
)
SensorsBridge.trackEvent(
"SplashAdOwnSkip",
"splash_ad_id",
ad.id,
"link_type",
linkEntity.type ?: "",
"link_id",
linkEntity.link ?: "",
"link_text",
linkEntity.text ?: ""
)
}
val sources: MutableList<ExposureSource> = ArrayList()
sources.add(ExposureSource("开屏广告", ad.id))

View File

@ -48,12 +48,6 @@ class SplashAdVideoView @JvmOverloads constructor(
// no nothing
}
override fun onPrepared() {
super.onPrepared()
visibility = VISIBLE
}
override fun onAutoCompletion() {
setStateAndUi(CURRENT_STATE_AUTO_COMPLETE);

View File

@ -22,8 +22,7 @@ import com.gh.gamecenter.ImageViewerActivity
import com.gh.gamecenter.WebActivity
import com.gh.gamecenter.common.callback.BiCallback
import com.gh.gamecenter.common.constant.Constants
import com.gh.gamecenter.common.constant.Constants.SP_MEMBER_PAYMENT_BUTTON_CLICK
import com.gh.gamecenter.common.constant.Constants.SP_MEMBER_RECHARGE_BUTTON_CLICK
import com.gh.gamecenter.common.constant.RouteConsts
import com.gh.gamecenter.common.entity.NotificationUgc
import com.gh.gamecenter.common.exposure.ExposureSource
import com.gh.gamecenter.common.loghub.LoghubUtils
@ -31,23 +30,20 @@ import com.gh.gamecenter.common.provider.IHelpAndFeedbackProvider
import com.gh.gamecenter.common.tracker.Tracker
import com.gh.gamecenter.common.utils.*
import com.gh.gamecenter.common.utils.NewFlatLogUtils
import com.gh.gamecenter.common.utils.SensorsBridge.EVENT_MEMBER_RECHARGE_BUTTON_CLICK
import com.gh.gamecenter.common.utils.SensorsBridge.EVENT_NAME
import com.gh.gamecenter.common.utils.SensorsBridge.KEY_IS_FIRST_TIME
import com.gh.gamecenter.common.view.dsbridge.CompletionHandler
import com.gh.gamecenter.core.AppExecutor
import com.gh.gamecenter.core.provider.IAcceleratorProvider
import com.gh.gamecenter.core.provider.IPushProvider
import com.gh.gamecenter.core.runOnIoThread
import com.gh.gamecenter.core.runOnUiThread
import com.gh.gamecenter.core.utils.*
import com.gh.gamecenter.core.utils.CurrentActivityHolder
import com.gh.gamecenter.core.utils.DisplayUtils
import com.gh.gamecenter.core.utils.SPUtils
import com.gh.gamecenter.core.utils.ToastUtils
import com.gh.gamecenter.entity.SensorsEvent
import com.gh.gamecenter.eventbus.EBDownloadStatus
import com.gh.gamecenter.eventbus.EBPackage
import com.gh.gamecenter.feature.entity.AcctRecordEntity
import com.gh.gamecenter.feature.entity.Badge
import com.gh.gamecenter.feature.entity.GameEntity
import com.gh.gamecenter.feature.entity.OrderEntity
import com.gh.gamecenter.feature.exposure.ExposureEvent
import com.gh.gamecenter.login.user.LoginTag
import com.gh.gamecenter.login.user.UserManager
@ -59,9 +55,6 @@ import com.gh.gamecenter.personalhome.border.AvatarBorderActivity
import com.gh.gamecenter.setting.SettingBridge
import com.gh.vspace.VHelper
import com.halo.assistant.HaloApp
import com.halo.assistant.member.MemberRepository
import com.halo.assistant.member.MemberRepository.Companion.PAYMENT_TYPE_ALIPAY
import com.halo.assistant.member.MemberRepository.Companion.PAYMENT_TYPE_WECHAT
import com.lightgame.download.DataWatcher
import com.lightgame.download.DownloadEntity
import com.lightgame.download.DownloadStatus.*
@ -82,7 +75,6 @@ class DefaultJsApi(
private var mBbsId: String? = "",
private var mOriginUrl: String? = "",
private val mForumName: String? = "",
private val listener: OnWebClickListener? = null
) {
companion object {
@ -707,84 +699,6 @@ class DefaultJsApi(
}
}
@JavascriptInterface
fun preOrderWithAli(json: Any) {
val order = json.toString().toObject<OrderEntity>() ?: return
trackMemberPaymentButtonClick(order, PAYMENT_TYPE_ALIPAY)
listener?.onPreOrderWithAli(order)
}
@JavascriptInterface
fun preOrderWithWechat(json: Any) {
val order = json.toString().toObject<OrderEntity>() ?: return
trackMemberPaymentButtonClick(order, PAYMENT_TYPE_WECHAT)
listener?.onPreOrderWithWechat(order)
}
private fun trackMemberPaymentButtonClick(order: OrderEntity, paymentType: String) {
val isFirstTime = SPUtils.getBoolean(SP_MEMBER_PAYMENT_BUTTON_CLICK, true)
SPUtils.setBoolean(SP_MEMBER_PAYMENT_BUTTON_CLICK, false)
SensorsBridge.trackMemberPaymentButtonClick(
isFirstTime,
paymentType,
order.setMenuName,
order.paymentAmount
)
}
@JavascriptInterface
fun startGameAccelerate(acctJson: Any) {
if (acctJson is String) {
val acctRecord = GsonUtils.fromJson(acctJson, AcctRecordEntity::class.java)
val accInfo = acctRecord.accInfo
listener?.onStartGameAccelerate(accInfo)
}
}
@JavascriptInterface
fun getCurAcctGameId(): String {
val isSpeeding = TheRouter.get(IAcceleratorProvider::class.java)?.isCurAccSuccess() ?: false
val gameId = if (isSpeeding) {
MemberRepository.instance.acctGameRecord.gameId
} else {
""
}
return gameId
}
@JavascriptInterface
fun stopGameAccelerate() {
listener?.onStopGameAccelerate()
}
@JavascriptInterface
fun refreshToken(token: Any, handler: CompletionHandler<Any>) {
val accessToken = token.toString()
UserManager.getInstance().refreshToken(accessToken, object : UserManager.refreshCallBack {
override fun onLogin() {
handler.complete(true)
}
override fun onLoginFailure(errorMessage: String?) {
handler.complete(false)
}
})
}
@JavascriptInterface
fun trackSensorsAnalytics(json: Any) {
val hashMap = json.toString().toObject<HashMap<String, Any>>() ?: return
val eventName = hashMap.remove(EVENT_NAME) ?: return
when (eventName) {
EVENT_MEMBER_RECHARGE_BUTTON_CLICK -> {
hashMap[KEY_IS_FIRST_TIME] = SPUtils.getBoolean(SP_MEMBER_RECHARGE_BUTTON_CLICK, true)
SPUtils.setBoolean(SP_MEMBER_RECHARGE_BUTTON_CLICK, false)
}
}
SensorsBridge.trackSensorsAnalyticsFromWeb(eventName.toString(), hashMap)
}
/**
* 获取 ExposureEvent可能为空
*/
@ -901,15 +815,4 @@ class DefaultJsApi(
}
}
}
interface OnWebClickListener {
fun onPreOrderWithAli(order: OrderEntity)
fun onPreOrderWithWechat(order: OrderEntity)
fun onStartGameAccelerate(accInfo: AcctRecordEntity.AccInfo)
fun onStopGameAccelerate()
}
}

View File

@ -4,7 +4,6 @@ import android.app.Activity
import android.content.Context
import com.gh.common.util.DialogUtils
import com.gh.common.util.DirectUtils
import com.gh.common.util.PackageChangeHelper
import com.gh.common.util.TempCertificationUtils
import com.gh.gamecenter.feature.entity.GameEntity
@ -26,10 +25,6 @@ class LandPageAddressHandler : DownloadChainHandler() {
processEndCallback?.invoke(asVGame, null)
}
} else {
val packageName = gameEntity.getApk().firstOrNull()?.packageName
if (packageName?.isNotEmpty() == true) {
PackageChangeHelper.addInstallPendingPackage(packageName)
}
DirectUtils.directToExternalBrowser(context, gameEntity.landPageAddressDialog!!.link!!)
}
}

View File

@ -8,21 +8,12 @@ import com.gh.gamecenter.feature.entity.GameEntity
class PackageCheckHandler : DownloadChainHandler() {
override fun handleRequest(context: Context, gameEntity: GameEntity, asVGame: Boolean) {
fun nextOrProcessEnd() {
PackageCheckDialogFragment.show((context as AppCompatActivity), gameEntity) {
if (hasNext()) {
getNext()?.handleRequest(context, gameEntity, asVGame)
} else {
processEndCallback?.invoke(asVGame, null)
}
}
if (gameEntity.canSpeed) {
nextOrProcessEnd()
} else {
PackageCheckDialogFragment.show((context as AppCompatActivity), gameEntity) {
nextOrProcessEnd()
}
}
}
}

View File

@ -3,6 +3,7 @@ package com.gh.common.dialog
import android.animation.ValueAnimator
import android.content.Context
import android.content.DialogInterface
import android.content.pm.PackageInfo
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
@ -18,6 +19,7 @@ import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.gh.common.util.DirectUtils
import com.gh.common.util.LogUtils
import com.gh.common.util.PackageHelper
import com.gh.common.util.PackageUtils
import com.gh.download.DownloadManager
import com.gh.gamecenter.common.base.BaseRecyclerViewHolder
@ -57,6 +59,7 @@ class PackageCheckDialogFragment : BaseDialogFragment() {
private val mDuration = 3000
private var mDisposable: Disposable? = null
private var mAdapter: PackageCheckAdapter? = null
private var mAllInstalledPackages = PackageHelper.getInstalledPackageNameList(HaloApp.getInstance().application, 0)
var gameEntity: GameEntity? = null
var callBack: ConfirmListener? = null
@ -192,7 +195,7 @@ class PackageCheckDialogFragment : BaseDialogFragment() {
if (binding.noRemindAgainCb.isChecked) {
saveRecord(entity)
}
val isAllPackageInstalled = isAllPackageInstalled(entity)
val isAllPackageInstalled = isAllPackageInstalled(mAllInstalledPackages, entity)
if (isAllPackageInstalled) {
mDismissByTouchInside = true
callBack?.onConfirm()
@ -296,7 +299,7 @@ class PackageCheckDialogFragment : BaseDialogFragment() {
private fun getNotInstalledLink(packageDialogEntity: PackageDialogEntity): LinkEntity? {
val links = LinkedHashSet<LinkEntity>()
packageDialogEntity.detectionObjects.forEach { obj ->
if (!checkDetectionsInstalled(obj.packages)) {
if (!checkDetectionsInstalled(mAllInstalledPackages, obj.packages)) {
obj.assignDownload.forEach {
links.add(packageDialogEntity.links[it])
}
@ -322,8 +325,9 @@ class PackageCheckDialogFragment : BaseDialogFragment() {
override fun onResume() {
super.onResume()
mAllInstalledPackages = PackageHelper.getInstalledPackageNameList(HaloApp.getInstance().application, 0)
gameEntity?.packageDialog?.let {
if (isAllPackageInstalled(it)) {
if (isAllPackageInstalled(mAllInstalledPackages, it)) {
callBack?.onConfirm()
dismissAllowingStateLoss()
}
@ -359,6 +363,7 @@ class PackageCheckDialogFragment : BaseDialogFragment() {
@Subscribe(threadMode = ThreadMode.MAIN)
fun onEventMainThread(busFour: EBPackage) {
if (busFour.isInstalledOrUninstalled()) {
mAllInstalledPackages = PackageHelper.getInstalledPackageNameList(HaloApp.getInstance().application, 0)
mAdapter?.notifyDataSetChanged()
}
}
@ -383,7 +388,7 @@ class PackageCheckDialogFragment : BaseDialogFragment() {
val entity = entities[position]
holder.binding.gameNameTv.text = entity.text
if (position <= index) {
val isAllInstalled = checkDetectionsInstalled(entity.packages)
val isAllInstalled = checkDetectionsInstalled(mAllInstalledPackages, entity.packages)
if (isAllInstalled) {
holder.binding.statusTv.text = "已安装"
holder.binding.statusTv.setTextColor(ContextCompat.getColor(context, com.gh.gamecenter.common.R.color.text_theme))
@ -411,7 +416,8 @@ class PackageCheckDialogFragment : BaseDialogFragment() {
return
}
if (isAllPackageInstalled(packageDialogEntity)) {
val allInstalledPackages = PackageHelper.getInstalledPackageNameList(HaloApp.getInstance().application, 0)
if (isAllPackageInstalled(allInstalledPackages, packageDialogEntity)) {
callBack.onConfirm()
return
}
@ -447,11 +453,13 @@ class PackageCheckDialogFragment : BaseDialogFragment() {
}
private fun checkDetectionsInstalled(
allInstalledPackages: List<String>,
packages: ArrayList<String>
): Boolean {
var isPackagesInstalled = false
packages.forEach { packageName ->
if (PackageUtils.isInstalledFromAllPackage(HaloApp.getInstance(), packageName)) {
val isInstalled = allInstalledPackages.find { it == packageName } != null
if (isInstalled) {
isPackagesInstalled = true
return@forEach
}
@ -461,14 +469,17 @@ class PackageCheckDialogFragment : BaseDialogFragment() {
fun isAllPackageInstalled(
allInstalledPackages: List<String>,
packageDialogEntity: PackageDialogEntity
): Boolean {
var isAllInstalled = true
packageDialogEntity.detectionObjects.forEach loop@{ obj ->
if (!checkDetectionsInstalled(obj.packages)) {
return false
if (!checkDetectionsInstalled(allInstalledPackages, obj.packages)) {
isAllInstalled = false
return isAllInstalled
}
}
return true
return isAllInstalled
}
}
}

View File

@ -17,7 +17,7 @@ import com.gh.gamecenter.common.entity.ErrorEntity
import com.gh.gamecenter.core.utils.CurrentActivityHolder
import com.gh.gamecenter.core.utils.DisplayUtils
import com.gh.gamecenter.databinding.DialogWechatBindingFailedBinding
import com.gh.gamecenter.login.user.UserManager
import com.gh.gamecenter.login.user.UserRepository
import com.lightgame.utils.Utils
class WechatBindingFailedDialogFragment : BaseDialogFragment() {
@ -48,10 +48,10 @@ class WechatBindingFailedDialogFragment : BaseDialogFragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
UserManager.getInstance().userInfoEntity?.let {
currentUserId = it.getShortUserId()
binding.tvCurrentName.text = it.name ?: ""
binding.ivCurrentAvatar.displayAvatar(it.icon)
UserRepository.getInstance().loginUserInfo.observe(viewLifecycleOwner) {
currentUserId = it.data.getShortUserId()
binding.tvCurrentName.text = it.data.name
binding.ivCurrentAvatar.displayAvatar(it.data.icon)
binding.tvUserId.text = getString(R.string.user_id, currentUserId)
}

View File

@ -10,12 +10,16 @@ fun FragmentManager.popBackStackAllowStateLoss() {
fun FragmentManager.popBackStackAllowStateLoss(id: Int, flags: Int) {
if (!isStateSaved) {
popBackStack(id, flags)
} else {
hook { popBackStack(id, flags) }
}
}
fun FragmentManager.popBackStackAllowStateLoss(name: String?, flags: Int) {
if (!isStateSaved) {
popBackStack(name, flags)
} else {
hook { popBackStack(name, flags) }
}
}
@ -25,9 +29,34 @@ fun FragmentManager.popBackStackImmediateAllowStateLoss(id: Int, flags: Int) =
if (!isStateSaved) {
popBackStackImmediate(id, flags)
} else {
false
hook { popBackStackImmediate(id, flags) }
}
fun FragmentManager.popBackStackImmediateAllowStateLoss(name: String?, flags: Int): Boolean =
if (!isStateSaved) {
popBackStackImmediate(name, flags)
} else {
hook { popBackStackImmediate(name, flags) }
}
/**
* 通过反射将FragmentManager的mStateSaved和mStopped设为false否则Activity在回调onSavedInstance以后
* 调用Fragment的popBackStack和popBackStackImmediate方法会触发“java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState”的异常。
* @see <a href="https://sentry.shanqu.cc/organizations/lightgame/issues/418688/?project=22">Sentry-418688</a>
*/
private fun <T> FragmentManager.hook(callback: FragmentManager.() -> T): T {
val mStateSavedField = getField(this::class.java,"mStateSaved")
val stateSaved = mStateSavedField.get(this);
mStateSavedField.set(this, false)
val mStoppedField = getField(this::class.java,"mStopped")
val stopped = mStateSavedField.get(this);
mStoppedField.set(this, false)
val result = callback.invoke(this)
mStateSavedField.set(this, stateSaved)
mStoppedField.set(this, stopped)
return result
}
@Throws(NoSuchFieldException::class)
private fun getField(clazz: Class<*>, name: String): Field {
var cls: Class<*>? = clazz

View File

@ -1,61 +0,0 @@
package com.gh.common.provider
import android.annotation.SuppressLint
import com.gh.gamecenter.common.utils.SensorsBridge
import com.gh.gamecenter.common.utils.singleToMain
import com.gh.gamecenter.core.provider.IAcceleratorProvider
import com.gh.gamecenter.core.provider.IWechatPayResultProvider
import com.gh.gamecenter.feature.entity.OrderEntity
import com.gh.gamecenter.feature.entity.VipEntity
import com.gh.gamecenter.feature.eventbus.EBPayState
import com.gh.gamecenter.login.user.UserManager
import com.gh.gamecenter.login.user.UserRepository
import com.halo.assistant.member.MemberRepository
import com.therouter.TheRouter
import org.greenrobot.eventbus.EventBus
@com.therouter.inject.ServiceProvider
class WechatPayResultProviderImpl : IWechatPayResultProvider {
private val repository = MemberRepository.instance
@SuppressLint("CheckResult")
override fun onPayComplete(nonceStr: String, order: Any?) {
val orderEntity = order as? OrderEntity
repository.getWechatPayResult(nonceStr)
.compose(singleToMain())
.subscribe({
// 支付成功
EventBus.getDefault().post(EBPayState.PaySuccess)
// 先刷新本地状态,支付成功,肯定是付费会员
TheRouter.get(IAcceleratorProvider::class.java)?.setVipEntity(
VipEntity(
_vipStatus = true,
_isNewUser = false,
_isTryVip = false
)
)
val userId = UserManager.getInstance().userId
if (userId.isNotBlank()) {
UserRepository.getInstance().refreshVipStatus(userId, true)
}
SensorsBridge.trackMemberRechargeResult(
MemberRepository.PAYMENT_TYPE_WECHAT,
orderEntity?.setMenuName ?: "",
orderEntity?.paymentAmount ?: "",
MemberRepository.RECHARGE_RESULT_SUCCESS
)
}, {
// 支付失败
EventBus.getDefault().post(EBPayState.PayFail)
SensorsBridge.trackMemberRechargeResult(
MemberRepository.PAYMENT_TYPE_WECHAT,
orderEntity?.setMenuName ?: "",
orderEntity?.paymentAmount ?: "",
MemberRepository.RECHARGE_RESULT_FAILURE
)
})
}
}

View File

@ -5,8 +5,6 @@ import android.text.TextUtils;
import android.view.View;
import android.widget.TextView;
import androidx.constraintlayout.widget.ConstraintLayout;
import com.gh.common.filter.RegionSetting;
import com.gh.common.filter.RegionSettingHelper;
import com.gh.common.repository.ReservationRepository;
@ -43,8 +41,7 @@ public class DetailDownloadUtils {
/**
* 更新底部下载区域
*
* @param viewHolder 下载区域的包裹
* @param viewHolder 下载区域的包裹
* @param ignoreDownloadEntity 忽略下载实体(往往用于下载异常时)
*/
public static void updateViewHolder(DetailViewHolder viewHolder, boolean ignoreDownloadEntity) {
@ -55,11 +52,6 @@ public class DetailDownloadUtils {
if (viewHolder.getMultiVersionDownloadTv() != null) {
viewHolder.getMultiVersionDownloadTv().setVisibility(View.GONE);
}
if (viewHolder.getSpeedContainer() != null) {
viewHolder.getSpeedContainer().setVisibility(View.GONE);
}
viewHolder.setSpeedViewsVisible(false);
// 根据预置的配置更新 ViewHolder 的状态 (譬如青少年模式、下载内容为空等)
if (updateViewHolderWithPredefinedConfig(viewHolder, gameEntity)) {
@ -227,7 +219,7 @@ public class DetailDownloadUtils {
downloadButton.setText("");
}
} else {
decoratedBtnText = rawBtnText + (containsAddWord ? "" : downloadAddWord) + getWrappedDownloadSizeText(viewHolder);
decoratedBtnText = rawBtnText + (containsAddWord? "" : downloadAddWord) + getWrappedDownloadSizeText(viewHolder);
if (overlayTv != null && downloadButton.getVisibility() != View.GONE) {
if (context.getString(com.gh.gamecenter.feature.R.string.launch).equals(rawBtnText)
@ -254,24 +246,16 @@ public class DetailDownloadUtils {
}
}
} else {
boolean isLaunchState = false;
// 非畅玩,显示为普通游戏
if (context.getString(com.gh.gamecenter.feature.R.string.pluggable).equals(rawBtnText)) {
downloadButton.setButtonStyle(DownloadButton.ButtonStyle.PLUGIN);
} else if (context.getString(com.gh.gamecenter.feature.R.string.launch).equals(rawBtnText)) {
downloadButton.setButtonStyle(DownloadButton.ButtonStyle.LAUNCH_OR_OPEN);
isLaunchState = true;
} else if (context.getString(com.gh.gamecenter.feature.R.string.install).equals(rawBtnText)) {
downloadButton.setButtonStyle(DownloadButton.ButtonStyle.INSTALL_NORMAL);
} else {
downloadButton.setButtonStyle(DownloadButton.ButtonStyle.NORMAL);
}
// 只有下载按钮状态为 “启动” 时才需要展示加速ui
if (isLaunchState) {
viewHolder.showAcceleratorGuideLayer();
} else {
viewHolder.hideSpeedUi();
}
if (showDualDownloadButton && viewHolder.getLocalDownloadSizeTv() != null) {
viewHolder.getLocalDownloadSizeTv().setVisibility(View.GONE);

View File

@ -53,7 +53,6 @@ object DownloadObserver {
private const val CORE_EVENT_DOWNLOAD_COMPLETE_LOGGED = "CORE_EVENT_DOWNLOAD_COMPLETE_LOGGED"
private val mRetryableHashMap = hashMapOf<String, Boolean>()
private val mRetryableProgressMap = hashMapOf<String, Long>()
/**
* 当下载任务是 预约上线提醒 触发的,则所有弹窗均不显示
@ -147,8 +146,7 @@ object DownloadObserver {
|| DownloadStatus.timeout == status
) {
if (mRetryableHashMap[downloadEntity.url] == true
&& (NetworkUtils.isWifiConnected(HaloApp.getInstance().application)
|| NDownloadBridge.isDownloadViaTrafficAllowed(downloadEntity))
&& NetworkUtils.isWifiConnected(HaloApp.getInstance().application)
) {
downloadManager.resumeDownload(downloadEntity.url)
mRetryableHashMap[downloadEntity.url] = false
@ -259,7 +257,6 @@ object DownloadObserver {
}
mRetryableHashMap.remove(downloadEntity.url)
mRetryableProgressMap.remove(downloadEntity.url)
EventBus.getDefault().post(EBDownloadStatus("done", "", "", "", downloadEntity.packageName, ""))
}
@ -267,9 +264,7 @@ object DownloadObserver {
DownloadNotificationHelper.addOrUpdateDownloadNotification(downloadEntity)
// 如果已下载大小发生变化,表示成功恢复下载,则重置重试标记
if (status == DownloadStatus.downloading
&& downloadEntity.progress != mRetryableProgressMap[downloadEntity.url]) {
mRetryableProgressMap[downloadEntity.url] = downloadEntity.progress
if (status == DownloadStatus.downloading) {
mRetryableHashMap[downloadEntity.url] = true
}
}

View File

@ -2778,34 +2778,4 @@ object NewFlatLogUtils {
parseAndPutMeta()(this)
}.let(::log)
}
// 自有开屏广告加载
fun logSplashAdLoad(id: String) {
json {
KEY_EVENT to "splash_ad_load"
"ad_id" to id
parseAndPutMeta()(this)
}.let(::log)
}
// 自有开屏广告展示
fun logSplashAdShow(id: String, duration: Long) {
json {
KEY_EVENT to "splash_ad_show"
"ad_id" to id
"duration" to duration
parseAndPutMeta()(this)
}.let(::log)
}
// 自有开屏广告加载/展示失败
@JvmStatic
fun logSplashAdFail(id: String, error: String) {
json {
KEY_EVENT to "splash_ad_fail"
"ad_id" to id
"error" to error
parseAndPutMeta()(this)
}.let(::log)
}
}

View File

@ -578,6 +578,7 @@ object PackageHelper {
Utils.log(TAG, "refreshWrongInstallStatus 检查安装状态异常的应用")
val uninstalledButKeepingWrongStatusPackageNameSet: HashSet<String> = hashSetOf()
val updatedButKeepingWrongStatusPackageNameSet: HashSet<String> = hashSetOf()
for (packageName in packageNameSet) {
val installedVersionName = PackageUtils.getVersionNameByPackageName(packageName)
@ -586,9 +587,18 @@ object PackageHelper {
&& installedVersionName == null
) {
uninstalledButKeepingWrongStatusPackageNameSet.add(packageName)
} else if (PackagesManager.isInstalled(packageName)
&& installedVersionName != null
&& !PackagesManager.isInstalledWithSpecificVersion(packageName, installedVersionName)
) {
updatedButKeepingWrongStatusPackageNameSet.add(packageName)
}
}
Utils.log(
TAG,
"refreshWrongInstallStatus 需要更新已更新状态的包数量为 ${updatedButKeepingWrongStatusPackageNameSet.size}"
)
Utils.log(
TAG,
"refreshWrongInstallStatus 需要移除已安装的包数量为 ${uninstalledButKeepingWrongStatusPackageNameSet.size}"
@ -606,6 +616,12 @@ object PackageHelper {
additionalWhiteListPackageNameSet.toString()
)
}
if (updatedButKeepingWrongStatusPackageNameSet.isNotEmpty()) {
for (packageName in updatedButKeepingWrongStatusPackageNameSet) {
PackageChangeHelper.addUpdate(packageName)
}
}
}
}
}
@ -619,6 +635,7 @@ object PackageHelper {
val installedButKeepingWrongStatusPackageNameSet: HashSet<String> = hashSetOf()
val uninstalledButKeepingWrongStatusPackageNameSet: HashSet<String> = hashSetOf()
val updatedButKeepingWrongStatusPackageNameSet: HashSet<String> = hashSetOf()
for (game in gameEntityList) {
for (apk in game.getApk()) {
@ -634,6 +651,13 @@ object PackageHelper {
&& installedVersionName == null
) {
uninstalledButKeepingWrongStatusPackageNameSet.add(packageName)
} else if (PackagesManager.isInstalled(packageName)
&& installedVersionName != null
&& !PackagesManager.isInstalledWithSpecificVersion(packageName, installedVersionName)
&& !PackagesManager.isCanUpdate(game.id, packageName, false)
) {
cachedPkgNameAndGameEntityMap.put(packageName, game)
updatedButKeepingWrongStatusPackageNameSet.add(packageName)
}
}
}
@ -642,6 +666,10 @@ object PackageHelper {
TAG,
"refreshWrongInstallStatus 需要更新已安装状态的包数量为 ${installedButKeepingWrongStatusPackageNameSet.size}"
)
Utils.log(
TAG,
"refreshWrongInstallStatus 需要更新已更新状态的包数量为 ${updatedButKeepingWrongStatusPackageNameSet.size}"
)
Utils.log(
TAG,
"refreshWrongInstallStatus 需要移除已安装的包数量为 ${uninstalledButKeepingWrongStatusPackageNameSet.size}"
@ -671,6 +699,12 @@ object PackageHelper {
additionalWhiteListPackageNameSet.toString()
)
}
if (updatedButKeepingWrongStatusPackageNameSet.isNotEmpty()) {
for (packageName in updatedButKeepingWrongStatusPackageNameSet) {
PackageChangeHelper.addUpdate(packageName, cachedPkgNameAndGameEntityMap.remove(packageName))
}
}
}
}
}

View File

@ -81,11 +81,28 @@ object PackageLauncher {
gameEntity: GameEntity? = null,
packageName: String?
) {
if (packageName.isNullOrEmpty()) {
ToastUtils.toast("启动失败")
return
}
// 获取 GameInstall 实体,用于记录启动日志用
val gameInstall = if (gameEntity != null) {
GameInstall.transformGameInstall(gameEntity, packageName)
} else {
PackagesManager.getInstalledList().find { it.packageName == packageName }
}
if (gameInstall != null) {
NewFlatLogUtils.logGameLaunch(
gameId = gameInstall.id ?: "unknown",
gameName = gameInstall.name ?: "unknown",
gameCategory = gameInstall.category ?: "unknown",
downloadStatus = if (gameInstall.downloadStatus == "demo") "试玩" else "下载"
)
}
try {
val intent = context.applicationContext.packageManager.getLaunchIntentForPackage(packageName)
if (intent != null) {
@ -96,26 +113,6 @@ object PackageLauncher {
} catch (e: Exception) {
ToastUtils.toast( "启动失败")
}
try {
// 获取 GameInstall 实体,用于记录启动日志用
val gameInstall = if (gameEntity != null) {
GameInstall.transformGameInstall(gameEntity, packageName)
} else {
PackagesManager.getInstalledList().find { it.packageName == packageName }
}
if (gameInstall != null) {
NewFlatLogUtils.logGameLaunch(
gameId = gameInstall.id ?: "unknown",
gameName = gameInstall.name ?: "unknown",
gameCategory = gameInstall.category ?: "unknown",
downloadStatus = if (gameInstall.downloadStatus == "demo") "试玩" else "下载"
)
}
} catch (e: RuntimeException) {
// 都 DeadSystemException 了,还想啥日志上报
}
}
}

View File

@ -301,7 +301,7 @@ public class PackageUtils {
Signature[] signatures = packageInfo.signatures;
// 使用幸运破解器破解安卓签名认证可能会出现不用签名也能装的情况,这里有可能是空的
if (signatures.length > 0 && signatures[0] != null) {
if (signatures[0] != null) {
return parseSignature(signatures[0].toByteArray());
} else {
return new String[]{null, null};

View File

@ -6,7 +6,6 @@ import com.gh.gamecenter.core.runOnIoThread
import com.gh.gamecenter.core.runOnUiThread
import com.gh.gamecenter.core.utils.ToastUtils
import com.gh.gamecenter.feature.entity.GameEntity
import com.gh.gamecenter.login.user.UserManager
import com.gh.ndownload.NHttpClient
import com.lightgame.utils.AppManager
import org.json.JSONObject
@ -90,12 +89,4 @@ object TempCertificationUtils {
return stringBuffer.toString()
}
/**
* 检测光环是否实名
*/
fun isUserVerified(): Boolean {
val idCard = UserManager.getInstance().userInfoEntity?.idCard
// 账号已实名
return idCard != null && idCard.status == 0
}
}

View File

@ -1,81 +0,0 @@
package com.gh.gamecenter
import android.os.Bundle
import android.widget.Button
import androidx.appcompat.app.AppCompatActivity
import com.gh.gamecenter.common.retrofit.Response
import com.gh.gamecenter.core.provider.IAcceleratorProvider
import com.gh.gamecenter.feature.entity.BaseEntity
import com.gh.gamecenter.login.retrofit.RetrofitManager
import com.gh.gamecenter.login.user.UserManager
import com.therouter.TheRouter
import io.reactivex.Observable
import io.reactivex.Single
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.schedulers.Schedulers
import retrofit2.HttpException
/**
* 奇游用户批量注册
*/
class BatchRegisterActivity : AppCompatActivity() {
private val userIds = listOf(
""
)
private var iAcceleratorProvider: IAcceleratorProvider? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_batch_register)
iAcceleratorProvider = TheRouter.get(IAcceleratorProvider::class.java)
val btnRegister = findViewById<Button>(R.id.btn_register)
btnRegister.setOnClickListener {
doRegister()
}
}
private fun doRegister() {
println("kayn -->doRegister:${userIds.size}")
Observable.fromIterable(userIds)
.flatMap({ userId ->
RetrofitManager.getInstance().newApi
.getQyToken(userId, "gjonline_vip")
.onErrorReturnItem(BaseEntity())
.flatMap { entity ->
val token = entity.data?.token ?: ""
Single.create<Pair<Boolean, String>> {
if (token.isBlank()) {
it.onSuccess(false to userId)
} else {
iAcceleratorProvider?.setQyUserToken(token) { isSuccess ->
it.onSuccess(isSuccess to userId)
}
}
}
}.toObservable()
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(object : Response<Pair<Boolean, String>>() {
override fun onNext(response: Pair<Boolean, String>) {
super.onNext(response)
val (isSuccess, userId) = response
println("kayn -->isSuccess:$isSuccess --userId:$userId")
}
override fun onFailure(e: HttpException?) {
super.onFailure(e)
}
override fun onComplete() {
super.onComplete()
}
})
}
}

View File

@ -554,31 +554,25 @@ public class MainActivity extends BaseActivity {
protected void handleMessage(Message msg) {
super.handleMessage(msg);
if (msg.what == COUNTDOWN_AD || msg.what == COUNTDOWN_SDK_AD) {
mCountdownCount++;
int maxCount;
// 第三秒的时候初始化 Fragment
if (mCountdownCount == 3) {
doInitMainFragment(mTempSavedInstanceState);
}
if (msg.what == COUNTDOWN_AD) {
maxCount = mCountdownMaxCount;
} else {
maxCount = COUNTDOWN_SDK_MAX_COUNT;
}
// 读秒到一半的时候初始化 MainWrapperFragment
if (mCountdownCount == maxCount / 2) {
doInitMainFragment(mTempSavedInstanceState);
}
mCountdownCount++;
if (maxCount < mCountdownCount) {
AdDelegateHelper.INSTANCE.setShowingSplashAd(false);
hideSplashAd();
if (msg.what == COUNTDOWN_AD && msg.obj instanceof StartupAdEntity) {
StartupAdEntity ad = (StartupAdEntity) msg.obj;
if (!AdDelegateHelper.INSTANCE.isOwnerSplashAdShown()) {
com.gh.common.util.NewFlatLogUtils.logSplashAdFail(ad.getId(), "广告加载超时");
}
AdDelegateHelper.INSTANCE.setOwnerSplashAdShown(false);
LinkEntity linkEntity = ad.getJump();
SensorsBridge.trackEvent(
"SplashAdOwnSkip",

View File

@ -329,19 +329,6 @@ open class SearchActivity : BaseActivity() {
// MtaHelper.onEvent("游戏搜索", "主动搜索", newSearchKey)
}
override fun onResume() {
super.onResume()
val newSearchKey = searchEt.text.toString().trim { it <= ' ' }
if (newSearchKey.isBlank()) {
try {
popBackToFragment(SearchDefaultFragment::class.java.name)
} catch (e: Exception) {
// no implement
}
}
}
protected open fun provideDao(): ISearchHistoryDao = SearchHistoryDao(this)
open fun updateDisplayType(type: DisplayType) {

View File

@ -14,6 +14,8 @@ import androidx.core.app.NotificationCompat
import androidx.core.text.bold
import androidx.core.text.buildSpannedString
import androidx.core.text.color
import com.therouter.router.Route
import com.therouter.TheRouter
import com.gh.common.dialog.NewPrivacyPolicyDialogFragment
import com.gh.common.util.DeviceTokenUtils
import com.gh.common.util.DialogUtils
@ -30,14 +32,13 @@ import com.gh.gamecenter.common.utils.*
import com.gh.gamecenter.core.iinterface.ISplashScreen
import com.gh.gamecenter.core.provider.IAppProvider
import com.gh.gamecenter.core.provider.IPackageUtilsProvider
import com.gh.gamecenter.core.provider.IPushProvider
import com.gh.gamecenter.core.runOnIoThread
import com.gh.gamecenter.core.utils.DisplayUtils
import com.gh.gamecenter.core.utils.SPUtils
import com.gh.gamecenter.feature.utils.PlatformUtils
import com.gh.gamecenter.pkg.PkgHelper
import com.halo.assistant.HaloApp
import com.therouter.TheRouter
import com.therouter.router.Route
import org.json.JSONObject
import splitties.systemservices.notificationManager
import java.text.SimpleDateFormat
@ -89,10 +90,8 @@ class SplashScreenActivity : BaseActivity(), ISplashScreen {
showPrivacyDialog()
} else {
val spanBuilder = buildSpannedString {
append(
"这个弹窗只会在右上角有环境标签的测试包出现" +
"\n进入应用以后还可以到关于我们页面长按应用图标重新选择"
)
append("这个弹窗只会在右上角有环境标签的测试包出现" +
"\n进入应用以后还可以到关于我们页面长按应用图标重新选择")
bold {
color(com.gh.gamecenter.common.R.color.text_theme.toColor(this@SplashScreenActivity)) {
append("\n点击这里进行预设置渠道")
@ -104,7 +103,7 @@ class SplashScreenActivity : BaseActivity(), ISplashScreen {
executeDex2OatInAdvance()
DialogHelper.showDialog(
context = this,
title = "选择环境",
title ="选择环境",
content = spanBuilder,
confirmText = "正式环境",
cancelText = "测试环境",
@ -131,7 +130,6 @@ class SplashScreenActivity : BaseActivity(), ISplashScreen {
} else {
launchMainActivity()
}
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.R) {
SPUtils.setString(Constants.SP_XAPK_UNZIP_ACTIVITY, "")
SPUtils.setString(Constants.SP_XAPK_URL, "")

View File

@ -6,19 +6,17 @@ import android.os.Bundle
import android.text.TextUtils
import android.view.KeyEvent
import android.view.View
import com.gh.common.constant.Config
import com.therouter.router.Route
import com.gh.gamecenter.common.base.activity.ToolBarActivity
import com.gh.gamecenter.common.constant.Constants
import com.gh.gamecenter.common.constant.EntranceConsts
import com.gh.gamecenter.common.constant.RouteConsts
import com.gh.gamecenter.common.entity.ToolBoxEntity
import com.gh.gamecenter.common.utils.EnvHelper
import com.gh.gamecenter.common.utils.updateStatusBarColor
import com.gh.gamecenter.feature.entity.ConcernEntity
import com.gh.gamecenter.feature.entity.NewsEntity
import com.gh.gamecenter.common.entity.ToolBoxEntity
import com.halo.assistant.fragment.WebFragment
import com.halo.assistant.member.MemberActivity
import com.therouter.router.Route
@Route(path = RouteConsts.activity.webActivity)
open class WebActivity : ToolBarActivity() {
@ -31,8 +29,6 @@ open class WebActivity : ToolBarActivity() {
val mIsBackpressRequireConfirmation =
bundle.getBoolean(WebFragment.KEY_REQUIRE_BACK_CONFIRMATION, false)
mIsFullScreen = !TextUtils.isEmpty(mGameName) && mIsBackpressRequireConfirmation
mIsFullScreen = true
if (mIsFullScreen) {
setTheme(R.style.AppFullScreenTheme)
}
@ -309,17 +305,5 @@ open class WebActivity : ToolBarActivity() {
intent.putExtra(NORMAL_FRAGMENT_BUNDLE, bundle)
return intent
}
@JvmStatic
fun getMyAssetsIntent(context: Context): Intent {
val intent = Intent(context, MemberActivity::class.java)
val url = if (EnvHelper.isDevEnv) {
Constants.MY_ASSETS_DEV
} else {
Constants.MY_ASSETS
}
intent.putExtra(EntranceConsts.KEY_URL, url)
return intent
}
}
}

View File

@ -4,11 +4,8 @@ import android.content.Context
import android.content.Intent
import android.text.TextUtils
import android.view.View
import android.widget.ImageView
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.constraintlayout.widget.Group
import androidx.fragment.app.DialogFragment
import androidx.fragment.app.FragmentActivity
import com.airbnb.lottie.LottieAnimationView
@ -16,7 +13,6 @@ import com.gh.common.chain.*
import com.gh.common.constant.Config
import com.gh.common.dialog.DeviceRemindDialog
import com.gh.common.dialog.GameOffServiceDialogFragment
import com.gh.common.dialog.PackageCheckDialogFragment
import com.gh.common.filter.RegionSettingHelper
import com.gh.common.history.HistoryHelper
import com.gh.common.simulator.NewSimulatorGameManager
@ -49,7 +45,6 @@ import com.gh.gamecenter.feature.exposure.ExposureEvent
import com.gh.gamecenter.feature.view.DownloadButton
import com.gh.gamecenter.feature.view.DownloadButton.ButtonStyle
import com.gh.gamecenter.gamedetail.GameDetailFragment
import com.gh.gamecenter.gamedetail.accelerator.GameDetailAcceleratorUiHelper
import com.gh.gamecenter.gamedetail.dialog.GamePermissionDialogFragment
import com.gh.gamecenter.teenagermode.TeenagerModeActivity.Companion.getIntent
import com.gh.vspace.VHelper
@ -67,8 +62,7 @@ class DetailViewHolder(
name: String?,
title: String?,
val traceEvent: ExposureEvent?,
val isSupportDualButton: Boolean = false, // 是否支持双下载按钮,不支持的时候跟普通列表意义选用优先级高的那个来显示,
val acceleratorUiHelper: GameDetailAcceleratorUiHelper? = null // 网速加速,只有游戏详情才有
val isSupportDualButton: Boolean = false // 是否支持双下载按钮,不支持的时候跟普通列表意义选用优先级高的那个来显示
) {
var context: Context
var downloadBottom: View
@ -96,12 +90,6 @@ class DetailViewHolder(
// 多版本下载文字
var multiVersionDownloadTv: TextView?
// 加速按钮
val speedContainer: ConstraintLayout?
private val ivFreeVipTag: ImageView?
private val gMoreZone: Group?
// 注意 View 的命名
init {
downloadBottom = view.findViewById(R.id.detail_ll_bottom)
@ -116,10 +104,6 @@ class DetailViewHolder(
localDownloadTitleTv = view.findViewById(R.id.localDownloadTitleTv)
localDownloadButton = view.findViewById(R.id.localDownloadButton)
speedContainer = view.findViewById(R.id.cl_speed_container)
ivFreeVipTag = view.findViewById(R.id.iv_free_vip_tag)
gMoreZone = view.findViewById(R.id.g_more_zone)
context = view.context
var gameDownloadMode = gameEntity.getGameDownloadButtonMode()
@ -174,9 +158,7 @@ class DetailViewHolder(
localDownloadButton?.putObject(gameEntity)
localDownloadButton?.setTag(
com.gh.gamecenter.feature.R.string.download, context.getString(
com.gh.gamecenter.feature.R.string.download_local
)
)
com.gh.gamecenter.feature.R.string.download_local))
}
}
downloadPb.putWidgetBusinessName("游戏详情页")
@ -194,19 +176,6 @@ class DetailViewHolder(
gamePermissionDialogFragment?.dismissAllowingStateLoss()
}
fun hideSpeedUi() {
acceleratorUiHelper?.showSpeedUi = false
}
fun showAcceleratorGuideLayer() {
acceleratorUiHelper?.checkIfShowGuideLayer(context)
}
fun setSpeedViewsVisible(isVisible: Boolean) {
ivFreeVipTag?.goneIf(!isVisible)
speedContainer?.goneIf(!isVisible)
}
internal class OnDetailDownloadClickListener(
private val mViewHolder: DetailViewHolder,
private val mEntrance: String?,
@ -225,10 +194,6 @@ class DetailViewHolder(
if (mGameEntity.isLandPageAddressDialog() && !mGameEntity.isLandPageAddressDialogShowOnly()) {
// 第三方落地页为开启状态并且展示状态不为“仅显示弹窗”,需要在点击确认后显示弹窗
DialogUtils.showLandPageAddressDialog(mViewHolder.context, mGameEntity) {
val packageName = mGameEntity.getApk().firstOrNull()?.packageName
if (packageName?.isNotEmpty() == true) {
PackageChangeHelper.addInstallPendingPackage(packageName)
}
DirectUtils.directToExternalBrowser(mViewHolder.context, mGameEntity.landPageAddressDialog!!.link!!)
}
}
@ -365,19 +330,7 @@ class DetailViewHolder(
if (mAsVGame) {
VHelper.installOrLaunch(mViewHolder.context, mGameEntity, null)
} else {
// 如果游戏配置了加速,则启动时需要进行包名检测
if (mGameEntity.canSpeed) {
PackageCheckDialogFragment.show(mViewHolder.context as AppCompatActivity, mGameEntity) {
PackageLauncher.launchApp(
mViewHolder.context, mGameEntity, mGameEntity.getUniquePackageName()
)
}
} else {
PackageLauncher.launchApp(
mViewHolder.context, mGameEntity, mGameEntity.getUniquePackageName()
)
}
PackageLauncher.launchApp(mViewHolder.context, mGameEntity, mGameEntity.getUniquePackageName())
}
} else {
GamePermissionDialogFragment.show(
@ -637,9 +590,8 @@ class DetailViewHolder(
val apkEntity = mGameEntity.getApk().firstOrNull()
val msg = FileUtils.isCanDownload(mViewHolder.context, apkEntity?.size ?: "")
if (TextUtils.isEmpty(msg)) {
val btnContainsUpdateText =
mViewHolder.context.getString(com.gh.gamecenter.feature.R.string.update_v) == buttonText
|| buttonText.contains(mViewHolder.context.getString(com.gh.gamecenter.feature.R.string.update))
val btnContainsUpdateText = mViewHolder.context.getString(com.gh.gamecenter.feature.R.string.update_v) == buttonText
|| buttonText.contains(mViewHolder.context.getString(com.gh.gamecenter.feature.R.string.update))
if (asVGame && btnContainsUpdateText) {
VHelper.updateOrReDownload(mGameEntity)

View File

@ -12,7 +12,6 @@ import androidx.recyclerview.widget.RecyclerView
import com.gh.common.exposure.IExposable
import com.gh.common.util.DialogUtils
import com.gh.common.util.DirectUtils
import com.gh.common.util.PackageChangeHelper
import com.gh.common.util.PackageInstaller
import com.gh.common.util.PackageLauncher
import com.gh.download.DownloadManager
@ -399,10 +398,6 @@ class UpdatableGameAdapter(private var mViewModel: UpdatableGameViewModel) :
if (update.isLandPageAddressDialogShowOnly()) {
updateOrPluggable(updateBtn, update, downloadEntity, pluginDesc)
} else {
val packageName = update.packageName
if (packageName.isNotEmpty() == true) {
PackageChangeHelper.addInstallPendingPackage(packageName)
}
DirectUtils.directToExternalBrowser(it.context, update.landPageAddressDialog!!.link!!)
}
}

View File

@ -1,13 +0,0 @@
package com.gh.gamecenter.gamedetail
import androidx.lifecycle.ViewModel
import com.halo.assistant.member.MemberUseCase
class AcceleratorZoneViewModel : ViewModel() {
val useCase = MemberUseCase()
override fun onCleared() {
useCase.onClear()
}
}

View File

@ -58,20 +58,20 @@ import com.gh.gamecenter.common.mvvm.Status
import com.gh.gamecenter.common.utils.*
import com.gh.gamecenter.common.view.WrapContentDraweeView
import com.gh.gamecenter.core.iinterface.IScrollable
import com.gh.gamecenter.core.provider.IAcceleratorProvider
import com.gh.gamecenter.core.utils.*
import com.gh.gamecenter.databinding.*
import com.gh.gamecenter.entity.GameUpdateEntity
import com.gh.gamecenter.entity.RecommendPopupEntity
import com.gh.gamecenter.eventbus.*
import com.gh.gamecenter.feature.entity.*
import com.gh.gamecenter.feature.entity.GameEntity
import com.gh.gamecenter.feature.entity.PluginLocation
import com.gh.gamecenter.feature.entity.SimpleGame
import com.gh.gamecenter.feature.entity.TagStyleEntity
import com.gh.gamecenter.feature.eventbus.EBConcernChanged
import com.gh.gamecenter.feature.eventbus.EBPayState
import com.gh.gamecenter.feature.exposure.ExposureEvent
import com.gh.gamecenter.feature.utils.ApkActiveUtils
import com.gh.gamecenter.feature.utils.SentryHelper
import com.gh.gamecenter.forum.detail.ForumDetailActivity
import com.gh.gamecenter.gamedetail.accelerator.GameDetailAcceleratorUiHelper
import com.gh.gamecenter.gamedetail.cloudarchive.CloudArchiveFragment
import com.gh.gamecenter.gamedetail.desc.DescFragment
import com.gh.gamecenter.gamedetail.dialog.*
@ -86,6 +86,7 @@ import com.gh.gamecenter.home.video.ScrollCalculatorHelper
import com.gh.gamecenter.login.user.UserViewModel
import com.gh.gamecenter.newsdetail.NewsDetailActivity
import com.gh.gamecenter.packagehelper.PackageViewModel
import com.gh.gamecenter.SearchActivity
import com.gh.gamecenter.simulatorgame.SimulatorGameActivity
import com.gh.gamecenter.tag.TagsActivity
import com.gh.gamecenter.video.detail.CustomManager
@ -100,7 +101,6 @@ import com.shuyu.gsyvideoplayer.builder.GSYVideoOptionBuilder
import com.shuyu.gsyvideoplayer.listener.GSYSampleCallBack
import com.shuyu.gsyvideoplayer.utils.OrientationUtils
import com.shuyu.gsyvideoplayer.video.base.GSYVideoView
import com.therouter.TheRouter
import io.reactivex.disposables.Disposable
import org.greenrobot.eventbus.Subscribe
import org.greenrobot.eventbus.ThreadMode
@ -155,8 +155,6 @@ class GameDetailFragment : BaseLazyFragment(), IScrollable {
private val mLooperHandle = LooperHandle(this)
private val mServerLooperKey = 123
private lateinit var acceleratorUiHelper: GameDetailAcceleratorUiHelper
private val dataWatcher = object : DataWatcher() {
override fun onDataChanged(downloadEntity: DownloadEntity) {
if (downloadEntity.gameId == mViewModel.gameId) {
@ -267,8 +265,7 @@ class GameDetailFragment : BaseLazyFragment(), IScrollable {
name = "游戏详情",
title = mGameEntity!!.name ?: "",
traceEvent = mTraceEvent,
isSupportDualButton = true,
acceleratorUiHelper
isSupportDualButton = true
)
private val contentCardClick: (contentCard: ContentCardEntity, position: Int) -> Unit =
@ -415,7 +412,6 @@ class GameDetailFragment : BaseLazyFragment(), IScrollable {
mVideoBinding = mBodyBinding.gameDetailVideo
mDownloadBinding = mBinding.detailLlBottom
mRecommendBinding = mBinding.gameDetailRecommendView
acceleratorUiHelper = GameDetailAcceleratorUiHelper(mDownloadBinding)
}.root
}
@ -552,12 +548,7 @@ class GameDetailFragment : BaseLazyFragment(), IScrollable {
pauseVideo()
mIsPauseTopVideo = true
}
mBodyBinding.toolbar.setTitleTextColor(
ContextCompat.getColor(
requireContext(),
com.gh.gamecenter.common.R.color.black
)
)
mBodyBinding.toolbar.setTitleTextColor(ContextCompat.getColor(requireContext(), com.gh.gamecenter.common.R.color.black))
} else if (mIsPauseTopVideo && absVerticalOffset == 0 && mVideoBinding.player.currentState == GSYVideoView.CURRENT_STATE_PAUSE) {
resumeVideo()
mIsPauseTopVideo = false
@ -678,9 +669,7 @@ class GameDetailFragment : BaseLazyFragment(), IScrollable {
}
} else {
setTextColor(com.gh.gamecenter.common.R.color.text_secondary.toColor(requireContext()))
background = com.gh.gamecenter.feature.R.drawable.bg_advance_download_game_subtitle.toDrawable(
requireContext()
)
background = com.gh.gamecenter.feature.R.drawable.bg_advance_download_game_subtitle.toDrawable(requireContext())
}
}
tagView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED)
@ -779,8 +768,6 @@ class GameDetailFragment : BaseLazyFragment(), IScrollable {
if (gameResource.status == Status.SUCCESS) {
mViewModel.logHistory(gameResource.data!!)
mGameEntity = gameResource.data
acceleratorUiHelper.setGame(gameResource.data)
loadAccelerationData(mGameEntity!!)
showBrowserInstallHintIfNeeded()
controlInstallHint()
// 添加启动弹窗的相关信息
@ -800,9 +787,7 @@ class GameDetailFragment : BaseLazyFragment(), IScrollable {
mViewModel.gameDetailLiveData.observeNonNull(this) { detailResource ->
if (detailResource.status == Status.SUCCESS) {
val data = detailResource.data ?: return@observeNonNull
if (detailResource.data?.acceleratorStatus == true) {
acceleratorUiHelper.initSpeedUi(requireActivity())
}
DataLogUtils.uploadGameLog(context, mGameEntity!!.id, mGameEntity!!.name, mEntrance)
postDelayedRunnable({
@ -854,12 +839,7 @@ class GameDetailFragment : BaseLazyFragment(), IScrollable {
DetailDownloadUtils.updateViewHolder(viewHolder)
mDestinationTab =
getTabPositionFromTabType(
arguments?.getString(
EntranceConsts.KEY_TARGET,
EntranceConsts.TAB_TYPE_DESC
) ?: EntranceConsts.TAB_TYPE_DESC
)
getTabPositionFromTabType(arguments?.getString(EntranceConsts.KEY_TARGET, EntranceConsts.TAB_TYPE_DESC) ?: EntranceConsts.TAB_TYPE_DESC)
// destinationTab 的优先级最高,关注和关联关注在它的后面
if (mDestinationTab != -1) {
@ -1014,32 +994,6 @@ class GameDetailFragment : BaseLazyFragment(), IScrollable {
}
}
/**
* 调用此方法时只是能获取game的包名还无法确认该游戏是否支持加速
* 所以这里只是提前加载加速所需的数据并不需要初始化加速相关的UI
*/
private fun loadAccelerationData(game: GameEntity) {
game.getApk().size
if (game.getApk().size == 1) {
// 单版本游戏才能支持加速(后台未对此作限制,所以需要在客户端判断)
val pkgName = game.getUniquePackageName() ?: ""
mViewModel.getLastSpeedLiveData(pkgName).observe(viewLifecycleOwner) {
acceleratorUiHelper.setCurrentAcctGameInfo(it)
}
mViewModel.getZoneListLiveData(pkgName).observe(viewLifecycleOwner) {
acceleratorUiHelper.setZoneList(it)
}
mViewModel.upsertAcctZoneListBeanAction.observe(viewLifecycleOwner) { (pkgName, zoneList) ->
mViewModel.upsertAcctZoneListBean(pkgName, zoneList)
}
mViewModel.loadAccelerationData(pkgName)
}
}
@SuppressLint("ClickableViewAccessibility")
private fun initViewPage(data: NewGameDetailEntity) {
// 各个 tab 显示的顺序为:详情>云存档>评价>专区>论坛
@ -1078,8 +1032,7 @@ class GameDetailFragment : BaseLazyFragment(), IScrollable {
mTabTitleList.clear()
val tag = "android:switcher:${mBodyBinding.gamedetailVp.id}:"
val descFragment =
childFragmentManager.findFragmentByTag("${tag}${EntranceConsts.TAB_TYPE_DESC}") ?: DescFragment()
val descFragment = childFragmentManager.findFragmentByTag("${tag}${EntranceConsts.TAB_TYPE_DESC}") ?: DescFragment()
descFragment.arguments = bundle
mFragmentsList.add(descFragment)
mTabTitleList.add(getString(R.string.game_detail_desc))
@ -1087,8 +1040,7 @@ class GameDetailFragment : BaseLazyFragment(), IScrollable {
if (data.showArchive) {
val cloudArchiveFragment =
childFragmentManager.findFragmentByTag("${tag}${EntranceConsts.TAB_TYPE_ARCHIVE}")
?: CloudArchiveFragment()
childFragmentManager.findFragmentByTag("${tag}${EntranceConsts.TAB_TYPE_ARCHIVE}") ?: CloudArchiveFragment()
bundle.putParcelable(EntranceConsts.KEY_GAME, mGameEntity ?: GameEntity())
bundle.putString(EntranceConsts.KEY_ARCHIVE_CONFIG_URL, data.archiveTab.configUrl)
cloudArchiveFragment.arguments = bundle
@ -1104,8 +1056,7 @@ class GameDetailFragment : BaseLazyFragment(), IScrollable {
}
if (data.showComment) {
val ratingFragment =
childFragmentManager.findFragmentByTag("${tag}${EntranceConsts.TAB_TYPE_RATING}") ?: RatingFragment()
val ratingFragment = childFragmentManager.findFragmentByTag("${tag}${EntranceConsts.TAB_TYPE_RATING}") ?: RatingFragment()
bundle.putBoolean(EntranceConsts.KEY_COMMENT_AS_DEFAULT_TAB, mSkipGameComment)
bundle.putBoolean(EntranceConsts.KEY_DIRECT_COMMENT, data.directComment)
ratingFragment.arguments = bundle
@ -1122,8 +1073,7 @@ class GameDetailFragment : BaseLazyFragment(), IScrollable {
mFragmentsList.add(Fragment())
} else if (it.style == "link") {
//显示web页面
val webFragment =
childFragmentManager.findFragmentByTag("${tag}${EntranceConsts.TAB_TYPE_TRENDS}") ?: WebFragment()
val webFragment = childFragmentManager.findFragmentByTag("${tag}${EntranceConsts.TAB_TYPE_TRENDS}") ?: WebFragment()
val webBundle = Bundle()
webBundle.putString(EntranceConsts.KEY_ENTRANCE, "游戏专区")
webBundle.putString(EntranceConsts.KEY_URL, it.link)
@ -1131,8 +1081,7 @@ class GameDetailFragment : BaseLazyFragment(), IScrollable {
webFragment.arguments = webBundle
mFragmentsList.add(webFragment)
} else {
val fuliFragment =
childFragmentManager.findFragmentByTag("${tag}${EntranceConsts.TAB_TYPE_TRENDS}") ?: FuLiFragment()
val fuliFragment = childFragmentManager.findFragmentByTag("${tag}${EntranceConsts.TAB_TYPE_TRENDS}") ?: FuLiFragment()
fuliFragment.arguments = bundle
mFragmentsList.add(fuliFragment)
}
@ -1232,8 +1181,7 @@ class GameDetailFragment : BaseLazyFragment(), IScrollable {
}
private fun doShowAlertDialog(dialog: GameEntity.Dialog) {
SensorsBridge.trackEvent(
"GameDetailDialogShow",
SensorsBridge.trackEvent("GameDetailDialogShow",
"game_id", mGameEntity?.id ?: "",
"game_name", mGameEntity?.name ?: "",
"game_type", mGameEntity?.categoryChinese ?: ""
@ -1245,8 +1193,7 @@ class GameDetailFragment : BaseLazyFragment(), IScrollable {
dialog.confirmButton.text.toString(),
dialog.closeButtonText,
{
SensorsBridge.trackEvent(
"GameDetailDialogClick",
SensorsBridge.trackEvent("GameDetailDialogClick",
"game_id", mGameEntity?.id ?: "",
"game_name", mGameEntity?.name ?: "",
"game_type", mGameEntity?.categoryChinese ?: "",
@ -1259,8 +1206,7 @@ class GameDetailFragment : BaseLazyFragment(), IScrollable {
DirectUtils.directToLinkPage(requireContext(), dialog.confirmButton, mEntrance, "")
},
{
SensorsBridge.trackEvent(
"GameDetailDialogClick",
SensorsBridge.trackEvent("GameDetailDialogClick",
"game_id", mGameEntity?.id ?: "",
"game_name", mGameEntity?.name ?: "",
"game_type", mGameEntity?.categoryChinese ?: "",
@ -1268,8 +1214,7 @@ class GameDetailFragment : BaseLazyFragment(), IScrollable {
)
},
{
SensorsBridge.trackEvent(
"GameDetailDialogClick",
SensorsBridge.trackEvent("GameDetailDialogClick",
"game_id", mGameEntity?.id ?: "",
"game_name", mGameEntity?.name ?: "",
"game_type", mGameEntity?.categoryChinese ?: "",
@ -1441,12 +1386,7 @@ class GameDetailFragment : BaseLazyFragment(), IScrollable {
mNewGameDetailEntity?.event?.let {
mBodyBinding.gameBigEvent.visibility = View.VISIBLE
if (it.highLight) {
mBodyBinding.gameBigEvent.setTextColor(
ContextCompat.getColor(
requireContext(),
com.gh.gamecenter.common.R.color.text_2A85FB
)
)
mBodyBinding.gameBigEvent.setTextColor(ContextCompat.getColor(requireContext(), com.gh.gamecenter.common.R.color.text_2A85FB))
mBodyBinding.gameBigEvent.background =
ContextCompat.getDrawable(requireContext(), R.drawable.bg_game_big_event_light)
mBodyBinding.gameBigEvent.setCompoundDrawablesWithIntrinsicBounds(
@ -1913,7 +1853,8 @@ class GameDetailFragment : BaseLazyFragment(), IScrollable {
requireContext(),
mGameEntity,
callback = getCallback(),
)
)
} else {
ReservationHelper.showCancelReservationDialog(requireContext(), mGameEntity) {
ReservationHelper.cancelReservation(mGameEntity!!) {
@ -2273,8 +2214,7 @@ class GameDetailFragment : BaseLazyFragment(), IScrollable {
pluginLocation = PluginLocation.only_game
)
val isLaunch = (status == getString(com.gh.gamecenter.feature.R.string.launch) || status == getString(
com.gh.gamecenter.feature.R.string.open
))
com.gh.gamecenter.feature.R.string.open))
if (SPUtils.getBoolean(
Constants.SP_SHOULD_SHOW_GAME_DETAIL_INSTALL_GUIDE,
false
@ -2434,9 +2374,6 @@ class GameDetailFragment : BaseLazyFragment(), IScrollable {
}
override fun onBackPressed(): Boolean {
if (acceleratorUiHelper.onBack()) {
return true
}
mOrientationUtils?.backToProtVideo()
val trendsTabPosition = getTabPositionFromTabType(EntranceConsts.TAB_TYPE_TRENDS)
@ -2497,11 +2434,6 @@ class GameDetailFragment : BaseLazyFragment(), IScrollable {
NewFlatLogUtils.logGameDetailExit(mGameEntity?.name ?: "", mGameEntity?.id ?: "")
}
override fun onDestroyView() {
acceleratorUiHelper.clear()
super.onDestroyView()
}
override fun onDestroy() {
super.onDestroy()
releaseVideo()
@ -2595,21 +2527,9 @@ class GameDetailFragment : BaseLazyFragment(), IScrollable {
// 更新分割线样式
updateDivider()
mBodyBinding.collapsingToolbar.setContentScrimColor(
com.gh.gamecenter.common.R.color.ui_surface.toColor(
requireContext()
)
)
mBodyBinding.gamedetailAppbar.setBackgroundColor(
com.gh.gamecenter.common.R.color.ui_surface.toColor(
requireContext()
)
)
mBodyBinding.toolbarGapView.setBackgroundColor(
com.gh.gamecenter.common.R.color.ui_background.toColor(
requireContext()
)
)
mBodyBinding.collapsingToolbar.setContentScrimColor(com.gh.gamecenter.common.R.color.ui_surface.toColor(requireContext()))
mBodyBinding.gamedetailAppbar.setBackgroundColor(com.gh.gamecenter.common.R.color.ui_surface.toColor(requireContext()))
mBodyBinding.toolbarGapView.setBackgroundColor(com.gh.gamecenter.common.R.color.ui_background.toColor(requireContext()))
mBodyBinding.gamedetailTvName.setTextColor(com.gh.gamecenter.common.R.color.text_primary.toColor(requireContext()))
mBodyBinding.gameBigEvent.background = R.drawable.bg_game_big_event.toDrawable(requireContext())
mBodyBinding.gameBigEvent.setTextColor(com.gh.gamecenter.common.R.color.text_tertiary.toColor(requireContext()))
@ -2621,11 +2541,7 @@ class GameDetailFragment : BaseLazyFragment(), IScrollable {
}
}
if (it is ImageView) {
if (mIsDarkModeOn) it.setColorFilter(
com.gh.gamecenter.common.R.color.text_primary.toColor(
requireContext()
)
) else it.colorFilter =
if (mIsDarkModeOn) it.setColorFilter(com.gh.gamecenter.common.R.color.text_primary.toColor(requireContext())) else it.colorFilter =
null
it.background = (it.background as GradientDrawable).apply {
setStroke(0.5F.dip2px(), Color.parseColor(if (mIsDarkModeOn) "#33FFFFFF" else "#CCCCCC"))
@ -2637,11 +2553,7 @@ class GameDetailFragment : BaseLazyFragment(), IScrollable {
val textView = tab.customView?.findViewById(R.id.tab_title) as? TextView ?: break
TextViewCompat.setTextAppearance(textView, com.gh.gamecenter.common.R.style.TabLayoutTextAppearance)
}
mBinding.detailLlBottom.detailLlBottom.setBackgroundColor(
com.gh.gamecenter.common.R.color.ui_background.toColor(
requireContext()
)
)
mBinding.detailLlBottom.detailLlBottom.setBackgroundColor(com.gh.gamecenter.common.R.color.ui_background.toColor(requireContext()))
updateToolbarStyle(!mViewModel.displayTopVideo || mBodyBinding.gamedetailThumbSmall.visibility == View.VISIBLE)
mViewModel.gameDetailLiveData.value?.data?.let {
if (it.isShowContentCard(mGameEntity)) {
@ -2674,7 +2586,6 @@ class GameDetailFragment : BaseLazyFragment(), IScrollable {
* 3. 当前游戏 APK 不为 1 个
* 4. 当前游戏类型不为畅玩
* 5. 当前游戏不是双下载时使用本地下载进行下载
* 6. 当前游戏配置了网络加速
*/
private fun isSpecialDownloadDialogAvailable(downloadEntity: DownloadEntity? = null): Boolean {
if (Config.getNewApiSettingsEntity()?.install?.questionTip?.linkEntity == null) return false
@ -2683,7 +2594,6 @@ class GameDetailFragment : BaseLazyFragment(), IScrollable {
if (downloadEntity?.asVGame() == true) return false
if (downloadEntity?.isSimulatorGame() == true) return false
if (downloadEntity?.isLocalDownloadInDualDownloadMode() == true) return false
if (mGameEntity?.canSpeed == true) return false
return true
}

View File

@ -5,10 +5,14 @@ import android.app.Application
import android.net.Uri
import android.os.Build
import android.text.TextUtils
import androidx.lifecycle.*
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import com.gh.common.filter.RegionSettingHelper
import com.gh.common.history.HistoryHelper
import com.gh.common.util.CheckLoginUtils
import com.gh.gamecenter.feature.utils.ConcernUtils
import com.gh.common.util.LibaoUtils
import com.gh.common.util.PackageHelper
import com.gh.gamecenter.common.constant.Constants
@ -16,53 +20,28 @@ import com.gh.gamecenter.common.mvvm.Resource
import com.gh.gamecenter.common.retrofit.BiResponse
import com.gh.gamecenter.common.retrofit.Response
import com.gh.gamecenter.common.utils.singleToMain
import com.gh.gamecenter.common.utils.toArrayList
import com.gh.gamecenter.common.utils.toRequestBody
import com.gh.gamecenter.core.provider.IAcceleratorProvider
import com.gh.gamecenter.core.utils.GsonUtils
import com.gh.gamecenter.core.utils.SPUtils
import com.gh.gamecenter.core.utils.UrlFilterUtils
import com.gh.gamecenter.entity.RecommendPopupEntity
import com.gh.gamecenter.entity.UnifiedUserTrendEntity
import com.gh.gamecenter.feature.entity.*
import com.gh.gamecenter.entity.*
import com.gh.gamecenter.feature.entity.GameEntity
import com.gh.gamecenter.feature.entity.LibaoEntity
import com.gh.gamecenter.feature.entity.LibaoStatusEntity
import com.gh.gamecenter.feature.entity.SimpleGame
import com.gh.gamecenter.feature.utils.ApkActiveUtils
import com.gh.gamecenter.feature.utils.ConcernUtils
import com.gh.gamecenter.feature.utils.ContentBlockedHelper
import com.gh.gamecenter.gamedetail.accelerator.AccelerationDataBase
import com.gh.gamecenter.gamedetail.entity.BigEvent
import com.gh.gamecenter.gamedetail.entity.CustomColumn
import com.gh.gamecenter.gamedetail.entity.DetailEntity
import com.gh.gamecenter.gamedetail.entity.NewGameDetailEntity
import com.gh.gamecenter.gamedetail.entity.*
import com.gh.gamecenter.login.user.UserManager
import com.gh.gamecenter.login.user.UserRepository
import com.gh.gamecenter.retrofit.RetrofitManager
import com.halo.assistant.HaloApp
import com.halo.assistant.member.MemberUseCase
import com.therouter.TheRouter
import io.reactivex.Single
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.schedulers.Schedulers
import okhttp3.ResponseBody
import org.json.JSONObject
import retrofit2.HttpException
import tv.danmaku.ijk.media.exo2.ExoSourceManager
import java.util.*
import java.util.concurrent.TimeUnit
import kotlin.collections.ArrayList
import kotlin.collections.List
import kotlin.collections.arrayListOf
import kotlin.collections.find
import kotlin.collections.firstOrNull
import kotlin.collections.forEach
import kotlin.collections.forEachIndexed
import kotlin.collections.hashMapOf
import kotlin.collections.isNotEmpty
import kotlin.collections.isNullOrEmpty
import kotlin.collections.removeAll
import kotlin.collections.set
import kotlin.collections.sortByDescending
import kotlin.collections.withIndex
class GameDetailViewModel(
application: Application,
@ -90,10 +69,6 @@ class GameDetailViewModel(
var videoIsMuted = SPUtils.getBoolean(Constants.SP_VIDEO_PLAY_MUTE, true)
var displayTopVideo: Boolean = false
private val compositeDisposable = CompositeDisposable()
val memberUseCase = MemberUseCase()
init {
loadData()
}
@ -110,17 +85,9 @@ class GameDetailViewModel(
getGameDetailNew()
getRecommendPopup(game?.id ?: "")
}
gameId != null -> getGameDigest()
else -> gameLiveData.postValue(null)
}
val userId = UserManager.getInstance().userId
if (userId.isNotBlank()) {
// 如果是登录状态获取最新的vip状态
UserRepository.getInstance().refreshVipStatus(userId, false)
}
}
// 获取游戏摘要
@ -195,11 +162,6 @@ class GameDetailViewModel(
.observeOn(AndroidSchedulers.mainThread())
.subscribe(object : BiResponse<NewGameDetailEntity>() {
override fun onSuccess(data: NewGameDetailEntity) {
game?.acceleratorStatus = data.acceleratorStatus
if (game?.canSpeed == true) {
// 此游戏支持加速
pkgName.value = game?.getUniquePackageName() ?: ""
}
if (data.newNotice != null) {
// 存在new_notice字段时移除detail_tab里面type=notice的项并添加new_notice到detail_tab
var noticePosition = -1
@ -697,66 +659,6 @@ class GameDetailViewModel(
})
}
fun getLastSpeedLiveData(pkgName: String) =
AccelerationDataBase.instance.accelerationDao().findByPackageName(pkgName)
fun getZoneListLiveData(pkgName: String) =
AccelerationDataBase.instance.accelerationDao().findZoneListBeanByPkgName(pkgName)
.map {
it?.acctGameList?.toArrayList()
}
private val zoneList = MutableLiveData<List<AcctGameInfo>>()
private val pkgName = MutableLiveData<String>()
val upsertAcctZoneListBeanAction = MediatorLiveData<Pair<String, List<AcctGameInfo>>>().apply {
addSource(zoneList) {
val pkgNameValue = pkgName.value
if (!pkgNameValue.isNullOrBlank()) {
value = pkgNameValue to it
}
}
addSource(pkgName) {
val zoneListValue = zoneList.value
if (zoneListValue != null) {
value = it to zoneListValue
}
}
}
fun loadAccelerationData(pkgName: String) {
Single.create<ArrayList<AcctGameInfo>> { emitter ->
val iAcceleratorProvider = TheRouter.get(IAcceleratorProvider::class.java)
iAcceleratorProvider?.loadQyGameZoneData(pkgName) {
val zoneData = (it as List<AcctGameInfo>).toArrayList()
emitter.onSuccess(zoneData)
} ?: emitter.onSuccess(arrayListOf())
}.timeout(5, TimeUnit.SECONDS)
.doOnSuccess {
zoneList.value = it
}
.subscribe({}, {}).let(compositeDisposable::add)
}
/**
* 只有能够加速的游戏需要保存区服信息
*/
@SuppressLint("CheckResult")
fun upsertAcctZoneListBean(pkgName: String, zoneList: List<AcctGameInfo>) {
AccelerationDataBase.instance.accelerationDao()
.upsertAcctZoneListBean(AcctZoneListBean(pkgName, zoneList))
.compose(singleToMain())
.subscribe({}, {})
}
override fun onCleared() {
super.onCleared()
compositeDisposable.clear()
memberUseCase.onClear()
}
class Factory(
private val mApplication: Application,
private val gameId: String?,

View File

@ -1,76 +0,0 @@
package com.gh.gamecenter.gamedetail
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import com.gh.gamecenter.common.retrofit.BiResponse
import com.gh.gamecenter.common.utils.singleToMain
import com.gh.gamecenter.core.provider.IAcceleratorProvider
import com.gh.gamecenter.feature.entity.BaseEntity
import com.gh.gamecenter.feature.entity.TrialEntity
import com.gh.gamecenter.feature.entity.VipEntity
import com.gh.gamecenter.livedata.Event
import com.gh.gamecenter.login.user.UserManager
import com.gh.gamecenter.login.user.UserRepository
import com.halo.assistant.member.MemberUseCase
import com.therouter.TheRouter
import io.reactivex.disposables.CompositeDisposable
class StartingAcceleratorViewModel : ViewModel() {
private val compositeDisposable = CompositeDisposable()
val useCase = MemberUseCase()
private val _restartingAcceleratorAction = MutableLiveData<Event<Boolean>>()
val restartingAcceleratorAction: LiveData<Event<Boolean>> = _restartingAcceleratorAction
fun loadAcceleratorToken() {
val userId = UserManager.getInstance().userId
if (userId.isNotBlank()) {
UserRepository.getInstance().setAcceleratorToken(userId) {
_restartingAcceleratorAction.value = Event(it)
}
}
}
private val _rechargeTrailResult = MutableLiveData<Event<Boolean>>()
val rechargeTrailResult: LiveData<Event<Boolean>> = _rechargeTrailResult
fun rechargeTrial() {
val userId = UserManager.getInstance().userId
useCase.rechargeTrial(userId)
.compose(singleToMain())
.subscribe(object : BiResponse<BaseEntity<TrialEntity>>() {
override fun onSuccess(data: BaseEntity<TrialEntity>) {
if (data.data?.result == true) {
// 刷新vip状态
// 这里先刷新内存数据再去刷新api数据
TheRouter.get(IAcceleratorProvider::class.java)?.setVipEntity(
VipEntity(
_vipStatus = true,
_isNewUser = false,
_isTryVip = true
)
)
refreshVipStatus(userId)
_rechargeTrailResult.value = Event(true)
} else {
_rechargeTrailResult.value = Event(false)
}
}
override fun onFailure(exception: Exception) {
super.onFailure(exception)
_rechargeTrailResult.value = Event(false)
}
}).let(compositeDisposable::add)
}
private fun refreshVipStatus(userId: String) {
UserRepository.getInstance().refreshVipStatus(userId, true)
}
override fun onCleared() {
super.onCleared()
compositeDisposable.clear()
}
}

View File

@ -1,35 +0,0 @@
package com.gh.gamecenter.gamedetail.accelerator
import android.content.Context
import androidx.room.Database
import androidx.room.Room
import androidx.room.RoomDatabase
import androidx.room.TypeConverters
import com.gh.gamecenter.feature.entity.AcctGameInfo
import com.gh.gamecenter.feature.entity.AcctZoneListBean
import com.gh.gamecenter.room.converter.AcctGameInfoConverter
import com.halo.assistant.HaloApp
@Database(
entities = [AcctGameInfo::class, AcctZoneListBean::class],
version = 1,
exportSchema = false
)
@TypeConverters(
AcctGameInfoConverter::class
)
abstract class AccelerationDataBase : RoomDatabase() {
abstract fun accelerationDao(): AcceleratorDao
companion object {
private const val DATABASE_NAME: String = "acceleration_db"
val instance: AccelerationDataBase by lazy { buildDatabase(HaloApp.getInstance().application) }
private fun buildDatabase(context: Context): AccelerationDataBase {
return Room.databaseBuilder(context, AccelerationDataBase::class.java, DATABASE_NAME)
.build()
}
}
}

View File

@ -1,25 +0,0 @@
package com.gh.gamecenter.gamedetail.accelerator
import androidx.lifecycle.LiveData
import androidx.room.Dao
import androidx.room.Query
import androidx.room.Upsert
import com.gh.gamecenter.feature.entity.AcctGameInfo
import com.gh.gamecenter.feature.entity.AcctZoneListBean
import io.reactivex.Single
@Dao
interface AcceleratorDao {
@Upsert
fun upsertAcctGameInfo(gameInfo: AcctGameInfo): Single<Long>
@Query("SELECT * FROM AcctGameInfo WHERE accGamePkgName = :pkgName")
fun findByPackageName(pkgName: String): LiveData<AcctGameInfo?>
@Upsert
fun upsertAcctZoneListBean(acctZoneListBean: AcctZoneListBean): Single<Long>
@Query("SELECT * FROM AcctZoneListBean WHERE pkgName = :pkgName")
fun findZoneListBeanByPkgName(pkgName: String): LiveData<AcctZoneListBean?>
}

View File

@ -1,182 +0,0 @@
package com.gh.gamecenter.gamedetail.accelerator
import android.app.Activity
import android.content.Context
import android.graphics.*
import android.util.AttributeSet
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.FrameLayout
import androidx.core.view.updateLayoutParams
import com.gh.gamecenter.common.utils.dip2px
import com.gh.gamecenter.common.utils.toColor
import com.gh.gamecenter.core.AppExecutor
import com.gh.gamecenter.databinding.LayoutAcceleratorGuidePageBinding
class AcceleratorGuideView @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
def: Int = 0
) : FrameLayout(context, attrs, def) {
private val binding: LayoutAcceleratorGuidePageBinding
private val rect = Rect()
private var _isShowing = false
val isShowing: Boolean
get() = _isShowing
private var isCanDismiss = false
private val guideBackgroundColor =
com.gh.gamecenter.common.R.color.black_alpha_60.toColor(context)
private val xfermode by lazy {
val mode = PorterDuff.Mode.CLEAR
PorterDuffXfermode(mode)
}
private val paint by lazy {
Paint().apply {
color = Color.YELLOW
isAntiAlias = true
isDither = true
}
}
private var onStartSpeed: (() -> Unit)? = null
init {
val inflater = LayoutInflater.from(context)
binding = LayoutAcceleratorGuidePageBinding.inflate(inflater, this, true)
binding.root.setOnClickListener {
// 点击透明区域消失
dismiss()
}
binding.clContainer.setOnClickListener {
//覆盖外部点击事件,点击此区域 guideView 不消失
}
binding.vIKnow.setOnClickListener {
dismiss()
}
binding.vSpeed.setOnClickListener {
dismiss()
onStartSpeed?.invoke()
}
}
override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) {
super.onLayout(changed, left, top, right, bottom)
val bottom = rect.bottom
val top = bottom - binding.clContainer.height
val right = rect.right + BORDER_WIDTH.dip2px()
val left = right - binding.clContainer.width
binding.clContainer.layout(left, top, right, bottom)
}
override fun dispatchDraw(canvas: Canvas) {
val saveCount = canvas.saveLayer(0f, 0f, width.toFloat(), height.toFloat(), paint)
paint.color = guideBackgroundColor
canvas.drawRect(0f, 0f, width.toFloat(), height.toFloat(), paint)
onDrawDecoration(canvas)
paint.xfermode = xfermode
canvas.drawRoundRect(
RectF(rect),
HIGH_LIGHT_RADIUS.dip2px().toFloat(),
HIGH_LIGHT_RADIUS.dip2px().toFloat(),
paint
)
paint.xfermode = null
canvas.restoreToCount(saveCount)
super.dispatchDraw(canvas)
}
private fun onDrawDecoration(canvas: Canvas) {
paint.color = com.gh.gamecenter.common.R.color.ui_surface.toColor(context)
val border = BORDER_WIDTH.dip2px()
val radius = HIGH_LIGHT_RADIUS.dip2px().toFloat()
val dRectF = RectF(
rect.left.toFloat() - border,
rect.top.toFloat() - border,
rect.right.toFloat() + border,
rect.bottom.toFloat() + border
)
canvas.drawRoundRect(dRectF, radius, radius, paint)
}
private fun setHighLightRect(newRect: Rect) {
rect.set(newRect)
binding.vSpeed.updateLayoutParams {
width = rect.width()
}
}
fun show(anchor: View, activity: Activity, block: () -> Unit) {
onStartSpeed = block
val newRect = getLocationInWindow(anchor)
val content = activity.window.decorView as ViewGroup
layoutParams = ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT
)
setHighLightRect(newRect)
content.addView(this)
setOnClickListener {
if (isCanDismiss) {
dismiss()
}
}
setOnClickListener {
}
_isShowing = true
isCanDismiss = false
AppExecutor.uiExecutor.executeWithDelay({
isCanDismiss = true
}, SHOW_MIN_DURATION)
}
fun dismiss() {
(parent as? ViewGroup)?.removeView(this)
_isShowing = false
onDismissListener?.invoke()
}
private var onDismissListener: (() -> Unit)? = null
fun setDismissListener(listener: () -> Unit) {
onDismissListener = listener
}
private fun getLocationInWindow(anchor: View): Rect {
val result = Rect()
val pos = IntArray(2)
anchor.getLocationInWindow(pos)
result.left = pos[0]
result.top = pos[1]
result.right = result.left + anchor.width
result.bottom = result.top + anchor.height
return result
}
companion object {
private const val BORDER_WIDTH = 4F
private const val HIGH_LIGHT_RADIUS = 100F
private const val SHOW_MIN_DURATION = 500L
}
}

View File

@ -1,401 +0,0 @@
package com.gh.gamecenter.gamedetail.accelerator
import android.content.Context
import android.view.ViewGroup
import androidx.appcompat.app.AppCompatActivity
import com.gh.common.util.CheckLoginUtils
import com.gh.common.util.PackageLauncher
import com.gh.gamecenter.R
import com.gh.gamecenter.common.constant.Constants
import com.gh.gamecenter.common.utils.*
import com.gh.gamecenter.core.callback.AccelerateState
import com.gh.gamecenter.core.callback.OnAccelerateListener
import com.gh.gamecenter.core.provider.IAcceleratorProvider
import com.gh.gamecenter.core.utils.SPUtils
import com.gh.gamecenter.core.utils.ToastUtils
import com.gh.gamecenter.databinding.DetailDownloadItemBinding
import com.gh.gamecenter.feature.entity.AcctGameInfo
import com.gh.gamecenter.feature.entity.GameEntity
import com.gh.gamecenter.gamedetail.accelerator.chain.*
import com.gh.gamecenter.gamedetail.accelerator.dialog.AcceleratorDialogFragment
import com.gh.gamecenter.gamedetail.accelerator.dialog.AcceleratorDialogFragment.Companion.SPEED_STOP
import com.gh.gamecenter.gamedetail.accelerator.dialog.AcceleratorZoneDialogFragment
import com.gh.gamecenter.gamedetail.accelerator.dialog.StartingAcceleratorDialogFragment
import com.halo.assistant.member.MemberRepository
import com.therouter.TheRouter
class GameDetailAcceleratorUiHelper(private val binding: DetailDownloadItemBinding) {
private var iAcceleratorProvider = TheRouter.get(IAcceleratorProvider::class.java)
private var guideView: AcceleratorGuideView? = null
val isGuideLayerShowing: Boolean
get() = guideView?.isShowing ?: false
private val zoneList = arrayListOf<AcctGameInfo>()
private var hasZoneListLoaded = false
private var _last: AcctGameInfo? = null
val last: AcctGameInfo?
get() = _last
private val hasMultiZone: Boolean
get() = zoneList.size > 1
private val hasZone: Boolean
get() = zoneList.isNotEmpty()
private val isVip: Boolean
get() = iAcceleratorProvider?.isVip() ?: false
val isNewUser: Boolean
get() = iAcceleratorProvider?.isNewUser() ?: false
private var canSpeed = false
var showSpeedUi = false
private var _game: GameEntity? = null
fun setGame(game: GameEntity?) {
_game = game
}
private val accelerationListener = object : OnAccelerateListener {
override fun onStateChanged(state: AccelerateState) {
when (state) {
is AccelerateState.Success -> {
_game?.let {
val acctGameInfo = state.acctGameInfo
if (acctGameInfo is AcctGameInfo) {
setCurrentAcctGameInfo(acctGameInfo)
}
updateSpeedUi()
}
}
is AccelerateState.Normal -> {
if (!state.isTokenExpired) {
updateSpeedUi()
}
}
else -> Unit
}
}
override fun onProgress(progress: Int, curGamePkgName: String?, curGameZoneFlag: String?) = Unit
override fun onVipStatusChanged(isNewUser: Boolean, isVip: Boolean) {
binding.ivFreeVipTag.visibleIf(
showSpeedUi &&
CheckLoginUtils.isLogin() &&
isNewUser &&
!isGuideLayerShowing
)
}
}
fun initSpeedUi(context: Context) {
canSpeed = true
_game?.let {
iAcceleratorProvider?.bindAccRelatedListener(it.getUniquePackageName() ?: "", accelerationListener)
}
binding.vSpeedContent.setOnClickListener {
_game?.let { game ->
checkDataReady {
startAccelerating(context, game, false)
}
}
}
binding.vMoreZone.setOnClickListener {
_game?.let { game ->
checkDataReady {
showZoneList(context, game)
}
}
}
binding.tvStopSpeed.setOnClickListener {
_game?.let {
SensorsBridge.trackNetworkAccelerationOtherButtonClick(
it.getUniquePackageName() ?: "",
it.id,
it.name ?: "",
iAcceleratorProvider?.getMemberType() ?: "",
BUTTON_NAME_STOP_ACCELERATOR,
SOURCE_ENTRANCE_GAME_DETAIL
)
AcceleratorDialogFragment.show(
SPEED_STOP, it.getUniquePackageName() ?: "", it.id, it.name ?: "",
SOURCE_ENTRANCE_GAME_DETAIL, context
)
}
}
binding.tvEnterGame.setOnClickListener {
_game?.let { game ->
SensorsBridge.trackNetworkAccelerationOtherButtonClick(
game.getUniquePackageName() ?: "",
game.id,
game.name ?: "",
iAcceleratorProvider?.getMemberType() ?: "",
BUTTON_NAME_ENTER_GAME,
SOURCE_ENTRANCE_GAME_DETAIL
)
PackageLauncher.launchApp(context, game, game.getUniquePackageName())
}
}
updateSpeedUi()
}
fun updateSpeedUi() {
if (!showSpeedUi) {
return
}
val hasGameBeingAccelerated = iAcceleratorProvider?.isCurAccSuccess() ?: false
val isCurAccSuccess = hasGameBeingAccelerated &&
MemberRepository.instance.acctGameRecord.gameId == (_game?.id ?: "")
binding.detailProgressbar.goneIf(isCurAccSuccess)
binding.clSpeed.goneIf(isCurAccSuccess)
binding.gAccelerating.goneIf(!isCurAccSuccess)
binding.gMoreZone.goneIf(!hasMultiZone)
binding.ivFreeVipTag.visibleIf(
showSpeedUi &&
CheckLoginUtils.isLogin() &&
isNewUser &&
!isGuideLayerShowing
)
binding.tvSpeed.text = if (hasMultiZone) {
last?.zoneName
} else {
null
} ?: R.string.network_acceleration.toResString()
}
/**
* 在这个方法里确定是否需要展示 加速ui
* 当 clSpeedContainer没有显示时调用updateSpeedUi()无效,可以调用initSpeedUi()
* 请注意,只要是 gameDetail 发生变化,这里就会回调,所以当 canSpeed 确定之后,这里最少还会回调一次
*/
fun checkIfShowGuideLayer(context: Context) {
showSpeedUi = canSpeed
binding.clSpeedContainer.goneIf(!showSpeedUi) {
// canSpeed =true 说明detail接口已完成
binding.detailProgressbar.setBackgroundResource(com.gh.gamecenter.common.R.drawable.bg_common_button_light_fill_blue)
binding.detailProgressbar.setTextColor(com.gh.gamecenter.common.R.color.text_theme.toColor(context))
updateSpeedUi()
if (CheckLoginUtils.isLogin()) {
if (!hasShow()) {
// 优先显示弹窗
binding.ivFreeVipTag.visibleIf(false)
showGuideLayer(context)
}
} else {
// 未登录
binding.ivFreeVipTag.visibleIf(false)
showGuideLayer(context)
}
}
}
private fun showGuideLayer(context: Context) {
if (!hasShow()) {
binding.root.post {
val uiListener = object : OnAcceleratorListener {
override fun onStartAccelerator() {
_game?.let {
startAccelerating(context, it, true)
}
}
override fun onGuideLayerDismiss() {
binding.ivFreeVipTag.visibleIf(CheckLoginUtils.isLogin() && hasZone && isNewUser)
}
}
SPUtils.setBoolean(Constants.SP_HAS_SHOW_ACCELERATION_GUIDE_LAYER, true)
if (guideView == null) {
guideView = AcceleratorGuideView(context).apply {
setDismissListener(uiListener::onGuideLayerDismiss)
}
}
(guideView?.parent as? ViewGroup)?.removeView(guideView)
if (context is AppCompatActivity) {
_game?.let {
SensorsBridge.trackNetworkAccelerationGuidanceDiagramShow(
it.getUniquePackageName() ?: "",
it.id,
it.name ?: ""
)
}
guideView?.show(binding.clSpeedContainer, context, uiListener::onStartAccelerator)
}
}
}
}
fun onBack(): Boolean {
val isShowing = guideView?.isShowing ?: false
if (isShowing) {
guideView?.dismiss()
return true
} else {
return false
}
}
private fun hasShow(): Boolean {
return SPUtils.getBoolean(Constants.SP_HAS_SHOW_ACCELERATION_GUIDE_LAYER)
}
private fun startAccelerating(context: Context, game: GameEntity, isShowing: Boolean) {
if (isInvalidClick() || !hasZone) {
return
}
val lastAcctGameInfo = last
val memberType = if (CheckLoginUtils.isLogin()) {
iAcceleratorProvider?.getMemberType() ?: ""
} else {
MEMBER_TYPE_NOT_LOGIN
}
val districtServer = when {
hasMultiZone && lastAcctGameInfo != null -> lastAcctGameInfo.zoneName
hasMultiZone -> DISTRICT_SERVER_EMPTY
else -> DISTRICT_SERVER_HAVA
}
SensorsBridge.trackNetworkAccelerationButtonClick(
game.getUniquePackageName() ?: "",
game.id,
game.name ?: "",
memberType,
districtServer,
if (isShowing) SCENE_TYPE_HAVE_GUIDE_LAYER else SCENE_TYPE_NO_GUIDE_LAYER,
SOURCE_ENTRANCE_GAME_DETAIL
)
when {
lastAcctGameInfo != null ->
doStartAccelerating(context, game, lastAcctGameInfo)
hasMultiZone -> AcceleratorZoneDialogFragment.show(context, zoneList, game)
else -> {
val gameInfo = zoneList.firstOrNull() ?: AcctGameInfo("", AcctGameInfo.ZoneInfo(0))
doStartAccelerating(context, game, gameInfo)
}
}
}
private fun showZoneList(context: Context, game: GameEntity) {
if (isInvalidClick() || !hasZone) {
return
}
AcceleratorZoneDialogFragment.show(context, zoneList, game)
}
private var clickTime = 0L
private fun doStartAccelerating(context: Context, game: GameEntity, acctGameInfo: AcctGameInfo) {
val request = AcceleratorValidator.Request(isVip, isNewUser, game, SOURCE_ENTRANCE_GAME_DETAIL)
AcceleratorClient.newInstance()
.execute(context, request, object : AcceleratorValidator.ValidateListener {
override fun finished(context: Context) {
StartingAcceleratorDialogFragment.show(
context, acctGameInfo, game, true, hasMultiZone,
SOURCE_ENTRANCE_GAME_DETAIL,
)
}
})
}
fun setCurrentAcctGameInfo(acctGameInfo: AcctGameInfo?) {
_last = acctGameInfo
if (hasZoneListLoaded) {
updateSpeedUi()
}
}
/**
* 第一次调用 setZoneList 是使用缓存中的数据
* 第二次调用是使用sdk中的最新数据
* 这里优先使用缓存中的sdk中的数据更新到数据库后待下次进入详情页在显示
* 当zoneList为null时说明磁盘上没有数据这时候使用sdk中的
*
*/
fun setZoneList(newZoneList: ArrayList<AcctGameInfo>?) {
if (newZoneList != null && zoneList.isEmpty()) {
hasZoneListLoaded = true
zoneList.clear()
zoneList.addAll(newZoneList)
updateSpeedUi()
}
}
private fun isInvalidClick(): Boolean {
// 300ms内只能调用一次
val currentTime = System.currentTimeMillis()
val difTime = currentTime - clickTime
if (difTime <= CLICK_DURATION) {
return true
}
clickTime = currentTime
return false
}
private fun checkDataReady(block: () -> Unit) {
when {
!hasZoneListLoaded -> {
ToastUtils.showToast("区服信息正在加载中,请稍后再试!")
}
zoneList.isEmpty() -> {
ToastUtils.showToast("区服信息加载失败,请稍后再试!")
}
else -> {
block()
}
}
}
fun clear() {
iAcceleratorProvider?.unBindAccRelatedListener(accelerationListener)
guideView?.dismiss()
}
companion object {
private const val CLICK_DURATION = 300
const val MEMBER_TYPE_NOT_LOGIN = "未登录"
private const val DISTRICT_SERVER_EMPTY = ""
const val DISTRICT_SERVER_HAVA = ""
private const val SCENE_TYPE_HAVE_GUIDE_LAYER = "有引导图"
const val SCENE_TYPE_NO_GUIDE_LAYER = "无引导图"
const val SOURCE_ENTRANCE_GAME_DETAIL = "游戏详情页"
const val SOURCE_ENTRANCE_MY_ASSETS = "我的资产"
const val BUTTON_NAME_ENTER_GAME = "进入游戏"
const val BUTTON_NAME_STOP_ACCELERATOR = "停止加速"
}
interface OnAcceleratorListener {
fun onStartAccelerator()
fun onGuideLayerDismiss()
}
}

View File

@ -1,54 +0,0 @@
package com.gh.gamecenter.gamedetail.accelerator
import android.content.Context
import com.gh.common.util.NewLogUtils
import com.gh.gamecenter.R
import com.gh.gamecenter.ShellActivity
import com.gh.gamecenter.common.constant.EntranceConsts
import com.gh.gamecenter.common.utils.DialogHelper
import com.gh.gamecenter.common.utils.SensorsBridge
import com.gh.gamecenter.common.utils.toResString
/**
* 会员功能 实名认证相关弹窗
*/
object UserVerifyDialogUtils {
fun showUnVerifiedDialog(context: Context, title: String, content: String) {
DialogHelper.showDialog(
context,
title = title,
content = content,
confirmText = R.string.go_to_real_name_authentication.toResString(),
cancelText = "取消",
confirmClickCallback = {
context.startActivity(
ShellActivity.getIntent(
context,
ShellActivity.Type.REAL_NAME_INFO
).apply {
putExtra(EntranceConsts.KEY_SOURCE_ENTRANCE, "游戏实名")
putExtra(EntranceConsts.KEY_IS_FORCED_TO_CERTIFICATE, true)
}
)
NewLogUtils.logCertificationHintDialogOptionsClicked("前往实名认证")
SensorsBridge.trackVerificationPopupClick("前往实名认证")
},
cancelClickCallback = {
NewLogUtils.logCertificationHintDialogOptionsClicked("取消")
SensorsBridge.trackVerificationPopupClick("取消")
}
)
}
fun showMinorsOrVerifyingDialog(context: Context, title: String, content: String) {
DialogHelper.showDialog(
context,
title = title,
content = content,
confirmText = R.string.dialog_hint_confirm.toResString(),
cancelText = "",
)
}
}

View File

@ -1,28 +0,0 @@
package com.gh.gamecenter.gamedetail.accelerator.chain
import android.content.Context
import com.gh.common.util.PackageUtils
import com.gh.gamecenter.gamedetail.accelerator.dialog.AcceleratorDialogFragment
import com.gh.gamecenter.gamedetail.accelerator.dialog.AcceleratorDialogFragment.Companion.SPEED_NOT_INSTALLED
class AcceleratorCheckInstallInterceptor : AcceleratorValidator.Interceptor {
override fun intercept(
context: Context,
chain: AcceleratorValidator.Chain,
listener: AcceleratorValidator.ValidateListener?
) {
val request = chain.request
if (PackageUtils.isInstalled(context, request.game.getUniquePackageName() ?: "")) {
chain.proceed(context, request, listener)
} else {
val game = request.game
AcceleratorDialogFragment.show(
SPEED_NOT_INSTALLED,
game.getUniquePackageName() ?: "",
game.id,
game.name ?: "",
request.sourceEntrance, context
)
}
}
}

View File

@ -1,29 +0,0 @@
package com.gh.gamecenter.gamedetail.accelerator.chain
import android.content.Context
class AcceleratorClient(
private vararg val interceptors: AcceleratorValidator.Interceptor,
) {
fun execute(
context: Context,
request: AcceleratorValidator.Request,
listener: AcceleratorValidator.ValidateListener
) {
val chain = RealAcceleratorInterceptorChain(interceptors.toList(), 0, request)
chain.proceed(context, request, listener)
}
companion object {
fun newInstance() = AcceleratorClient(
AcceleratorCheckInstallInterceptor(),
AcceleratorLoginInterceptor(),
AcceleratorPackageCheckInterceptor(),
AcceleratorRealNameInterceptor(),
AcceleratorVipInterceptor(),
AcceleratorStateInterceptor()
)
}
}

View File

@ -1,18 +0,0 @@
package com.gh.gamecenter.gamedetail.accelerator.chain
import android.content.Context
import com.gh.gamecenter.common.utils.ifLogin
class AcceleratorLoginInterceptor : AcceleratorValidator.Interceptor {
override fun intercept(
context: Context,
chain: AcceleratorValidator.Chain,
listener: AcceleratorValidator.ValidateListener?
) {
context.ifLogin("[网络加速]") {
val request = chain.request
chain.proceed(context, request, listener)
}
}
}

View File

@ -1,20 +0,0 @@
package com.gh.gamecenter.gamedetail.accelerator.chain
import android.content.Context
import androidx.appcompat.app.AppCompatActivity
import com.gh.common.dialog.PackageCheckDialogFragment
class AcceleratorPackageCheckInterceptor : AcceleratorValidator.Interceptor {
override fun intercept(
context: Context,
chain: AcceleratorValidator.Chain,
listener: AcceleratorValidator.ValidateListener?
) {
val request = chain.request
if (context is AppCompatActivity) {
PackageCheckDialogFragment.show(context, request.game) {
chain.proceed(context, request, listener)
}
}
}
}

View File

@ -1,26 +0,0 @@
package com.gh.gamecenter.gamedetail.accelerator.chain
import android.content.Context
import com.gh.common.util.TempCertificationUtils
import com.gh.gamecenter.R
import com.gh.gamecenter.common.utils.toResString
import com.gh.gamecenter.gamedetail.accelerator.UserVerifyDialogUtils
class AcceleratorRealNameInterceptor : AcceleratorValidator.Interceptor {
override fun intercept(
context: Context,
chain: AcceleratorValidator.Chain,
listener: AcceleratorValidator.ValidateListener?
) {
val request = chain.request
if (TempCertificationUtils.isUserVerified()) {
chain.proceed(context, request, listener)
} else {
UserVerifyDialogUtils.showUnVerifiedDialog(
context,
R.string.real_name_tips.toResString(),
R.string.acceleration_service_without_real_name_description.toResString()
)
}
}
}

View File

@ -1,37 +0,0 @@
package com.gh.gamecenter.gamedetail.accelerator.chain
import android.content.Context
import com.gh.gamecenter.core.provider.IAcceleratorProvider
import com.gh.gamecenter.gamedetail.accelerator.dialog.AcceleratorReplaceDialogFragment
import com.therouter.TheRouter
class AcceleratorStateInterceptor : AcceleratorValidator.Interceptor {
override fun intercept(
context: Context,
chain: AcceleratorValidator.Chain,
listener: AcceleratorValidator.ValidateListener?
) {
val request = chain.request
val iAcceleratorProvider = TheRouter.get(IAcceleratorProvider::class.java)
val isAccelerating = iAcceleratorProvider?.isCurAccSuccess() ?: false
if (isAccelerating) {
val game = request.game
AcceleratorReplaceDialogFragment.show(
context,
game.getUniquePackageName() ?: "",
game.id,
game.name ?: "",
request.sourceEntrance
) {
if (chain.isValidContext(context)) {
listener?.finished(context)
}
}
} else {
chain.proceed(context, request, listener)
}
}
}

View File

@ -1,71 +0,0 @@
package com.gh.gamecenter.gamedetail.accelerator.chain
import android.content.Context
import android.os.Parcelable
import androidx.appcompat.app.AppCompatActivity
import com.gh.gamecenter.feature.entity.GameEntity
import com.gh.gamecenter.gamedetail.accelerator.chain.AcceleratorValidator.Request
import kotlinx.parcelize.Parcelize
class AcceleratorValidator {
interface ValidateListener {
fun finished(context: Context)
}
interface Interceptor {
fun intercept(context: Context, chain: Chain, listener: ValidateListener?)
}
interface Chain {
val request: Request
fun proceed(context: Context, request: Request, listener: ValidateListener?)
fun isValidContext(context: Context) =
context is AppCompatActivity && !context.isFinishing && !context.isDestroyed
}
@Parcelize
data class Request(
val isVip: Boolean,
val isNewUser: Boolean,
val game: GameEntity,
val sourceEntrance: String
):Parcelable
}
class RealAcceleratorInterceptorChain(
private val interceptors: List<AcceleratorValidator.Interceptor>,
private val index: Int,
private val _request: Request
) : AcceleratorValidator.Chain {
override val request: Request
get() = _request
override
fun proceed(context: Context, request: Request, listener: AcceleratorValidator.ValidateListener?) {
if (!isValidContext(context)) {
// 如果 context失效说明当前页面已销毁直接中断流程
return
}
if (index >= interceptors.size) {
// 验证完成
listener?.finished(context)
return
}
val next = RealAcceleratorInterceptorChain(
interceptors,
index + 1,
_request
)
interceptors[index].intercept(context, next, listener)
}
}

View File

@ -1,31 +0,0 @@
package com.gh.gamecenter.gamedetail.accelerator.chain
import android.content.Context
import com.gh.gamecenter.gamedetail.accelerator.dialog.AcceleratorDialogFragment
import com.gh.gamecenter.gamedetail.accelerator.dialog.AcceleratorDialogFragment.Companion.SPEED_ENABLE_VIP
class AcceleratorVipInterceptor : AcceleratorValidator.Interceptor {
override fun intercept(
context: Context,
chain: AcceleratorValidator.Chain,
listener: AcceleratorValidator.ValidateListener?
) {
val request = chain.request
val isVip = request.isVip
val isNewUser = request.isNewUser
if (isVip || isNewUser) {
chain.proceed(context, request, listener)
} else {
val game = request.game
AcceleratorDialogFragment.show(
SPEED_ENABLE_VIP,
game.getUniquePackageName() ?: "",
game.id,
game.name ?: "",
request.sourceEntrance,
context
)
}
}
}

View File

@ -1,241 +0,0 @@
package com.gh.gamecenter.gamedetail.accelerator.dialog
import android.app.Dialog
import android.content.Context
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.annotation.IntDef
import androidx.appcompat.app.AppCompatActivity
import com.gh.common.util.DirectUtils
import com.gh.gamecenter.R
import com.gh.gamecenter.WebActivity
import com.gh.gamecenter.common.HaloApp
import com.gh.gamecenter.common.base.fragment.BaseDialogFragment
import com.gh.gamecenter.common.constant.Constants
import com.gh.gamecenter.common.constant.EntranceConsts
import com.gh.gamecenter.common.utils.SensorsBridge
import com.gh.gamecenter.common.utils.dip2px
import com.gh.gamecenter.common.utils.goneIf
import com.gh.gamecenter.common.utils.toColor
import com.gh.gamecenter.core.provider.IAcceleratorProvider
import com.gh.gamecenter.core.utils.CurrentActivityHolder
import com.gh.gamecenter.databinding.DialogFragmentSpeedReplaceGameBinding
import com.therouter.TheRouter
/**
* 加速器相关的dialog
*/
class AcceleratorDialogFragment : BaseDialogFragment() {
private lateinit var binding: DialogFragmentSpeedReplaceGameBinding
private lateinit var uiHelper: SpeedDialogUiHelper
private var pkgName = ""
private var gameId = ""
private var gameName = ""
private var sourceEntrance = ""
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val type = arguments?.getInt(EntranceConsts.KEY_SPEED_TYPE) ?: 0
pkgName = arguments?.getString(EntranceConsts.KEY_PACKAGENAME) ?: ""
gameId = arguments?.getString(EntranceConsts.KEY_GAMEID) ?: ""
gameName = arguments?.getString(EntranceConsts.KEY_GAMENAME) ?: ""
sourceEntrance = arguments?.getString(EntranceConsts.KEY_SOURCE_ENTRANCE) ?: ""
uiHelper = when (type) {
SPEED_ENABLE_VIP -> {
SensorsBridge.trackMembershipActivationDialogShow(pkgName, gameId, gameName, sourceEntrance)
EnableVipUi()
}
SPEED_START_FAILURE -> {
SensorsBridge.trackNetworkAccelerationFailureDialogShow(pkgName, gameId, gameName, sourceEntrance)
SpeedFailureUi()
}
SPEED_STOP -> StopSpeedUi()
SPEED_NOT_INSTALLED -> NotInstalledUi()
else -> throw IllegalArgumentException("请传递正确的参数 SpeedType !")
}
}
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
val createDialog = super.onCreateDialog(savedInstanceState)
createDialog.setCanceledOnTouchOutside(true)
createDialog.setCancelable(true)
return createDialog
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
return DialogFragmentSpeedReplaceGameBinding.inflate(inflater, container, false)
.also {
binding = it
}.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding.tvContent.setText(uiHelper.contentResId)
binding.tvCancel.goneIf(!uiHelper.isShowCancelButton) {
if (uiHelper.cancelResId != -1) {
binding.tvCancel.setText(uiHelper.cancelResId)
}
binding.tvCancel.setOnClickListener {
dismiss()
}
}
binding.tvSubmit.setText(uiHelper.submitResId)
binding.tvSubmit.setTextColor(uiHelper.submitTextColorResId.toColor(view.context))
binding.tvSubmit.setBackgroundResource(uiHelper.submitBackgroundResId)
binding.tvSubmit.setOnClickListener {
dismiss()
when (uiHelper) {
is EnableVipUi -> {
SensorsBridge.trackMembershipActivationDialogClick(
pkgName,
gameId,
gameName,
sourceEntrance
)
SensorsBridge.trackMyAssetsPageShow(pkgName, gameId, gameName, sourceEntrance)
val intent = WebActivity.getMyAssetsIntent(requireContext())
startActivity(intent)
}
is SpeedFailureUi -> {
SensorsBridge.trackNetworkAccelerationFailureDialogClick(pkgName, gameId, gameName, sourceEntrance)
context?.let {
DirectUtils.directToWebView(it, Constants.QQ_QIDIAN_ADDRESS, "")
}
}
is StopSpeedUi -> {
TheRouter.get(IAcceleratorProvider::class.java)?.stopQyGameAccelerate()
}
}
}
}
override fun onStart() {
super.onStart()
val width = HaloApp.getInstance().resources.displayMetrics.widthPixels - 60F.dip2px()
val height = dialog?.window?.attributes?.height ?: ViewGroup.LayoutParams.WRAP_CONTENT
dialog?.window?.setLayout(width, height)
}
companion object {
const val SPEED_ENABLE_VIP = 1
const val SPEED_START_FAILURE = 2
const val SPEED_STOP = 3
const val SPEED_NOT_INSTALLED = 4
fun show(
@SpeedType type: Int,
pkgName: String,
gameId: String,
gameName: String,
sourceEntrance: String,
context: Context
) {
if (context is AppCompatActivity) {
context.supportFragmentManager
} else {
(CurrentActivityHolder.getCurrentActivity() as? AppCompatActivity)?.supportFragmentManager
}?.let {
val fragment = AcceleratorDialogFragment().apply {
arguments = Bundle().apply {
putInt(EntranceConsts.KEY_SPEED_TYPE, type)
putString(EntranceConsts.KEY_PACKAGENAME, pkgName)
putString(EntranceConsts.KEY_GAMEID, gameId)
putString(EntranceConsts.KEY_GAMENAME, gameName)
putString(EntranceConsts.KEY_SOURCE_ENTRANCE, sourceEntrance)
}
}
fragment.show(it, AcceleratorDialogFragment::class.java.simpleName)
}
}
}
@IntDef(SPEED_ENABLE_VIP, SPEED_START_FAILURE, SPEED_STOP, SPEED_NOT_INSTALLED)
@Retention(AnnotationRetention.SOURCE)
annotation class SpeedType
abstract class SpeedDialogUiHelper {
abstract val contentResId: Int
abstract val isShowCancelButton: Boolean
open val cancelResId: Int = -1
abstract val submitResId: Int
open val submitTextColorResId = com.gh.gamecenter.common.R.color.text_aw_primary
open val submitBackgroundResId = com.gh.gamecenter.common.R.drawable.bg_common_button_fill_blue
}
class EnableVipUi : SpeedDialogUiHelper() {
override val contentResId: Int
get() = R.string.enable_vip_tips
override val isShowCancelButton: Boolean
get() = false
override val submitResId: Int
get() = R.string.go_to_activate
}
class SpeedFailureUi : SpeedDialogUiHelper() {
override val contentResId: Int
get() = R.string.speed_failure_tips
override val isShowCancelButton: Boolean
get() = false
override val submitResId: Int
get() = R.string.contact_service
override val submitTextColorResId: Int
get() = com.gh.gamecenter.common.R.color.primary_theme
override val submitBackgroundResId: Int
get() = com.gh.gamecenter.common.R.drawable.bg_common_button_light_fill_blue
}
class StopSpeedUi : SpeedDialogUiHelper() {
override val contentResId: Int
get() = R.string.stop_speed_tips
override val isShowCancelButton: Boolean
get() = true
override val submitResId: Int
get() = R.string.stop_speed
override val cancelResId: Int
get() = R.string.cancel
}
class NotInstalledUi : SpeedDialogUiHelper() {
override val contentResId: Int
get() = R.string.speed_not_installed_tips
override val isShowCancelButton: Boolean
get() = false
override val submitResId: Int
get() = R.string.dialog_hint_confirm
}
}

View File

@ -1,116 +0,0 @@
package com.gh.gamecenter.gamedetail.accelerator.dialog
import android.content.Context
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.appcompat.app.AppCompatActivity
import com.gh.gamecenter.R
import com.gh.gamecenter.common.HaloApp
import com.gh.gamecenter.common.constant.EntranceConsts
import com.gh.gamecenter.common.utils.SensorsBridge
import com.gh.gamecenter.common.utils.dip2px
import com.gh.gamecenter.core.utils.CurrentActivityHolder
import com.gh.gamecenter.databinding.DialogFragmentSpeedReplaceGameBinding
import com.lightgame.dialog.BaseDialogFragment
class AcceleratorReplaceDialogFragment : BaseDialogFragment() {
private lateinit var binding: DialogFragmentSpeedReplaceGameBinding
private var pkgName = ""
private var gameId = ""
private var gameName = ""
private var sourceEntrance = ""
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
pkgName = arguments?.getString(EntranceConsts.KEY_PACKAGENAME) ?: ""
gameId = arguments?.getString(EntranceConsts.KEY_GAMEID) ?: ""
gameName = arguments?.getString(EntranceConsts.KEY_GAMENAME) ?: ""
sourceEntrance = arguments?.getString(EntranceConsts.KEY_SOURCE_ENTRANCE) ?: ""
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
return DialogFragmentSpeedReplaceGameBinding.inflate(inflater, container, false)
.also {
binding = it
}.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
SensorsBridge.trackNetworkAccelerationConflictDialogShow(pkgName, gameId, gameName, sourceEntrance)
binding.tvContent.text = getString(R.string.speed_replace_game_tips, gameName)
binding.tvCancel.setOnClickListener {
SensorsBridge.trackNetworkAccelerationConflictDialogClick(
pkgName,
gameId,
gameName,
BUTTON_NAME_CANCEL,
sourceEntrance
)
dismiss()
}
binding.tvSubmit.setOnClickListener {
SensorsBridge.trackNetworkAccelerationConflictDialogClick(
pkgName,
gameId,
gameName,
BUTTON_NAME_CONTINUE,
sourceEntrance
)
// 加速
dismiss()
callback?.invoke()
}
}
override fun onStart() {
super.onStart()
val width = HaloApp.getInstance().resources.displayMetrics.widthPixels - 60F.dip2px()
val height = dialog?.window?.attributes?.height ?: ViewGroup.LayoutParams.WRAP_CONTENT
dialog?.window?.setLayout(width, height)
}
private var callback: (() -> Unit)? = null
fun setOnSubmitListener(callback: () -> Unit) {
this.callback = callback
}
companion object {
private const val BUTTON_NAME_CANCEL = "暂不启动"
private const val BUTTON_NAME_CONTINUE = "继续启动"
fun show(
context: Context,
pkgName: String,
gameId: String,
gameName: String,
sourceEntrance: String,
callback: () -> Unit
) {
if (context is AppCompatActivity) {
context.supportFragmentManager
} else {
(CurrentActivityHolder.getCurrentActivity() as? AppCompatActivity)?.supportFragmentManager
}?.let {
val fragment = AcceleratorReplaceDialogFragment().apply {
setOnSubmitListener(callback)
arguments = Bundle().apply {
putString(EntranceConsts.KEY_PACKAGENAME, pkgName)
putString(EntranceConsts.KEY_GAMEID, gameId)
putString(EntranceConsts.KEY_GAMENAME, gameName)
putString(EntranceConsts.KEY_SOURCE_ENTRANCE, sourceEntrance)
}
}
fragment.show(it, AcceleratorDialogFragment::class.java.simpleName)
}
}
}
}

View File

@ -1,197 +0,0 @@
package com.gh.gamecenter.gamedetail.accelerator.dialog
import android.content.Context
import android.graphics.Rect
import android.os.Build
import android.os.Bundle
import android.view.View
import android.view.ViewGroup
import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.viewModels
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView
import androidx.recyclerview.widget.RecyclerView.ViewHolder
import com.gh.common.util.CheckLoginUtils
import com.gh.gamecenter.R
import com.gh.gamecenter.common.base.fragment.BaseBottomDialogFragment
import com.gh.gamecenter.common.utils.SensorsBridge
import com.gh.gamecenter.common.utils.dip2px
import com.gh.gamecenter.common.utils.toBinding
import com.gh.gamecenter.common.utils.toColor
import com.gh.gamecenter.core.provider.IAcceleratorProvider
import com.gh.gamecenter.core.utils.CurrentActivityHolder
import com.gh.gamecenter.databinding.DialogFragmentAcceleratorZoneBinding
import com.gh.gamecenter.databinding.RecyclerAcceleratorZoneBinding
import com.gh.gamecenter.feature.entity.AcctGameInfo
import com.gh.gamecenter.feature.entity.GameEntity
import com.gh.gamecenter.gamedetail.accelerator.GameDetailAcceleratorUiHelper.Companion.MEMBER_TYPE_NOT_LOGIN
import com.gh.gamecenter.gamedetail.accelerator.GameDetailAcceleratorUiHelper.Companion.SCENE_TYPE_NO_GUIDE_LAYER
import com.gh.gamecenter.gamedetail.accelerator.GameDetailAcceleratorUiHelper.Companion.SOURCE_ENTRANCE_GAME_DETAIL
import com.gh.gamecenter.gamedetail.AcceleratorZoneViewModel
import com.gh.gamecenter.gamedetail.accelerator.chain.AcceleratorClient
import com.gh.gamecenter.gamedetail.accelerator.chain.AcceleratorValidator
import com.therouter.TheRouter
import kotlin.math.roundToInt
class AcceleratorZoneDialogFragment : BaseBottomDialogFragment<DialogFragmentAcceleratorZoneBinding>() {
private val viewModel by viewModels<AcceleratorZoneViewModel>()
private lateinit var adapter: ZoneAdapter
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val data =
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
arguments?.getParcelableArrayList(KEY_DATA, AcctGameInfo::class.java)
} else {
arguments?.getParcelableArrayList(KEY_DATA)
} ?: listOf<AcctGameInfo>()
val game = arguments?.getParcelable<GameEntity>(KEY_GAME)!!
mBinding.titleView.setOnRightClickListener {
dismiss()
}
adapter = ZoneAdapter {
startAccelerating(game, it)
dismiss()
}
mBinding.recyclerZone.layoutManager = GridLayoutManager(requireContext(), 3)
mBinding.recyclerZone.addItemDecoration(MyDecorationItem())
mBinding.recyclerZone.adapter = adapter
adapter.submitList(data)
}
private fun startAccelerating(game: GameEntity, acctGameInfo: AcctGameInfo) {
context?.let {
viewModel.useCase.insertAcctGameInfo(acctGameInfo)
val iAcceleratorProvider = TheRouter.get(IAcceleratorProvider::class.java)
val memberType = if (CheckLoginUtils.isLogin()) {
iAcceleratorProvider?.getMemberType() ?: ""
} else {
MEMBER_TYPE_NOT_LOGIN
}
SensorsBridge.trackNetworkAccelerationButtonClick(
game.getUniquePackageName() ?: "",
game.id,
game.name ?: "",
memberType,
acctGameInfo.zoneInfo.cnName ?: "",
SCENE_TYPE_NO_GUIDE_LAYER,
SOURCE_ENTRANCE_GAME_DETAIL
)
val isVip = iAcceleratorProvider?.isVip() ?: false
val isNewUser = iAcceleratorProvider?.isNewUser() ?: false
val request = AcceleratorValidator.Request(isVip, isNewUser, game, SOURCE_ENTRANCE_GAME_DETAIL)
AcceleratorClient.newInstance()
.execute(it, request, object : AcceleratorValidator.ValidateListener {
override fun finished(context: Context) {
StartingAcceleratorDialogFragment.show(
context, acctGameInfo, game, isNeedRecord = true, hasMultiZone = true,
sourceEntrance = SOURCE_ENTRANCE_GAME_DETAIL
)
}
})
}
}
companion object {
private const val KEY_DATA = "key_data"
private const val KEY_GAME = "key_game"
fun show(context: Context, data: ArrayList<AcctGameInfo>, game: GameEntity) {
if (context is AppCompatActivity) {
context.supportFragmentManager
} else {
(CurrentActivityHolder.getCurrentActivity() as? AppCompatActivity)?.supportFragmentManager
}?.let {
val fragment = AcceleratorZoneDialogFragment().apply {
arguments = Bundle().apply {
putParcelableArrayList(KEY_DATA, data)
putParcelable(KEY_GAME, game)
}
}
fragment.show(it, fragment::class.java.simpleName)
}
}
}
private class MyDecorationItem : RecyclerView.ItemDecoration() {
override fun getItemOffsets(outRect: Rect, view: View, parent: RecyclerView, state: RecyclerView.State) {
val position = parent.getChildAdapterPosition(view)
val space = (16F.dip2px() / 3F).roundToInt()
val (left, right) = when (position % 3) {
0 -> 0 to space
1 -> space to space
else -> space to 0
}
outRect.top = 8F.dip2px()
outRect.left = left
outRect.right = right
}
}
class ZoneAdapter(private val click: (AcctGameInfo) -> Unit) :
ListAdapter<AcctGameInfo, ZoneAdapter.ZoneViewHolder>(diffCallback) {
private var selectedPosition = -1
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ZoneViewHolder {
return ZoneViewHolder(parent.toBinding())
}
override fun onBindViewHolder(holder: ZoneViewHolder, position: Int, payloads: MutableList<Any>) {
if (payloads.isNotEmpty()) {
updateSelectedState(holder, position)
} else {
super.onBindViewHolder(holder, position, payloads)
}
}
override fun onBindViewHolder(holder: ZoneViewHolder, position: Int) {
val item = getItem(position) ?: return
updateSelectedState(holder, position)
holder.binding.tvName.text = item.zoneName
holder.itemView.setOnClickListener {
click(item)
}
}
private fun updateSelectedState(holder: ZoneViewHolder, position: Int) {
val (textColorResId, backgroundResId) = if (position == selectedPosition) {
com.gh.gamecenter.common.R.color.text_theme to R.drawable.bg_shape_2496ff_alpha_10_radius_8
} else {
com.gh.gamecenter.common.R.color.text_secondary to R.drawable.bg_shape_f8_radius_8
}
holder.binding.tvName.setTextColor(textColorResId.toColor(holder.itemView.context))
holder.binding.tvName.setBackgroundResource(backgroundResId)
}
companion object {
private const val SELECTED_CHANGED_PAYLOAD = "selected_changed_payload"
private val diffCallback = object : DiffUtil.ItemCallback<AcctGameInfo>() {
override fun areItemsTheSame(oldItem: AcctGameInfo, newItem: AcctGameInfo): Boolean {
return oldItem.zoneInfo.id == newItem.zoneInfo.id
}
override fun areContentsTheSame(oldItem: AcctGameInfo, newItem: AcctGameInfo): Boolean {
return oldItem == newItem
}
}
}
class ZoneViewHolder(val binding: RecyclerAcceleratorZoneBinding) : ViewHolder(binding.root)
}
}

View File

@ -1,258 +0,0 @@
package com.gh.gamecenter.gamedetail.accelerator.dialog
import android.app.Dialog
import android.content.Context
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.viewModels
import com.gh.common.util.PackageLauncher
import com.gh.gamecenter.R
import com.gh.gamecenter.common.base.fragment.BaseDialogFragment
import com.gh.gamecenter.common.constant.EntranceConsts
import com.gh.gamecenter.common.utils.SensorsBridge
import com.gh.gamecenter.core.callback.AccelerateState
import com.gh.gamecenter.core.callback.OnAccelerateListener
import com.gh.gamecenter.core.provider.IAcceleratorProvider
import com.gh.gamecenter.core.utils.CurrentActivityHolder
import com.gh.gamecenter.core.utils.ToastUtils
import com.gh.gamecenter.databinding.DialogFragmentStartingAcceleratorBinding
import com.gh.gamecenter.feature.entity.AcctGameInfo
import com.gh.gamecenter.feature.entity.GameEntity
import com.gh.gamecenter.gamedetail.StartingAcceleratorViewModel
import com.gh.gamecenter.gamedetail.accelerator.GameDetailAcceleratorUiHelper.Companion.DISTRICT_SERVER_HAVA
import com.gh.gamecenter.gamedetail.accelerator.GameDetailAcceleratorUiHelper.Companion.SOURCE_ENTRANCE_GAME_DETAIL
import com.gh.gamecenter.gamedetail.accelerator.dialog.AcceleratorDialogFragment.Companion.SPEED_START_FAILURE
import com.gh.gamecenter.livedata.EventObserver
import com.therouter.TheRouter
import io.reactivex.disposables.CompositeDisposable
import kotlin.math.max
class StartingAcceleratorDialogFragment : BaseDialogFragment() {
private val viewModel by viewModels<StartingAcceleratorViewModel>()
private lateinit var binding: DialogFragmentStartingAcceleratorBinding
private lateinit var acctGameInfo: AcctGameInfo
private lateinit var game: GameEntity
private var isNeedRecord: Boolean = false
private var iAcceleratorProvider: IAcceleratorProvider? = null
private var hasMultiZone = false
private var sourceEntrance = SOURCE_ENTRANCE_GAME_DETAIL
private val compositeDisposable = CompositeDisposable()
private var _progress = 0
private val handler = Handler(Looper.getMainLooper())
private var refreshTokenCount = 0
private val accelerationListener = object : OnAccelerateListener {
override fun onStateChanged(state: AccelerateState) {
// 如果状态能成功回,则移除计时
handler.removeCallbacksAndMessages(null)
when (state) {
is AccelerateState.Success -> {
ToastUtils.showToast("加速成功")
// 加速成功,启动游戏
PackageLauncher.launchApp(requireContext(), game, game.getUniquePackageName())
// 记录加速记录
if (isNeedRecord) {
viewModel.useCase.recordAcctGameInfo(game.id, acctGameInfo, hasMultiZone)
}
trackNetworkAccelerationStartupResult("成功")
dismissAllowingStateLoss()
}
is AccelerateState.Failure -> {
// 有些错误需要额外处理,这里直接跳过错误提示(如token失效登录时token设置失败)
if ((state.isTokenExpired || state.isTokenEmpty) && refreshTokenCount < REFRESH_TOKEN_MAX_COUNT) {
// do nothing
} else {
if (!state.isSkipError) {
context?.let {
AcceleratorDialogFragment.show(
SPEED_START_FAILURE,
game.getUniquePackageName() ?: "",
game.id,
game.name ?: "",
sourceEntrance,
it
)
}
}
dismissAllowingStateLoss()
trackNetworkAccelerationStartupResult("失败(${state.code})")
}
}
is AccelerateState.Normal -> {
if (state.isTokenExpired || state.isTokenEmpty) {
// token过期/登录时token设置失败,在此获取token并重新启动加速(最多重试三次)
if (refreshTokenCount < REFRESH_TOKEN_MAX_COUNT) {
viewModel.loadAcceleratorToken()
refreshTokenCount++
}
}
}
else -> Unit
}
}
override fun onProgress(progress: Int, curGamePkgName: String?, curGameZoneFlag: String?) {
_progress = max(_progress, progress)
binding.tvProgress.text = getString(R.string.accelerating_with_progress, "$progress")
}
override fun onVipStatusChanged(isNewUser: Boolean, isVip: Boolean) = Unit
}
private fun trackNetworkAccelerationStartupResult(result: String) {
SensorsBridge.trackNetworkAccelerationStartupResult(
game.getUniquePackageName() ?: "",
game.id,
game.name ?: "",
iAcceleratorProvider?.getMemberType() ?: "",
if (hasMultiZone) acctGameInfo.zoneInfo.cnName ?: "" else DISTRICT_SERVER_HAVA,
result,
sourceEntrance
)
}
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
return super.onCreateDialog(savedInstanceState).apply {
setCancelable(false)
setCanceledOnTouchOutside(false)
this@StartingAcceleratorDialogFragment.isCancelable = false
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
iAcceleratorProvider = TheRouter.get(IAcceleratorProvider::class.java)
acctGameInfo = arguments?.getParcelable(EntranceConsts.KEY_ACCT_GAME_INFO)!!
game = arguments?.getParcelable(EntranceConsts.KEY_GAME)!!
isNeedRecord = arguments?.getBoolean(EntranceConsts.KEY_IS_NEED_RECORD) ?: false
hasMultiZone = arguments?.getBoolean(EntranceConsts.KEY_HAS_MULTI_ZONE) ?: false
sourceEntrance = arguments?.getString(EntranceConsts.KEY_SOURCE_ENTRANCE) ?: SOURCE_ENTRANCE_GAME_DETAIL
}
override fun onBack(): Boolean {
return true
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
return DialogFragmentStartingAcceleratorBinding.inflate(inflater, container, false)
.also {
binding = it
}.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding.tvProgress.text = getString(R.string.accelerating_with_progress, "0")
iAcceleratorProvider?.bindAccRelatedListener("", accelerationListener)
val isVip = iAcceleratorProvider?.isVip() ?: false
val isNewUser = iAcceleratorProvider?.isNewUser() ?: false
if (isNewUser && !isVip) {
// 新用户并且还不是vip
viewModel.rechargeTrial()
} else {
startGameAccelerate()
}
viewModel.restartingAcceleratorAction.observe(viewLifecycleOwner, EventObserver {
startGameAccelerate()
})
viewModel.rechargeTrailResult.observe(viewLifecycleOwner, EventObserver {
if (it) {
startGameAccelerate()
} else {
// 充值失败
AcceleratorDialogFragment.show(
SPEED_START_FAILURE,
game.getUniquePackageName() ?: "",
game.id,
game.name ?: "",
sourceEntrance,
requireContext()
)
dismissAllowingStateLoss()
}
})
}
private fun startGameAccelerate() {
handler.removeCallbacksAndMessages(null)
handler.postDelayed({
// 15s以后不管成功还是失败都要关闭当前页面
dismissAllowingStateLoss()
}, TIME_OUT)
viewModel.useCase.setLastAcctGameRecord(game)
iAcceleratorProvider?.startQyGameAccelerate(acctGameInfo)
if (isNeedRecord) {
viewModel.useCase.insertAcctGameInfo(acctGameInfo)
}
if (refreshTokenCount == 0) {
SensorsBridge.trackNetworkAccelerationStartup(
game.getUniquePackageName() ?: "",
game.id,
game.name ?: "",
iAcceleratorProvider?.getMemberType() ?: "",
if (hasMultiZone) acctGameInfo.zoneInfo.cnName ?: "" else DISTRICT_SERVER_HAVA,
sourceEntrance
)
}
}
override fun onDestroyView() {
handler.removeCallbacksAndMessages(null)
iAcceleratorProvider?.unBindAccRelatedListener(accelerationListener)
super.onDestroyView()
compositeDisposable.clear()
}
companion object {
private const val TIME_OUT = 1000 * 15L
private const val REFRESH_TOKEN_MAX_COUNT = 3
fun show(
context: Context,
acctGameInfo: AcctGameInfo,
game: GameEntity,
isNeedRecord: Boolean,
hasMultiZone: Boolean,
sourceEntrance: String
) {
if (context is AppCompatActivity) {
context.supportFragmentManager
} else {
(CurrentActivityHolder.getCurrentActivity() as? AppCompatActivity)?.supportFragmentManager
}?.let {
val fragment = StartingAcceleratorDialogFragment().apply {
arguments = Bundle().apply {
putParcelable(EntranceConsts.KEY_ACCT_GAME_INFO, acctGameInfo)
putParcelable(EntranceConsts.KEY_GAME, game)
putBoolean(EntranceConsts.KEY_IS_NEED_RECORD, isNeedRecord)
putBoolean(EntranceConsts.KEY_HAS_MULTI_ZONE, hasMultiZone)
putString(EntranceConsts.KEY_SOURCE_ENTRANCE, sourceEntrance)
}
}
fragment.show(it, fragment::class.java.simpleName)
}
}
}
}

View File

@ -61,14 +61,7 @@ class NewGameDetailEntity(
@SerializedName("new_notice")
var newNotice: ArrayList<LinkEntity>? = null,
@SerializedName("accelerator_status")
private var _acceleratorStatus: Boolean? = null
) {
val acceleratorStatus: Boolean
get() = _acceleratorStatus ?: false
fun isShowContentCard(gameEntity: GameEntity?): Boolean {
return contentCard.size > 1 && (gameEntity?.shouldUseMirrorInfo() == false || (gameEntity?.shouldUseMirrorInfo() == true && mirrorData?.contentCardStatus == "on"))
}

View File

@ -239,7 +239,7 @@ class CustomPageFragment : LazyFragment(), ISmartRefreshContent, IScrollable {
viewModel.loadFirst(false)
}
}
binding.reuseNoConnectionStub.inflateOrShow()
binding.reuseNoConnectionStub.inflate()
} else {
noConnectionBinding?.root?.visibility = View.VISIBLE
}
@ -249,7 +249,7 @@ class CustomPageFragment : LazyFragment(), ISmartRefreshContent, IScrollable {
noDataBinding = ReuseNoneDataBinding.bind(inflated)
noDataBinding?.root?.visibility = View.VISIBLE
}
binding.reuseNoDataStub.inflateOrShow()
binding.reuseNoDataStub.inflate()
} else {
noDataBinding?.root?.visibility = View.VISIBLE
}
@ -304,7 +304,7 @@ class CustomPageFragment : LazyFragment(), ISmartRefreshContent, IScrollable {
}
initSearchBar(it)
}
binding.reuseSearchBarStub.inflateOrShow()
binding.reuseSearchBarStub.inflate()
} else {
initSearchBar(it)
}

View File

@ -53,7 +53,6 @@ class CustomHomeSlideListItemViewHolder(val binding: HomeSlideListItemCustomBind
ImageUtils.displayWithCallback(
binding.slideBackground,
homeSlide.image,
false,
object : BaseControllerListener<ImageInfo>() {
override fun onFinalImageSet(id: String?, imageInfo: ImageInfo?, animatable: Animatable?) {
binding.bottomGradient.visibility = View.VISIBLE

View File

@ -67,7 +67,6 @@ class CustomHomeSubSlideListItemViewHolder(val binding: HomeSubSlideListItemCust
ImageUtils.displayWithCallback(
binding.slideBackground,
homeSlide.image,
false,
object : BaseControllerListener<ImageInfo>() {
override fun onFinalImageSet(id: String?, imageInfo: ImageInfo?, animatable: Animatable?) {
if (homeSlide.placeholderColor.isNotEmpty() && homeSlide.linkGame != null) {

View File

@ -144,7 +144,7 @@ public class LibaoDetailFragment extends ToolbarFragment implements LibaoDetailA
private DetailViewHolder getDetailViewHolder() {
// 每次获取需要重新创建, 防止数据刷新
return new DetailViewHolder(mCachedView, mGameEntity, false, mEntrance, mName, mTitle, null, false, null); // 下载按钮ViewHolder
return new DetailViewHolder(mCachedView, mGameEntity, false, mEntrance, mName, mTitle, null, false); // 下载按钮ViewHolder
}
public LibaoEntity getLibaoEntity() {

View File

@ -192,8 +192,7 @@ public class NewsDetailFragment extends ToolbarFragment {
"新闻详情",
adapter.getTitle(),
mExposureEvent,
false,
null); // 下载按钮ViewHolder
false); // 下载按钮ViewHolder
}
@Override

View File

@ -35,21 +35,17 @@ class PackageFilterManager {
if (appendOnly) {
// 添加因为异常而没能正常更新的包名列表
synchronized(PackageRepository.mPendingPackageNameSet) {
finalPackageList.addAll(PackageRepository.mPendingPackageNameSet)
}
finalPackageList.addAll(PackageRepository.mPendingPackageNameSet)
}
RetrofitManager.getInstance()
.newApi
.postInstalledAppList(finalPackageList.toRequestBody())
.postInstalledAppList(packageList.toRequestBody())
.subscribeOn(Schedulers.io())
.subscribe(object : BiResponse<PackageFilter>() {
override fun onSuccess(data: PackageFilter) {
mPackageKey = data.key
synchronized(PackageRepository.mPendingPackageNameSet) {
PackageRepository.mPendingPackageNameSet.removeAll(finalPackageList)
}
PackageRepository.mPendingPackageNameSet.clear()
val partialPackageList = arrayListOf<String>()
@ -82,9 +78,7 @@ class PackageFilterManager {
super.onFailure(exception)
if (appendOnly) {
synchronized(PackageRepository.mPendingPackageNameSet) {
PackageRepository.mPendingPackageNameSet.addAll(finalPackageList)
}
PackageRepository.mPendingPackageNameSet.addAll(packageList)
} else {
if (exception is retrofit2.HttpException && exception.code() == 403) {
// 403 代表 key 过期,需要重新获取

View File

@ -85,7 +85,7 @@ object PackageRepository {
_recentVaPlayedChanged.postValue(Unit)
}
val packageFilterManager = PackageFilterManager()
var mPendingPackageNameSet = Collections.synchronizedSet<String>(hashSetOf<String>()) // 因遇到异常而等待下次操作更新的包名列表
var mPendingPackageNameSet = hashSetOf<String>() // 因遇到异常而等待下次操作更新的包名列表
var mValidPackageNameSet = hashSetOf<String>() // 已被收录的游戏包名列表

View File

@ -28,7 +28,10 @@ import com.gh.common.util.*
import com.gh.common.util.LogUtils
import com.gh.common.util.NewFlatLogUtils
import com.gh.common.util.NewLogUtils
import com.gh.gamecenter.*
import com.gh.gamecenter.CollectionActivity
import com.gh.gamecenter.R
import com.gh.gamecenter.ShareGhActivity
import com.gh.gamecenter.WebActivity
import com.gh.gamecenter.common.base.fragment.BaseLazyFragment
import com.gh.gamecenter.common.constant.Constants
import com.gh.gamecenter.common.constant.EntranceConsts
@ -115,11 +118,9 @@ class HaloPersonalFragment : BaseLazyFragment() {
com.tencent.connect.common.Constants.REQUEST_LOGIN -> {
LoginHelper.onQQLoginCallback(requestCode, resultCode, data)
}
32973 -> {
LoginHelper.onWeiboLoginCallback(requireActivity(), requestCode, resultCode, data)
}
REQUEST_MESSAGE -> {
mUnreadViewModel.retry()
}
@ -136,24 +137,15 @@ class HaloPersonalFragment : BaseLazyFragment() {
SensorsBridge.trackHaloSelfClick("用户信息", "立即登录", "", "", "")
CheckLoginUtils.checkLogin(context, "我的光环-立即登录", null)
} else {
NewFlatLogUtils.logHaloSelfClick("用户信息", "个人主页")
SensorsBridge.trackHaloSelfClick("用户信息", "个人主页", "", "", "")
DirectUtils.directToHomeActivity(
requireContext(),
UserManager.getInstance().userId,
"",
"我的光环"
)
mStubBinding.ivArrow.performClick()
}
}
mStubBinding.toolbarContainer -> {
if (mUserInfoEntity == null) {
NewFlatLogUtils.logHaloSelfLogin()
CheckLoginUtils.checkLogin(context, "我的光环-立即登录", null)
}
}
mStubBinding.darkModeIv -> {
if (!ClickUtils.isFastDoubleClick(v.id, 1000)) {
NewFlatLogUtils.logHaloSelfClick("右上角", "切换模式")
@ -190,7 +182,6 @@ class HaloPersonalFragment : BaseLazyFragment() {
}
}
}
mStubBinding.personalMsg -> {
// 优先进入有数字提醒的消息tab其次是有红点提醒的游戏动态最后是没有提醒的消息tab
val defaultTabIndex = if ((mUnreadViewModel.messageUnreadCountLiveData.value?.message
@ -217,7 +208,6 @@ class HaloPersonalFragment : BaseLazyFragment() {
DirectUtils.directToMessageCenter(defaultTabIndex, "我的光环-消息")
}
mStubBinding.personalUserIcon,
mStubBinding.personalUserName -> {
if (mUserInfoEntity != null) {
@ -236,21 +226,22 @@ class HaloPersonalFragment : BaseLazyFragment() {
CheckLoginUtils.checkLogin(context, "我的光环-立即登录", null)
}
}
mStubBinding.tvMyAssets -> {
mStubBinding.ivArrow -> {
if (mUserInfoEntity != null) {
NewFlatLogUtils.logHaloSelfClick("用户信息", "个人主页")
SensorsBridge.trackHaloSelfClick("用户信息", "个人主页", "", "", "")
SensorsBridge.trackMyAssetsPageShow("", "", "", "我的光环")
val intent = WebActivity.getMyAssetsIntent(requireContext())
startActivity(intent)
DirectUtils.directToHomeActivity(
requireContext(),
UserManager.getInstance().userId,
"",
"我的光环"
)
} else {
NewFlatLogUtils.logHaloSelfClick("用户信息", "立即登录")
SensorsBridge.trackHaloSelfClick("用户信息", "立即登录", "", "", "")
CheckLoginUtils.checkLogin(context, "我的光环-个人主页", null)
}
}
mStubBinding.personalBadge -> {
NewFlatLogUtils.logHaloSelfClick("用户信息", "我的徽章")
SensorsBridge.trackHaloSelfClick("用户信息", "我的徽章", "", "", "")
@ -261,7 +252,6 @@ class HaloPersonalFragment : BaseLazyFragment() {
mUserInfoEntity?.icon
)
}
mStubBinding.myGameTv -> {
if (UserManager.getInstance().isLoggedIn) {
NewFlatLogUtils.logHaloSelfClick("常用功能", "我的游戏")
@ -278,7 +268,6 @@ class HaloPersonalFragment : BaseLazyFragment() {
CheckLoginUtils.checkLogin(requireContext(), "我的光环-我的游戏") {}
}
}
mStubBinding.myPostTv -> {
if (UserManager.getInstance().isLoggedIn) {
NewFlatLogUtils.logHaloSelfClick("常用功能", "我的发布")
@ -295,7 +284,6 @@ class HaloPersonalFragment : BaseLazyFragment() {
CheckLoginUtils.checkLogin(requireContext(), "我的光环-我的发布") { }
}
}
mStubBinding.myGameCollectionTv -> {
if (UserManager.getInstance().isLoggedIn) {
NewFlatLogUtils.logHaloSelfClick("常用功能", "我的游戏单")
@ -312,7 +300,6 @@ class HaloPersonalFragment : BaseLazyFragment() {
CheckLoginUtils.checkLogin(requireContext(), "我的光环-我的游戏单") { }
}
}
mStubBinding.historyTv -> {
NewFlatLogUtils.logHaloSelfClick("常用功能", "浏览记录")
SensorsBridge.trackHaloSelfClick(
@ -324,7 +311,6 @@ class HaloPersonalFragment : BaseLazyFragment() {
)
startActivity(HistoryActivity.getHistoryIntent(requireContext(), "我的光环-浏览记录"))
}
mStubBinding.myCollectionTv -> {
if (UserManager.getInstance().isLoggedIn) {
NewFlatLogUtils.logHaloSelfClick("常用功能", "我的收藏")
@ -620,7 +606,7 @@ class HaloPersonalFragment : BaseLazyFragment() {
null
)
accelerateSet.add(it[0].messageId)
SPUtils.setStringSet(Constants.SP_ACCELERATE_NOTIFICATION_POP_UP_SET, accelerateSet)
SPUtils.setStringSet(Constants.SP_ACCELERATE_NOTIFICATION_POP_UP_SET, accelerateSet)
}
} else {
accelerateNotificationHandler.doPreProcess(
@ -651,30 +637,16 @@ class HaloPersonalFragment : BaseLazyFragment() {
getConstraintSet(R.id.start).run {
setVisibility(R.id.personal_badge, View.VISIBLE)
clear(R.id.personal_user_name, ConstraintSet.BOTTOM)
clear(R.id.tv_my_assets, ConstraintSet.TOP)
clear(R.id.tv_my_assets, ConstraintSet.BOTTOM)
if (!mUserInfoEntity?.getShortUserId().isNullOrEmpty()) {
setMargin(R.id.personal_user_name, ConstraintSet.TOP, 14F.dip2px())
setMargin(R.id.personal_badge, ConstraintSet.BOTTOM, 14F.dip2px())
setMargin(R.id.userIdTv, ConstraintSet.TOP, 0)
connect(R.id.userIdTv, ConstraintSet.TOP, R.id.personal_user_name, ConstraintSet.BOTTOM)
connect(R.id.userIdTv, ConstraintSet.BOTTOM, R.id.personal_badge, ConstraintSet.TOP)
connect(R.id.tv_my_assets, ConstraintSet.BOTTOM, R.id.personal_badge, ConstraintSet.BOTTOM)
setVisibility(R.id.userIdTv, View.VISIBLE)
} else {
connect(
R.id.personal_user_name,
ConstraintSet.BOTTOM,
R.id.personal_badge,
ConstraintSet.TOP
)
connect(
R.id.personal_badge,
ConstraintSet.TOP,
R.id.personal_user_name,
ConstraintSet.BOTTOM
)
connect(R.id.tv_my_assets, ConstraintSet.BOTTOM, R.id.personal_badge, ConstraintSet.BOTTOM)
connect(R.id.personal_user_name, ConstraintSet.BOTTOM, R.id.personal_badge, ConstraintSet.TOP)
connect(R.id.personal_badge, ConstraintSet.TOP, R.id.personal_user_name, ConstraintSet.BOTTOM)
setVerticalChainStyle(R.id.personal_user_name, ConstraintSet.CHAIN_PACKED)
setVerticalChainStyle(R.id.personal_badge, ConstraintSet.CHAIN_PACKED)
setMargin(R.id.personal_badge, ConstraintSet.TOP, 6F.dip2px())
@ -709,8 +681,6 @@ class HaloPersonalFragment : BaseLazyFragment() {
connect(R.id.personal_user_name, ConstraintSet.BOTTOM, R.id.userIdTv, ConstraintSet.TOP)
connect(R.id.userIdTv, ConstraintSet.TOP, R.id.personal_user_name, ConstraintSet.BOTTOM)
connect(R.id.userIdTv, ConstraintSet.BOTTOM, R.id.personal_user_icon, ConstraintSet.BOTTOM)
connect(R.id.tv_my_assets, ConstraintSet.BOTTOM, R.id.personal_user_icon, ConstraintSet.BOTTOM)
connect(R.id.tv_my_assets, ConstraintSet.TOP, R.id.personal_user_icon, ConstraintSet.TOP)
setMargin(R.id.personal_user_name, ConstraintSet.TOP, 0)
setMargin(R.id.userIdTv, ConstraintSet.TOP, 3F.dip2px())
}
@ -731,11 +701,12 @@ class HaloPersonalFragment : BaseLazyFragment() {
}
private fun inflateRealView() {
mBinding.stub.inflateOrShow()
mBinding.stub.inflate()
mStubBinding.statusBar.goneIf(Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP)
mStubBinding.darkModeIv.goneIf(!(Config.getNightModeSetting()?.icon ?: false))
mStubBinding.darkModeIv.setImageResource(if (mIsDarkModeOn) R.drawable.ic_personal_light_mode else R.drawable.ic_personal_dark_mode)
mStubBinding.ivArrow.enlargeTouchArea()
mStubBinding.loginMessageHint.typeface =
Typeface.createFromAsset(requireContext().assets, Constants.DIN_FONT_PATH)
@ -743,7 +714,7 @@ class HaloPersonalFragment : BaseLazyFragment() {
mStubBinding.toolbarContainer.setOnClickListener(this)
mStubBinding.darkModeIv.setOnClickListener(this)
mStubBinding.personalMsg.setOnClickListener(this)
mStubBinding.tvMyAssets.setOnClickListener(this)
mStubBinding.ivArrow.setOnClickListener(this)
mStubBinding.personalUserName.setOnClickListener(this)
mStubBinding.personalUserIcon.setOnClickListener(this)
mStubBinding.personalBadge.setOnClickListener(this)
@ -753,12 +724,6 @@ class HaloPersonalFragment : BaseLazyFragment() {
mStubBinding.historyTv.setOnClickListener(this)
mStubBinding.myCollectionTv.setOnClickListener(this)
mStubBinding.tvMyAssets.setOnLongClickListener {
val intent = Intent(requireContext(), BatchRegisterActivity::class.java)
startActivity(intent)
return@setOnLongClickListener true
}
val statusBarHeight =
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.KITKAT) 0 else DisplayUtils.getStatusBarHeight(resources)
mStubBinding.motionLayout.minimumHeight = statusBarHeight + 48F.dip2px()
@ -834,10 +799,7 @@ class HaloPersonalFragment : BaseLazyFragment() {
linkId = "",
linkText = ""
)
DirectUtils.directToHelpAndFeedback(
requireContext(),
bundleOf(EntranceConsts.KEY_ENTRANCE to "我的光环")
)
DirectUtils.directToHelpAndFeedback(requireContext(), bundleOf(EntranceConsts.KEY_ENTRANCE to "我的光环"))
}
// 港澳台APP不显示帮助与反馈
root.goneIf(EnvHelper.isGATApp)
@ -1015,7 +977,6 @@ class HaloPersonalFragment : BaseLazyFragment() {
MotionEvent.ACTION_DOWN -> {
mStubBinding.listRefresh.isEnabled = false
}
MotionEvent.ACTION_UP -> {
mStubBinding.listRefresh.isEnabled = true
}
@ -1123,7 +1084,7 @@ class HaloPersonalFragment : BaseLazyFragment() {
fun onEventMainThread(busNetworkState: EBNetworkState) {
if (busNetworkState.isNetworkConnected
&& UserManager.getInstance().isLoggedIn
&& (mUserViewModel.loginObsUserinfo.value == null)
&& (mUserInfoEntity == null || TextUtils.isEmpty(UserManager.getInstance().token))
) {
mUserViewModel.retryCheckLogin()
}
@ -1203,9 +1164,6 @@ class HaloPersonalFragment : BaseLazyFragment() {
R.drawable.ic_personal_my_post
)
)
tvMyAssets.background =
com.gh.gamecenter.common.R.drawable.bg_common_button_stroke_gray.toDrawable(requireContext())
tvMyAssets.setTextColor(com.gh.gamecenter.common.R.color.text_secondary.toColor(requireContext()))
}
}
}

View File

@ -101,14 +101,12 @@ import com.gh.gamecenter.entity.VideoEntity;
import com.gh.gamecenter.entity.VideoTagEntity;
import com.gh.gamecenter.entity.VoteEntity;
import com.gh.gamecenter.entity.WhitePackageListEntity;
import com.gh.gamecenter.feature.entity.AliPayEntity;
import com.gh.gamecenter.feature.entity.AnswerEntity;
import com.gh.gamecenter.feature.entity.ApkEntity;
import com.gh.gamecenter.feature.entity.ArticleDraftEntity;
import com.gh.gamecenter.feature.entity.ArticleEntity;
import com.gh.gamecenter.feature.entity.AvatarBorderEntity;
import com.gh.gamecenter.feature.entity.BackgroundImageEntity;
import com.gh.gamecenter.feature.entity.BaseEntity;
import com.gh.gamecenter.feature.entity.CommentEntity;
import com.gh.gamecenter.feature.entity.CommentnumEntity;
import com.gh.gamecenter.feature.entity.ConcernEntity;
@ -130,12 +128,9 @@ import com.gh.gamecenter.feature.entity.ServerCalendarGame;
import com.gh.gamecenter.feature.entity.ServerCalendarNotifySetting;
import com.gh.gamecenter.feature.entity.SettingsEntity;
import com.gh.gamecenter.feature.entity.SimulatorEntity;
import com.gh.gamecenter.feature.entity.TrialEntity;
import com.gh.gamecenter.feature.entity.UserEntity;
import com.gh.gamecenter.feature.entity.ViewsEntity;
import com.gh.gamecenter.feature.entity.VipEntity;
import com.gh.gamecenter.feature.entity.WXSubscribeMsgConfig;
import com.gh.gamecenter.feature.entity.WechatPayEntity;
import com.gh.gamecenter.gamedetail.entity.BigEvent;
import com.gh.gamecenter.gamedetail.entity.NewGameDetailEntity;
import com.gh.gamecenter.home.custom.model.CustomPageData;
@ -151,7 +146,6 @@ import com.gh.gamecenter.qa.entity.QuestionsIndexEntity;
import com.gh.gamecenter.qa.entity.TopCommunityCategory;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.google.protobuf.Any;
import java.util.ArrayList;
import java.util.HashMap;
@ -3430,7 +3424,6 @@ public interface ApiService {
*/
@PATCH("app/{module}/diverter_visit_time")
Single<ResponseBody> patchDiverterVisitTime(@Path("module") String module, @Body RequestBody body);
/**
* 游戏单搜索(复用 游戏单合集-内容列表 (适用于刷新轮换) 接口实体)
*/
@ -3442,22 +3435,4 @@ public interface ApiService {
*/
@GET("app/column_test_v2/{link_id}/top_games")
Observable<List<GameServerTestTopGame>> getServerTestV2TopGames(@Path("link_id") String linkId);
@POST("pay/wechat/goods/{goodId}/user/{userId}")
Single<BaseEntity<WechatPayEntity>> preOrderWithWechat(@Path("goodId") String goodId, @Path("userId") String userId, @Query("type") String type);
@POST("pay/alipay/goods/{goodId}/user/{userId}")
Single<BaseEntity<AliPayEntity>> preOrderWithAli(@Path("goodId") String goodId, @Path("userId") String userId, @Query("type") String type);
@GET("pay/alipay/order/{orderNo}/user/{userId}")
Single<BaseEntity<Any>> getAliPayResult(@Path("orderNo") String orderNo, @Path("userId") String userId, @Query("type") String type);
@GET("pay/wechat/order/{orderNo}/user/{userId}")
Single<BaseEntity<Any>> getWechatPayResult(@Path("orderNo") String orderNo, @Path("userId") String userId, @Query("type") String type);
@POST("vip/user/{userId}/game")
Single<BaseEntity<Any>> recordAcctGameInfo(@Path("userId") String userId, @Query("type") String type, @Body RequestBody body);
@POST("vip/user/{userId}/recharge_trial")
Single<BaseEntity<TrialEntity>> rechargeTrial(@Path("userId") String userId, @Query("type") String type);
}

View File

@ -1,33 +0,0 @@
package com.gh.gamecenter.room.converter
import androidx.room.TypeConverter
import com.gh.gamecenter.common.utils.toJson
import com.gh.gamecenter.common.utils.toObject
import com.gh.gamecenter.feature.entity.AcctGameInfo
import com.gh.gamecenter.feature.entity.AcctZoneListBean
import com.google.gson.Gson
class AcctGameInfoConverter {
@TypeConverter
fun fromZoneInfo(zoneInfo: AcctGameInfo.ZoneInfo): String {
// 使用Gson将ZoneInfo转换为JSON字符串
return zoneInfo.toJson()
}
@TypeConverter
fun toZoneInfo(value: String): AcctGameInfo.ZoneInfo {
// 将JSON字符串转回ZoneInfo对象
return value.toObject<AcctGameInfo.ZoneInfo>() ?: AcctGameInfo.ZoneInfo(0)
}
@TypeConverter
fun fromZoneList(zoneList: List<AcctGameInfo>): String {
return zoneList.toJson()
}
@TypeConverter
fun toZoneList(value: String): List<AcctGameInfo> {
return value.toObject<List<AcctGameInfo>>() ?: listOf()
}
}

View File

@ -162,7 +162,7 @@ abstract class BaseTabWrapperFragment : BaseLazyFragment(), IMultiTab {
showLoading(true)
}
}
noConnectionStub?.inflateOrShow()
noConnectionStub?.inflate()
} else {
noConnectionBinding?.root?.visibility = View.VISIBLE
}
@ -178,7 +178,7 @@ abstract class BaseTabWrapperFragment : BaseLazyFragment(), IMultiTab {
noDataBinding = ReuseNoneDataBinding.bind(inflated)
noDataBinding?.root?.visibility = View.VISIBLE
}
noDataStub?.inflateOrShow()
noDataStub?.inflate()
} else {
noDataBinding?.root?.visibility = View.VISIBLE
}
@ -194,7 +194,7 @@ abstract class BaseTabWrapperFragment : BaseLazyFragment(), IMultiTab {
loadingBinding = ReuseLoadingBinding.bind(inflated)
loadingBinding?.root?.visibility = View.VISIBLE
}
loadingStub?.inflateOrShow()
loadingStub?.inflate()
} else {
loadingBinding?.root?.visibility = View.VISIBLE
}

View File

@ -968,7 +968,7 @@ class SearchToolbarTabWrapperFragment : BaseTabWrapperFragment(), ISearchToolbar
setPullDownPushInternal(pullDownPush, pullDownPushHandler)
}
try {
binding.autoVideoViewStub.inflateOrShow()
binding.autoVideoViewStub.inflate()
} catch (e: Exception) {
SentryHelper.onEvent("VIEW_STUB_INFLATE_ERROR", "digest", e.localizedMessage)
}

View File

@ -416,7 +416,7 @@ object NDownloadBridge : InnerDownloadListener, IErrorRetryHandler {
}, GlobalDownloadConfig.ERROR_RETRY_INTERVAL)
}
fun isDownloadViaTrafficAllowed(downloadEntity: DownloadEntity?): Boolean {
private fun isDownloadViaTrafficAllowed(downloadEntity: DownloadEntity?): Boolean {
val mNetworkMobileStatus = "2G3G4G5G"
val networkStatus: String? = downloadEntity?.meta?.get(DownloadEntity.NETWORK_STATUS_KEY)
Utils.log("download network status$networkStatus")

View File

@ -57,7 +57,6 @@ import com.gh.gamecenter.common.utils.ImageUtils;
import com.gh.gamecenter.common.utils.SensorsBridge;
import com.gh.gamecenter.core.AppExecutor;
import com.gh.gamecenter.core.iinterface.IApplication;
import com.gh.gamecenter.core.provider.IAcceleratorProvider;
import com.gh.gamecenter.core.provider.IFlavorProvider;
import com.gh.gamecenter.core.provider.IPushProvider;
import com.gh.gamecenter.core.provider.IQGameProvider;
@ -421,11 +420,6 @@ public class HaloApp extends MultiDexApplication {
});
}
}, delay);
IAcceleratorProvider acceleratorProvider = TheRouter.get(IAcceleratorProvider.class);
if (acceleratorProvider != null) {
acceleratorProvider.init(this, PackageUtils.getGhVersionName());
}
}
public void getWebviewAbiList() {

View File

@ -15,7 +15,6 @@ import android.view.MenuItem
import android.view.View
import android.webkit.*
import androidx.annotation.RequiresApi
import androidx.fragment.app.viewModels
import com.gh.common.DefaultJsApi
import com.gh.common.DefaultUrlHandler
import com.gh.common.util.*
@ -36,10 +35,7 @@ import com.gh.gamecenter.common.utils.*
import com.gh.gamecenter.common.utils.PermissionHelper.checkStoragePermissionBeforeAction
import com.gh.gamecenter.common.view.dsbridge.DWebView
import com.gh.gamecenter.core.AppExecutor.uiExecutor
import com.gh.gamecenter.core.callback.AccelerateState
import com.gh.gamecenter.core.callback.OnAccelerateListener
import com.gh.gamecenter.core.iinterface.IScrollable
import com.gh.gamecenter.core.provider.IAcceleratorProvider
import com.gh.gamecenter.core.utils.ElapsedTimeCallback
import com.gh.gamecenter.core.utils.GsonUtils.fromJson
import com.gh.gamecenter.core.utils.MtaHelper.onEventWithTime
@ -48,29 +44,11 @@ import com.gh.gamecenter.databinding.FragmentWebBinding
import com.gh.gamecenter.databinding.FragmentWebWarningBinding
import com.gh.gamecenter.entity.WebShareEntity
import com.gh.gamecenter.eventbus.EBTypeChange
import com.gh.gamecenter.feature.entity.AcctGameInfo
import com.gh.gamecenter.feature.entity.AcctRecordEntity
import com.gh.gamecenter.feature.entity.CommentnumEntity
import com.gh.gamecenter.feature.entity.OrderEntity
import com.gh.gamecenter.feature.eventbus.EBPayState
import com.gh.gamecenter.gamedetail.GameDetailFragment
import com.gh.gamecenter.gamedetail.accelerator.GameDetailAcceleratorUiHelper.Companion.BUTTON_NAME_STOP_ACCELERATOR
import com.gh.gamecenter.gamedetail.accelerator.GameDetailAcceleratorUiHelper.Companion.DISTRICT_SERVER_HAVA
import com.gh.gamecenter.gamedetail.accelerator.GameDetailAcceleratorUiHelper.Companion.MEMBER_TYPE_NOT_LOGIN
import com.gh.gamecenter.gamedetail.accelerator.GameDetailAcceleratorUiHelper.Companion.SCENE_TYPE_NO_GUIDE_LAYER
import com.gh.gamecenter.gamedetail.accelerator.GameDetailAcceleratorUiHelper.Companion.SOURCE_ENTRANCE_MY_ASSETS
import com.gh.gamecenter.gamedetail.accelerator.UserVerifyDialogUtils
import com.gh.gamecenter.gamedetail.accelerator.chain.AcceleratorClient
import com.gh.gamecenter.gamedetail.accelerator.chain.AcceleratorValidator
import com.gh.gamecenter.gamedetail.accelerator.dialog.AcceleratorDialogFragment
import com.gh.gamecenter.gamedetail.accelerator.dialog.AcceleratorDialogFragment.Companion.SPEED_STOP
import com.gh.gamecenter.gamedetail.accelerator.dialog.StartingAcceleratorDialogFragment
import com.gh.gamecenter.livedata.EventObserver
import com.gh.gamecenter.message.MessageDetailFragment
import com.gh.gamecenter.retrofit.RetrofitManager
import com.halo.assistant.member.MemberUseCase
import com.lightgame.utils.Utils
import com.therouter.TheRouter
import com.zhihu.matisse.Matisse
import com.zhihu.matisse.MimeType
import com.zhihu.matisse.engine.impl.PicassoEngine
@ -83,8 +61,6 @@ import kotlin.math.abs
class WebFragment : LazyFragment(), IScrollable {
private val viewModel by viewModels<WebViewModel>()
private var mBinding: FragmentWebBinding? = null
var mMenuShare: MenuItem? = null
var mMenuCollect: MenuItem? = null
@ -138,19 +114,6 @@ class WebFragment : LazyFragment(), IScrollable {
}
}
private val acctListener = object : OnAccelerateListener {
override fun onStateChanged(state: AccelerateState) {
if (state is AccelerateState.Success || state is AccelerateState.Normal) {
onAccelerateCallback()
}
}
override fun onProgress(progress: Int, curGamePkgName: String?, curGameZoneFlag: String?) = Unit
override fun onVipStatusChanged(isNewUser: Boolean, isVip: Boolean) = Unit
}
override fun onCreate(savedInstanceState: Bundle?) {
updateIsWebViewInstalled()
super.onCreate(savedInstanceState)
@ -348,132 +311,7 @@ class WebFragment : LazyFragment(), IScrollable {
mLeaveWebpageToHandleTitle = args.getBoolean(KEY_LEAVE_WEB_PAGE_TO_HANDLE_TITLE, false)
mWebUrl = dealWithUrl(args.getString(EntranceConsts.KEY_URL, ""))
}
mJsApi = DefaultJsApi(
requireContext(),
mEntrance,
this,
mBbsId,
mWebUrl,
mForumName,
object : DefaultJsApi.OnWebClickListener {
override fun onPreOrderWithAli(order: OrderEntity) {
viewModel.memberUseCase.preOrderWithAlipay(order)
}
override fun onPreOrderWithWechat(order: OrderEntity) {
viewModel.memberUseCase.preOrderWithWechat(order)
}
override fun onStartGameAccelerate(accInfo: AcctRecordEntity.AccInfo) {
context?.let {
val iAcceleratorProvider = TheRouter.get(IAcceleratorProvider::class.java)
val game = accInfo.game
val pkg = game.getUniquePackageName() ?: ""
val hasMultiZone = accInfo.isMoreServiceArea
val acctGameInfo =
AcctGameInfo(pkg, AcctGameInfo.ZoneInfo(accInfo.serviceAreaId, accInfo.serviceArea))
val memberType = if (CheckLoginUtils.isLogin()) {
iAcceleratorProvider?.getMemberType() ?: ""
} else {
MEMBER_TYPE_NOT_LOGIN
}
SensorsBridge.trackNetworkAccelerationButtonClick(
game.getUniquePackageName() ?: "",
game.id,
game.name ?: "",
memberType,
if (hasMultiZone) accInfo.serviceArea else DISTRICT_SERVER_HAVA,
SCENE_TYPE_NO_GUIDE_LAYER,
SOURCE_ENTRANCE_MY_ASSETS
)
// h5 页面点击加速
val isVip = iAcceleratorProvider?.isVip() ?: false
val request = AcceleratorValidator.Request(isVip, false, game, SOURCE_ENTRANCE_MY_ASSETS)
AcceleratorClient.newInstance()
.execute(it, request, object : AcceleratorValidator.ValidateListener {
override fun finished(context: Context) {
StartingAcceleratorDialogFragment.show(
context,
acctGameInfo,
game,
false,
hasMultiZone,
SOURCE_ENTRANCE_MY_ASSETS
)
}
})
}
}
override fun onStopGameAccelerate() {
context?.let {
val acctGameRecord = viewModel.memberUseCase.lastAcctRecord
SensorsBridge.trackNetworkAccelerationOtherButtonClick(
acctGameRecord.pkgName,
acctGameRecord.gameId,
acctGameRecord.gameName,
TheRouter.get(IAcceleratorProvider::class.java)?.getMemberType() ?: "",
BUTTON_NAME_STOP_ACCELERATOR,
SOURCE_ENTRANCE_MY_ASSETS
)
AcceleratorDialogFragment.show(
SPEED_STOP,
acctGameRecord.pkgName,
acctGameRecord.gameId,
acctGameRecord.gameName,
SOURCE_ENTRANCE_MY_ASSETS,
it
)
}
}
})
with(viewModel.memberUseCase) {
requestAlipayAction.observe(viewLifecycleOwner, EventObserver { (order, payEntity) ->
viewModel.memberUseCase.sendAlipayRequest(requireActivity(), order, payEntity)
})
requestWechatPayAction.observe(viewLifecycleOwner, EventObserver { (order, payEntity) ->
viewModel.memberUseCase.sendWechatPayRequest(order, payEntity)
})
showUserVerifyDialog.observe(viewLifecycleOwner, EventObserver {
when (it) {
is MemberUseCase.UserVerifyState.UnVerified -> { // 未实名
UserVerifyDialogUtils.showUnVerifiedDialog(
requireContext(),
R.string.archive_dialog_title.toResString(),
it.toast ?: R.string.recharge_without_real_name_description.toResString()
)
}
is MemberUseCase.UserVerifyState.Minors -> { // 已实名:未成年
UserVerifyDialogUtils.showMinorsOrVerifyingDialog(
requireContext(),
R.string.archive_dialog_title.toResString(),
it.toast ?: R.string.recharge_with_minors_description.toResString()
)
}
is MemberUseCase.UserVerifyState.Verifying -> { // 实名审核中
UserVerifyDialogUtils.showMinorsOrVerifyingDialog(
requireContext(),
R.string.archive_dialog_title.toResString(),
it.toast ?: R.string.recharge_with_verifying_description.toResString()
)
}
}
})
}
TheRouter.get(IAcceleratorProvider::class.java)?.bindAccRelatedListener("", acctListener)
mJsApi = DefaultJsApi(requireContext(), mEntrance, this, mBbsId, mWebUrl, mForumName)
}
@SuppressLint("SetJavaScriptEnabled")
@ -524,20 +362,6 @@ class WebFragment : LazyFragment(), IScrollable {
// 用webview打开url
webview.webViewClient = object : WebViewClient() {
override fun shouldInterceptRequest(
view: WebView?,
request: WebResourceRequest
): WebResourceResponse? {
val url = request.url.toString()
// 检查是否是字体请求
if (isFontRequest(url)) {
// 获取字体文件名
return loadFontFromAssets()
}
return super.shouldInterceptRequest(view, request)
}
override fun shouldOverrideUrlLoading(view: WebView, url: String): Boolean {
return if (isAdded) {
val originalUrl = requireArguments().getString(EntranceConsts.KEY_URL, "")
@ -775,42 +599,6 @@ class WebFragment : LazyFragment(), IScrollable {
}
}
private fun onAccelerateCallback() {
val gameId = viewModel.memberUseCase.lastAcctGameId
mBinding?.webview?.callHandler("onAccelerateCallback", arrayOf(gameId)) { _: Any -> }
}
private fun isFontRequest(url: String): Boolean {
return url.lowercase().endsWith(Constants.DIN_FONT_PATH)
}
/**
* 从assets加载字体文件
*/
private fun loadFontFromAssets(): WebResourceResponse? {
return try {
val inputStream = requireContext().assets.open(Constants.DIN_FONT_PATH)
val mineType = "font/ttf"
WebResourceResponse(
mineType,
"UTF-8",
inputStream
).apply {
// 设置响应头
setStatusCodeAndReasonPhrase(200, "OK")
setResponseHeaders(
mapOf(
"Access-Control-Allow-Origin" to "*",
"Content-Type" to mineType
)
)
}
} catch (e: Exception) {
null
}
}
override fun onDestroy() {
super.onDestroy()
if (!TextUtils.isEmpty(mGameName)) {
@ -821,7 +609,6 @@ class WebFragment : LazyFragment(), IScrollable {
removeJavascriptObject("share")
removeJavascriptObject("internal")
}
TheRouter.get(IAcceleratorProvider::class.java)?.unBindAccRelatedListener(acctListener)
}
private fun getNewsCommentNum() {
@ -894,16 +681,6 @@ class WebFragment : LazyFragment(), IScrollable {
}
}
@Subscribe(threadMode = ThreadMode.MAIN)
fun onEventMainThread(data: EBPayState) {
val payStatus = when (data) {
EBPayState.PaySuccess -> "success"
EBPayState.PayFail -> "fail"
EBPayState.PayCancel -> "cancel"
}
mBinding?.webview?.callHandler("onPayCallback", arrayOf(payStatus)) { _: Any -> }
}
override fun onFragmentResume() {
super.onFragmentResume()
mBinding?.webview?.callHandler("videoPlay") { _: Any? -> }

View File

@ -1,14 +0,0 @@
package com.halo.assistant.fragment
import androidx.lifecycle.ViewModel
import com.halo.assistant.member.MemberUseCase
class WebViewModel:ViewModel() {
val memberUseCase = MemberUseCase()
override fun onCleared() {
super.onCleared()
memberUseCase.onClear()
}
}

View File

@ -1,30 +0,0 @@
package com.halo.assistant.member
import android.graphics.Color
import android.os.Bundle
import com.gh.gamecenter.common.base.activity.BaseActivity
import com.gh.gamecenter.core.utils.DisplayUtils
import com.halo.assistant.fragment.WebFragment
class MemberActivity : BaseActivity() {
override fun getLayoutId(): Int {
return com.gh.gamecenter.common.R.layout.activity_member
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
DisplayUtils.setLightStatusBar(this, true)
setStatusBarColor(Color.TRANSPARENT)
val containerFragment = supportFragmentManager.findFragmentByTag(WebFragment::class.java.name)
?: WebFragment().with(intent.extras)
// 若 placeholder 外层为 RelativeLayout 的话,会出现莫名的偏移
supportFragmentManager.beginTransaction()
.replace(
com.gh.gamecenter.selector.R.id.layout_activity_content,
containerFragment,
WebFragment::class.java.name
)
.commitAllowingStateLoss()
}
}

View File

@ -1,181 +0,0 @@
package com.halo.assistant.member
import android.annotation.SuppressLint
import android.app.Activity
import com.gh.gamecenter.common.utils.SensorsBridge
import com.gh.gamecenter.common.utils.singleToMain
import com.gh.gamecenter.common.utils.toRequestBody
import com.gh.gamecenter.core.provider.IAcceleratorProvider
import com.gh.gamecenter.core.provider.IAliPayProvider
import com.gh.gamecenter.core.provider.IWechatPayProvider
import com.gh.gamecenter.feature.entity.*
import com.gh.gamecenter.feature.eventbus.EBPayState
import com.gh.gamecenter.login.user.UserManager
import com.gh.gamecenter.login.user.UserRepository
import com.gh.gamecenter.retrofit.RetrofitManager
import com.gh.gamecenter.retrofit.service.ApiService
import com.therouter.TheRouter
import io.reactivex.Flowable
import io.reactivex.Single
import io.reactivex.schedulers.Schedulers
import org.greenrobot.eventbus.EventBus
import java.util.concurrent.TimeUnit
/**
* 会员相关单利类
* 会保存一些加速器状态相关数据
* 加速器相关的操作,统一放在这里
*/
class MemberRepository private constructor(private val api: ApiService) {
// 最后一次加速的游戏id失败或者成功都会记录
private var _acctGameRecord: AcctGameRecord? = null
val acctGameRecord: AcctGameRecord
get() = _acctGameRecord ?: AcctGameRecord()
fun setAcctGameRecord(record: AcctGameRecord) {
_acctGameRecord = record
}
fun preOrderWithAli(goodId: String): Single<AliPayEntity> {
val userId = UserManager.getInstance().userId
return api.preOrderWithAli(goodId, userId, VIP_TYPE)
.map {
it.data
}
}
@SuppressLint("CheckResult")
fun payWithAli(order: OrderEntity, payEntity: AliPayEntity, activity: Activity) {
TheRouter.get(IAliPayProvider::class.java)
?.sendRequest(activity, payEntity.orderStr)
?.flatMap {
if (it == 0) {
// 需要后端确认支付结果
getAlipayResult(payEntity.orderNo)
} else {
Single.just(it)
}
}
?.compose(singleToMain())
?.subscribe({
val (payState, result) = when (it) {
0 -> EBPayState.PaySuccess to RECHARGE_RESULT_SUCCESS
1 -> EBPayState.PayCancel to RECHARGE_RESULT_CANCEL
else -> EBPayState.PayFail to RECHARGE_RESULT_FAILURE
}
if (payState is EBPayState.PaySuccess) {
refreshVipStatus()
}
SensorsBridge.trackMemberRechargeResult(
PAYMENT_TYPE_ALIPAY,
order.setMenuName,
order.paymentAmount,
result
)
EventBus.getDefault().post(payState)
}, {
// 支付失败
EventBus.getDefault().post(EBPayState.PayFail)
})
}
private fun getAlipayResult(orderNo: String): Single<Int> {
val userId = UserManager.getInstance().userId
return RetrofitManager.getInstance().newApi
.getAliPayResult(orderNo, userId, VIP_TYPE)
.retryWhen { errors ->
errors.zipWith(Flowable.range(1, 3)) { error, attempt ->
if (attempt <= 3) {
attempt
} else {
throw error
}
}.flatMap {
Flowable.timer(1, TimeUnit.SECONDS)
}
}.map {
if (it.data != null) 0 else 2
}
}
fun preOrderWithWechat(goodId: String): Single<BaseEntity<WechatPayEntity>> {
val userId = UserManager.getInstance().userId
return api.preOrderWithWechat(goodId, userId, VIP_TYPE)
}
fun sendWechatPayRequest(order: OrderEntity, payEntity: WechatPayEntity) {
TheRouter.get(IWechatPayProvider::class.java)?.payRequest(order, payEntity)
}
fun getWechatPayResult(orderNo: String): Single<Boolean> {
val userId = UserManager.getInstance().userId
return RetrofitManager.getInstance().newApi
.getWechatPayResult(orderNo, userId, VIP_TYPE)
.retryWhen { errors ->
errors.zipWith(Flowable.range(1, 3)) { error, attempt ->
if (attempt <= 3) {
attempt
} else {
throw error
}
}.flatMap {
Flowable.timer(1, TimeUnit.SECONDS)
}
}.map {
it.data != null
}
}
private fun refreshVipStatus() {
// 先刷新本地状态,支付成功,肯定是付费会员
TheRouter.get(IAcceleratorProvider::class.java)?.setVipEntity(
VipEntity(
_vipStatus = true,
_isNewUser = false,
_isTryVip = false
)
)
val userId = UserManager.getInstance().userId
if (userId.isNotBlank()) {
UserRepository.getInstance().refreshVipStatus(userId, true)
}
}
@SuppressLint("CheckResult")
fun recordAcctGameInfo(gameId: String, zoneId: Int, zoneName: String, hasMultiZone: Boolean) {
val userId = UserManager.getInstance().userId
val body =
hashMapOf(
"game_id" to gameId,
"service_area_id" to zoneId,
"service_area" to zoneName,
"is_more_service_area" to hasMultiZone
).toRequestBody()
RetrofitManager.getInstance().newApi
.recordAcctGameInfo(userId, VIP_TYPE, body)
.subscribeOn(Schedulers.io())
.subscribe({}, {})
}
fun rechargeTrial(userId: String) =
api.rechargeTrial(userId, VIP_TYPE)
companion object {
private const val VIP_TYPE = "gjonline_vip"
const val RECHARGE_RESULT_SUCCESS = "充值成功"
private const val RECHARGE_RESULT_CANCEL = "充值取消"
const val RECHARGE_RESULT_FAILURE = "充值失败"
const val PAYMENT_TYPE_ALIPAY = "支付宝"
const val PAYMENT_TYPE_WECHAT = "微信"
val instance by lazy {
MemberRepository(RetrofitManager.getInstance().newApi)
}
}
data class AcctGameRecord(
val gameId: String = "",
val pkgName: String = "",
val gameName: String = ""
)
}

View File

@ -1,147 +0,0 @@
package com.halo.assistant.member
import android.annotation.SuppressLint
import android.app.Activity
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import com.gh.gamecenter.common.entity.ErrorEntity
import com.gh.gamecenter.common.retrofit.BiResponse
import com.gh.gamecenter.common.utils.singleToMain
import com.gh.gamecenter.common.utils.toObject
import com.gh.gamecenter.feature.entity.*
import com.gh.gamecenter.gamedetail.accelerator.AccelerationDataBase
import com.gh.gamecenter.livedata.Event
import com.halo.assistant.member.MemberUseCase.UserVerifyState.Companion.ERROR_CODE_MINORS
import com.halo.assistant.member.MemberUseCase.UserVerifyState.Companion.ERROR_CODE_UNVERIFIED
import com.halo.assistant.member.MemberUseCase.UserVerifyState.Companion.ERROR_CODE_VERIFYING
import io.reactivex.Single
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.schedulers.Schedulers
import retrofit2.HttpException
class MemberUseCase {
private val compositeDisposable = CompositeDisposable()
private val repository = MemberRepository.instance
val lastAcctGameId: String
get() = repository.acctGameRecord.gameId
val lastAcctRecord: MemberRepository.AcctGameRecord
get() = repository.acctGameRecord
fun setLastAcctGameRecord(game: GameEntity) {
repository.setAcctGameRecord(
MemberRepository.AcctGameRecord(game.id, game.getUniquePackageName() ?: "", game.name ?: "")
)
}
private val _showUserVerifyDialog = MutableLiveData<Event<UserVerifyState>>()
val showUserVerifyDialog: LiveData<Event<UserVerifyState>> = _showUserVerifyDialog
private val _requestAlipayAction = MutableLiveData<Event<Pair<OrderEntity, AliPayEntity>>>()
val requestAlipayAction: LiveData<Event<Pair<OrderEntity, AliPayEntity>>> = _requestAlipayAction
fun preOrderWithAlipay(order: OrderEntity) {
repository.preOrderWithAli(order.goodId)
.compose(singleToMain())
.subscribe(object : BiResponse<AliPayEntity>() {
override fun onSuccess(data: AliPayEntity) {
_requestAlipayAction.value = Event(order to data)
}
override fun onFailure(exception: Exception) {
super.onFailure(exception)
handlePreOrderError(exception)
}
}).let(compositeDisposable::add)
}
fun sendAlipayRequest(activity: Activity, order: OrderEntity, payEntity: AliPayEntity) {
repository.payWithAli(order, payEntity, activity)
}
private val _requestWechatPayAction = MutableLiveData<Event<Pair<OrderEntity, WechatPayEntity>>>()
val requestWechatPayAction: LiveData<Event<Pair<OrderEntity, WechatPayEntity>>> = _requestWechatPayAction
fun preOrderWithWechat(order: OrderEntity) {
repository.preOrderWithWechat(order.goodId)
.compose(singleToMain())
.subscribe(object : BiResponse<BaseEntity<WechatPayEntity>>() {
override fun onSuccess(data: BaseEntity<WechatPayEntity>) {
val payEntity = data.data
if (payEntity != null) {
_requestWechatPayAction.value = Event(order to payEntity)
}
}
override fun onFailure(exception: Exception) {
super.onFailure(exception)
handlePreOrderError(exception)
}
}).let(compositeDisposable::add)
}
fun sendWechatPayRequest(order: OrderEntity, payEntity: WechatPayEntity) {
repository.sendWechatPayRequest(order, payEntity)
}
private fun handlePreOrderError(exception: Exception) {
if (exception is HttpException) {
val errorEntity = exception.response().errorBody()?.string()?.toObject<ErrorEntity>()
val code = errorEntity?.code ?: 0
val toast = errorEntity?.toast
when (code) {
ERROR_CODE_UNVERIFIED -> UserVerifyState.UnVerified(toast)
ERROR_CODE_MINORS -> UserVerifyState.Minors(toast)
ERROR_CODE_VERIFYING -> UserVerifyState.Verifying(toast)
else -> null
}?.let {
_showUserVerifyDialog.value = Event(it)
}
}
}
@SuppressLint("CheckResult")
fun insertAcctGameInfo(acctGameInfo: AcctGameInfo) {
AccelerationDataBase.instance.accelerationDao()
.upsertAcctGameInfo(acctGameInfo)
.subscribeOn(Schedulers.io())
.subscribe({
}, {})
}
fun recordAcctGameInfo(gameId: String, acctGameInfo: AcctGameInfo, hasMultiZone: Boolean) {
// 如果是 web 端 启动的加速,则不需要记录
repository.recordAcctGameInfo(
gameId,
acctGameInfo.zoneInfo.id,
acctGameInfo.zoneInfo.cnName ?: "",
hasMultiZone
)
}
fun rechargeTrial(userId: String): Single<BaseEntity<TrialEntity>> = repository.rechargeTrial(userId)
fun onClear() {
compositeDisposable.clear()
}
sealed class UserVerifyState(val toast: String?) {
class UnVerified(toast: String?) : UserVerifyState(toast)
class Minors(toast: String?) : UserVerifyState(toast)
class Verifying(toast: String?) : UserVerifyState(toast)
companion object {
const val ERROR_CODE_UNVERIFIED = 403129
const val ERROR_CODE_MINORS = 403128
const val ERROR_CODE_VERIFYING = 403130
}
}
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,7 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<corners android:radius="100dp" />
<stroke
android:width="4dp"
android:color="@color/ui_surface" />
</shape>

View File

@ -1,10 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:pathData="M18.705,4.64C17.097,4.269 13.525,3.991 9.853,7.563C9.646,7.765 9.361,7.867 9.073,7.843L6.446,7.624C5.806,7.571 5.179,7.828 4.761,8.315L3.593,9.678L5.447,10.606C5.786,10.775 6,11.121 6,11.5V12.586L11.414,18H12.5C12.879,18 13.225,18.214 13.394,18.553L14.322,20.407L15.685,19.239C16.172,18.821 16.429,18.194 16.376,17.554L16.157,14.927C16.133,14.639 16.235,14.354 16.437,14.147C20.009,10.475 19.731,6.903 19.36,5.295C19.283,4.96 19.039,4.717 18.705,4.64ZM8.793,5.813C12.972,1.971 17.136,2.226 19.155,2.691C20.234,2.94 21.06,3.766 21.309,4.845C21.774,6.864 22.029,11.028 18.187,15.207L18.369,17.388C18.476,18.668 17.961,19.922 16.986,20.757L15.623,21.926C14.635,22.772 13.115,22.465 12.533,21.302L11.882,20H11C10.735,20 10.48,19.895 10.293,19.707L4.293,13.707C4.105,13.52 4,13.265 4,13V12.118L2.698,11.467C1.535,10.885 1.227,9.365 2.074,8.377L3.242,7.014C4.078,6.039 5.332,5.524 6.612,5.631L8.793,5.813ZM13,10C12.448,10 12,10.448 12,11C12,11.552 12.448,12 13,12C13.552,12 14,11.552 14,11C14,10.448 13.552,10 13,10ZM10,11C10,9.343 11.343,8 13,8C14.657,8 16,9.343 16,11C16,12.657 14.657,14 13,14C11.343,14 10,12.657 10,11ZM4.949,17.316C5.123,16.792 4.84,16.226 4.316,16.051C3.792,15.877 3.226,16.16 3.051,16.684C2.765,17.542 2.632,18.506 2.567,19.222C2.533,19.587 2.517,19.902 2.508,20.127C2.504,20.24 2.502,20.33 2.501,20.394C2.501,20.426 2.5,20.451 2.5,20.469L2.5,20.49L2.5,20.497L2.5,20.499L2.5,20.499L2.5,20.5C2.5,20.5 2.5,20.5 3.5,20.5H2.5C2.5,21.052 2.948,21.5 3.5,21.5V20.5C3.5,21.5 3.5,21.5 3.5,21.5H3.501H3.501L3.503,21.5L3.51,21.5L3.531,21.5C3.549,21.5 3.574,21.499 3.606,21.499C3.67,21.498 3.76,21.496 3.873,21.492C4.098,21.483 4.413,21.467 4.778,21.433C5.494,21.368 6.458,21.235 7.316,20.949C7.84,20.774 8.123,20.208 7.949,19.684C7.774,19.16 7.208,18.877 6.684,19.051C6.042,19.265 5.256,19.382 4.597,19.442L4.555,19.445L4.558,19.403C4.618,18.744 4.735,17.958 4.949,17.316Z"
android:fillColor="#000000"
android:fillType="evenOdd"/>
</vector>

View File

@ -1,14 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<group>
<clip-path
android:pathData="M0,0h24v24h-24z"/>
<path
android:pathData="M4.793,4.793C5.183,4.402 5.817,4.402 6.207,4.793L12,10.586L17.793,4.793C18.183,4.402 18.817,4.402 19.207,4.793C19.598,5.183 19.598,5.817 19.207,6.207L13.414,12L19.207,17.793C19.598,18.183 19.598,18.817 19.207,19.207C18.817,19.598 18.183,19.598 17.793,19.207L12,13.414L6.207,19.207C5.817,19.598 5.183,19.598 4.793,19.207C4.402,18.817 4.402,18.183 4.793,17.793L10.586,12L4.793,6.207C4.402,5.817 4.402,5.183 4.793,4.793Z"
android:fillColor="#000000"
android:fillType="evenOdd"/>
</group>
</vector>

View File

@ -1,14 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="18dp"
android:height="18dp"
android:viewportWidth="24"
android:viewportHeight="24">
<group>
<clip-path
android:pathData="M0,0h24v24h-24z"/>
<path
android:pathData="M4.793,4.793C5.183,4.402 5.817,4.402 6.207,4.793L12,10.586L17.793,4.793C18.183,4.402 18.817,4.402 19.207,4.793C19.598,5.183 19.598,5.817 19.207,6.207L13.414,12L19.207,17.793C19.598,18.183 19.598,18.817 19.207,19.207C18.817,19.598 18.183,19.598 17.793,19.207L12,13.414L6.207,19.207C5.817,19.598 5.183,19.598 4.793,19.207C4.402,18.817 4.402,18.183 4.793,17.793L10.586,12L4.793,6.207C4.402,5.817 4.402,5.183 4.793,4.793Z"
android:fillColor="#000000"
android:fillType="evenOdd"/>
</group>
</vector>

View File

@ -1,24 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt"
android:width="52dp"
android:height="18dp"
android:viewportWidth="52"
android:viewportHeight="18">
<path
android:pathData="M0,9C0,4.029 4.029,0 9,0H43C47.971,0 52,4.029 52,9V16C52,17.105 51.105,18 50,18H9C4.029,18 0,13.971 0,9Z">
<aapt:attr name="android:fillColor">
<gradient
android:startX="0"
android:startY="9"
android:endX="52"
android:endY="9"
android:type="linear">
<item android:offset="0" android:color="#FFFFC247"/>
<item android:offset="1" android:color="#FFFF9933"/>
</gradient>
</aapt:attr>
</path>
<path
android:pathData="M13.79,7.92H11.54C11.49,8.45 11.43,8.98 11.33,9.47H13.79V7.92ZM8.43,9.47H10.35C10.46,8.98 10.51,8.46 10.56,7.92H8.43V9.47ZM11.62,6.09H9.34C9.08,6.43 8.79,6.77 8.48,7.09H10.87C11.13,6.8 11.4,6.43 11.62,6.09ZM12.89,12.77H14.22C14.6,12.77 14.67,12.58 14.71,11.43C14.92,11.58 15.31,11.73 15.56,11.79C15.45,13.22 15.2,13.6 14.29,13.6H12.76C11.7,13.6 11.43,13.33 11.43,12.42V10.3H11.11C10.61,11.82 9.54,13.02 7.04,13.71C6.94,13.47 6.71,13.12 6.51,12.93C8.67,12.39 9.63,11.46 10.1,10.3H7.5V7.99C7.35,8.11 7.2,8.23 7.04,8.34C6.89,8.13 6.59,7.8 6.37,7.66C7.72,6.77 8.68,5.56 9.21,4.58L10.23,4.77C10.13,4.96 10.02,5.13 9.89,5.32H12.15L12.29,5.28L12.94,5.69C12.69,6.13 12.33,6.65 11.97,7.09H14.77V10.3H12.4V12.41C12.4,12.72 12.47,12.77 12.89,12.77ZM19.48,7.08H18.19C18.16,7.29 18.13,7.48 18.09,7.68H19.34C19.42,7.49 19.46,7.29 19.48,7.08ZM20.34,5.84V6.43H21.72V5.84H20.34ZM23.87,5.84H22.6V6.43H23.87V5.84ZM21.72,7.68V7.08H20.33C20.32,7.29 20.29,7.48 20.25,7.68H21.72ZM17.84,12.32V9.8C17.59,9.88 17.33,9.95 17.05,10.01C16.97,9.81 16.74,9.46 16.58,9.31C17.77,9.05 18.49,8.72 18.91,8.32H17.14C17.25,7.81 17.37,7.06 17.44,6.44H17.79V6.43H19.5V5.84H17.11V5.2H19.5V4.61H20.34V5.2H21.72V4.61H22.6V5.2H24.72V7.08H22.6V7.68H25.33C25.33,7.68 25.32,7.86 25.31,7.97C25.25,8.63 25.18,8.97 25.02,9.14C24.89,9.29 24.71,9.35 24.5,9.36C24.32,9.37 23.98,9.37 23.6,9.35C23.59,9.17 23.52,8.91 23.44,8.74C23.72,8.78 23.96,8.78 24.06,8.78C24.17,8.78 24.23,8.77 24.29,8.71C24.33,8.65 24.37,8.55 24.4,8.32H22.6V9.37H21.72V8.32H20.01C19.75,8.81 19.28,9.24 18.47,9.58H24.22V12.23H23.28V10.35H18.74V12.32H17.84ZM20.66,10.72H21.59C21.21,12.46 20.22,13.36 16.83,13.78C16.77,13.55 16.59,13.18 16.43,12.99C19.55,12.68 20.34,12.04 20.66,10.72ZM21.19,12.48L21.68,11.85C22.9,12.14 24.59,12.67 25.49,13.07L24.97,13.79C24.13,13.39 22.44,12.81 21.19,12.48ZM26.94,10.46V9.55H35.13V10.46H30.85C30.31,11.17 29.68,11.86 29.03,12.45L33.1,12.17C32.77,11.79 32.41,11.42 32.07,11.11L32.86,10.7C33.74,11.47 34.66,12.53 35.11,13.27L34.27,13.78C34.14,13.55 33.97,13.27 33.75,12.99C28.65,13.39 28.05,13.42 27.62,13.59C27.56,13.38 27.42,12.9 27.3,12.64C27.53,12.59 27.76,12.41 28.06,12.13C28.32,11.91 28.97,11.24 29.58,10.46H26.94ZM29.04,7.64H33.11C32.31,7.13 31.57,6.54 31.02,6C30.45,6.61 29.78,7.15 29.04,7.64ZM31.01,4.59L31.87,4.98C31.78,5.12 31.67,5.26 31.56,5.4C32.5,6.28 34.09,7.28 35.63,7.8C35.43,7.98 35.12,8.36 34.98,8.61C34.43,8.39 33.88,8.11 33.36,7.8V8.5H28.68V7.87C28.17,8.18 27.64,8.46 27.08,8.72C26.95,8.48 26.63,8.08 26.42,7.9C28.33,7.13 30.09,5.9 31.01,4.59ZM38.85,5.84V6.8H43.17V5.84H38.85ZM37.88,5.04H44.2V7.6H37.88V5.04ZM40.44,9.8H41.45V10.71C41.45,11.76 40.93,13.03 37.28,13.86C37.16,13.65 36.88,13.29 36.65,13.09C40.16,12.43 40.44,11.43 40.44,10.69V9.8ZM41.31,12.41L41.77,11.72C42.9,12.07 44.53,12.65 45.39,13.05L44.91,13.85C44.1,13.43 42.49,12.81 41.31,12.41ZM37.5,8.39H44.61V11.93H43.61V9.25H38.47V12.02H37.5V8.39Z"
android:fillColor="#ffffff"/>
</vector>

File diff suppressed because one or more lines are too long

View File

@ -1,9 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="8dp"
android:height="8dp"
android:viewportWidth="8"
android:viewportHeight="8">
<path
android:pathData="M6.4395,2C7.0684,2 7.418,2.7274 7.0252,3.2185L4.5856,6.2679C4.2854,6.6432 3.7146,6.6432 3.4144,6.2679L0.9748,3.2185C0.582,2.7274 0.9316,2 1.5605,2H6.4395Z"
android:fillColor="#000000"/>
</vector>

View File

@ -1,16 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto">
<Button
android:id="@+id/btn_register"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="批量注册"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toBottomOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -279,7 +279,6 @@
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@id/detail_progressbar"
app:layout_constraintHorizontal_weight="76"
app:layout_constraintStart_toEndOf="@+id/iv_switch"
app:layout_constraintTop_toTopOf="parent"
tools:visibility="visible">
@ -314,8 +313,7 @@
app:download_button_show_progress="true"
app:download_button_text_size="@dimen/primary_text_size"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@id/cl_speed_container"
app:layout_constraintHorizontal_weight="76"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/localDownloadContainer"
app:layout_constraintTop_toTopOf="parent"
app:layout_goneMarginStart="24dp" />
@ -389,167 +387,6 @@
app:layout_constraintStart_toStartOf="@id/detail_progressbar"
app:layout_constraintTop_toTopOf="@id/detail_progressbar"
tools:text="选择下载你的版本" />
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/cl_speed_container"
android:layout_width="0dp"
android:layout_height="40dp"
android:layout_marginStart="8dp"
android:layout_marginTop="10dp"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_weight="144"
app:layout_constraintStart_toEndOf="@id/detail_progressbar"
app:layout_constraintTop_toTopOf="parent"
tools:visibility="visible">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/cl_speed"
android:layout_width="0dp"
android:layout_height="0dp"
android:background="@drawable/bg_common_button_fill_gradient_blue"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:visibility="gone">
<View
android:id="@+id/v_more_zone"
android:layout_width="36dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:id="@+id/iv_more_zone"
android:layout_width="8dp"
android:layout_height="8dp"
app:layout_constraintBottom_toBottomOf="@id/v_more_zone"
app:layout_constraintEnd_toEndOf="@id/v_more_zone"
app:layout_constraintStart_toStartOf="@id/v_more_zone"
app:layout_constraintTop_toTopOf="@id/v_more_zone"
app:srcCompat="@drawable/ic_triangle_down"
app:tint="@color/text_aw_primary" />
<View
android:id="@+id/v_divider"
android:layout_width="1dp"
android:layout_height="12dp"
android:background="@color/white_alpha_20"
app:layout_constraintBottom_toBottomOf="@id/v_more_zone"
app:layout_constraintEnd_toStartOf="@id/v_more_zone"
app:layout_constraintTop_toTopOf="parent" />
<androidx.constraintlayout.widget.Group
android:id="@+id/g_more_zone"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:constraint_referenced_ids="v_divider,iv_more_zone,v_more_zone" />
<View
android:id="@+id/v_guide_end"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginStart="4dp"
app:layout_constraintStart_toEndOf="@id/v_divider"
app:layout_constraintTop_toTopOf="@id/v_divider" />
<View
android:id="@+id/v_speed_content"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@id/v_divider"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<LinearLayout
android:layout_width="0dp"
android:layout_height="0dp"
android:gravity="center"
android:orientation="horizontal"
android:paddingHorizontal="16dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@id/v_guide_end"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<ImageView
android:id="@+id/iv_speed"
android:layout_width="14dp"
android:layout_height="14dp"
app:srcCompat="@drawable/ic_basic_accelerator"
app:tint="@color/text_aw_primary" />
<TextView
android:id="@+id/tv_speed"
style="@style/TextBody2B"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="2dp"
android:ellipsize="end"
android:gravity="center"
android:maxLines="1"
android:text="@string/network_acceleration"
android:textColor="@color/text_aw_primary" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
<TextView
android:id="@+id/tv_stop_speed"
style="@style/TextBody2B"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginStart="24dp"
android:background="@drawable/bg_common_button_light_fill_gray"
android:gravity="center"
android:maxLines="1"
android:text="@string/stop_speed"
android:textColor="@color/text_secondary"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@id/tv_enter_game"
app:layout_constraintHorizontal_weight="1"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/tv_enter_game"
style="@style/TextBody2B"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginStart="8dp"
android:background="@drawable/bg_common_button_light_fill_blue"
android:gravity="center"
android:maxLines="1"
android:text="@string/enter_game"
android:textColor="@color/text_theme"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_weight="1"
app:layout_constraintStart_toEndOf="@id/tv_stop_speed"
app:layout_constraintTop_toTopOf="parent" />
<androidx.constraintlayout.widget.Group
android:id="@+id/g_accelerating"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="gone"
app:constraint_referenced_ids="tv_stop_speed,tv_enter_game" />
</androidx.constraintlayout.widget.ConstraintLayout>
<ImageView
android:id="@+id/iv_free_vip_tag"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="12dp"
android:visibility="gone"
app:layout_constraintBottom_toTopOf="@id/cl_speed_container"
app:layout_constraintEnd_toEndOf="@id/cl_speed_container"
app:layout_constraintTop_toTopOf="@id/cl_speed_container"
app:srcCompat="@drawable/ic_free_vip_tag" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -1,34 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="300dp"
android:orientation="vertical">
<com.gh.gamecenter.common.view.titlebar.BottomSheetTitleView
android:id="@+id/title_view"
android:layout_width="match_parent"
android:layout_height="48dp"
app:left_style="title"
app:right_icon_color="@color/text_tertiary"
app:right_icon_resource="@drawable/ic_basic_x_18"
app:right_style="icon"
app:title="@string/select_the_acceleration_zone" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_zone"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/ui_surface"
android:paddingHorizontal="16dp"
android:paddingBottom="16dp"
android:clipToPadding="false"
tools:itemCount="3"
tools:listitem="@layout/recycler_accelerator_zone" />
</LinearLayout>
</LinearLayout>

View File

@ -1,49 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/background_shape_white_radius_8"
android:padding="24dp">
<TextView
android:id="@+id/tv_title"
style="@style/TextHeadline"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/hint"
android:textColor="@color/text_primary"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/tv_content"
style="@style/TextBody2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:gravity="center"
android:textColor="@color/text_secondary"
android:text="@string/speed_failure_tips"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_title" />
<TextView
android:id="@+id/tv_submit"
style="@style/BtnRegularStyle"
android:layout_width="0dp"
android:layout_marginTop="24dp"
android:textColor="@color/primary_theme"
android:background="@drawable/bg_common_button_light_fill_blue"
android:text="@string/contact_service"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_content" />
</androidx.constraintlayout.widget.ConstraintLayout>
</FrameLayout>

View File

@ -1,65 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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="wrap_content">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/background_shape_white_radius_8"
android:padding="24dp">
<TextView
android:id="@+id/tv_title"
style="@style/TextHeadline"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/hint"
android:textColor="@color/text_primary"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/tv_content"
style="@style/TextBody2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:gravity="center"
android:textColor="@color/text_secondary"
android:textSize="14sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_title" />
<TextView
android:id="@+id/tv_cancel"
style="@style/BtnRegularStyle"
android:layout_width="0dp"
android:layout_marginTop="24dp"
android:background="@drawable/bg_common_button_light_fill_gray"
android:text="@string/not_started_yet"
android:textColor="@color/text_secondary"
android:textSize="14sp"
app:layout_constraintEnd_toStartOf="@id/tv_submit"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_content" />
<TextView
android:id="@+id/tv_submit"
style="@style/BtnRegularStyle"
android:layout_width="0dp"
android:layout_marginStart="12dp"
android:layout_marginTop="24dp"
android:background="@drawable/bg_common_button_fill_blue"
android:text="@string/continue_to_start"
app:layout_goneMarginStart="0dp"
android:textColor="@color/text_aw_primary"
android:textSize="14sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/tv_cancel"
app:layout_constraintTop_toBottomOf="@id/tv_content" />
</androidx.constraintlayout.widget.ConstraintLayout>
</FrameLayout>

View File

@ -1,49 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/background_shape_white_radius_8"
android:padding="24dp">
<TextView
android:id="@+id/tv_title"
style="@style/TextHeadline"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/hint"
android:textColor="@color/text_primary"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/tv_content"
style="@style/TextBody2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:gravity="center"
android:textColor="@color/text_secondary"
android:text="@string/enable_vip_tips"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_title" />
<TextView
android:id="@+id/tv_submit"
style="@style/BtnRegularStyle"
android:layout_width="0dp"
android:layout_marginTop="24dp"
android:textColor="@color/text_aw_primary"
android:background="@drawable/bg_common_button_fill_blue"
android:text="@string/go_to_activate"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_content" />
</androidx.constraintlayout.widget.ConstraintLayout>
</FrameLayout>

View File

@ -1,35 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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="160dp"
android:layout_height="88dp">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="160dp"
android:layout_height="88dp"
android:background="@drawable/background_shape_white_radius_8">
<ProgressBar
android:id="@+id/progress_bar"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_marginTop="16dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:progressDrawable="@drawable/bg_horizontal_progressbar"/>
<TextView
android:id="@+id/tv_progress"
style="@style/TextBody2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:textColor="@color/text_secondary"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/progress_bar"
tools:text="加速中...16%" />
</androidx.constraintlayout.widget.ConstraintLayout>
</FrameLayout>

View File

@ -132,18 +132,11 @@
tools:visibility="visible" />
</RelativeLayout>
<TextView
android:id="@+id/tv_my_assets"
style="@style/TextButton3"
android:layout_width="72dp"
android:layout_height="28dp"
android:layout_marginEnd="20dp"
android:background="@drawable/bg_common_button_stroke_gray"
android:gravity="center"
android:text="我的资产"
android:textColor="@color/text_secondary"
app:layout_constraintEnd_toEndOf="parent"
tools:layout_editor_absoluteY="133dp" />
<ImageView
android:id="@+id/iv_arrow"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:srcCompat="@drawable/ic_jump" />
</com.gh.common.view.CollapsingMotionLayout>
</com.google.android.material.appbar.AppBarLayout>

View File

@ -1,40 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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"
android:gravity="bottom">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/cl_container"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/iv_background"
android:layout_width="188dp"
android:layout_height="119dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@drawable/bg_accelerator_guide" />
<View
android:id="@+id/v_i_know"
android:layout_width="80dp"
android:layout_height="32dp"
android:layout_marginEnd="16dp"
android:layout_marginBottom="18dp"
app:layout_constraintBottom_toBottomOf="@id/iv_background"
app:layout_constraintEnd_toEndOf="@id/iv_background" />
<View
android:id="@+id/v_speed"
android:layout_width="144dp"
android:layout_height="40dp"
android:layout_marginTop="14dp"
android:layout_marginEnd="4dp"
app:layout_constraintEnd_toEndOf="@id/iv_background"
app:layout_constraintTop_toBottomOf="@id/iv_background" />
</androidx.constraintlayout.widget.ConstraintLayout>
</FrameLayout>

View File

@ -13,6 +13,7 @@
android:id="@+id/adImage"
android:layout_width="0dp"
android:layout_height="0dp"
android:tint="#01000000"
android:visibility="gone"
app:actualImageScaleType="centerCrop"
app:fadeDuration="0"
@ -25,7 +26,6 @@
android:id="@+id/ad_video"
android:layout_width="0dp"
android:layout_height="0dp"
android:visibility="gone"
app:layout_constraintBottom_toTopOf="@id/startAdIcpContainer"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"

View File

@ -1,14 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/tv_name"
style="@style/TextCaption1"
android:layout_width="match_parent"
android:layout_height="32dp"
android:background="@drawable/bg_shape_f8_radius_8"
android:ellipsize="end"
android:gravity="center"
android:maxLines="1"
android:paddingHorizontal="10dp"
android:textColor="@color/text_secondary"
tools:text="选择区服" />

View File

@ -650,30 +650,5 @@
<string name="my_game">我的遊戲</string>
<string name="played">玩過</string>
<string name="reserve">預約</string>
<string name="hint">提示</string>
<string name="speed_without_login_tips">請您完成登入後,在使用加速啟動遊戲</string>
<string name="go_to_login">去登入</string>
<string name="enable_vip_tips">開通會員使用加速功能!</string>
<string name="go_to_activate">去開通</string>
<string name="speed_failure_tips">加速失敗,請聯絡客服</string>
<string name="contact_service">聯絡客服</string>
<string name="speed_replace_game_tips">偵測到您目前正在加速遊戲,繼續啟動將停止原遊戲的加速,並加速啟動【%1$s】是否繼續</string>
<string name="not_started_yet">暫不啟動</string>
<string name="continue_to_start">繼續啟動</string>
<string name="stop_speed_tips">停止加速可能會導致遊戲斷線,是否繼續?</string>
<string name="stop_speed">停止加速</string>
<string name="cancel">取消</string>
<string name="select_the_acceleration_zone">選擇加速區服</string>
<string name="network_acceleration">網路加速</string>
<string name="accelerating_with_progress">加速中...%1$s%%</string>
<string name="enter_game">進入遊戲</string>
<string name="speed_not_installed_tips">偵測到您尚未安裝對應遊戲,請先安裝遊戲後再啟動加速器!</string>
<string name="customer_service_qq_number_has_been_copied">已複製客服QQ號</string>
<string name="real_name_tips">實名提示</string>
<string name="acceleration_service_without_real_name_description">根據相關政策要求,該遊戲需通過認證後才能加速</string>
<string name="go_to_real_name_authentication">前往實名認證</string>
<string name="recharge_without_real_name_description">響應國家號召,本平台僅對成年人提供儲值服務,請先完成實名認證</string>
<string name="recharge_with_minors_description">響應國家號召,保護未成年人健康參與遊戲,本平台暫不對未成年人提供儲值服務</string>
<string name="recharge_with_verifying_description">您實名認證處於【認證中】,暫不能進行充值,請等待完成認證</string>
</resources>

View File

@ -650,29 +650,4 @@
<string name="my_game">我的游戏</string>
<string name="played">玩过</string>
<string name="reserve">预约</string>
<string name="hint">提示</string>
<string name="speed_without_login_tips">请您完成登录后,在使用加速启动游戏</string>
<string name="go_to_login">去登录</string>
<string name="enable_vip_tips">开通会员使用加速功能!</string>
<string name="go_to_activate">去开通</string>
<string name="speed_failure_tips">加速失败,请联系客服</string>
<string name="contact_service">联系客服</string>
<string name="speed_replace_game_tips">检测到您当前正在加速游戏,继续启动将停止原游戏的加速,并加速启动【%1$s】是否继续</string>
<string name="not_started_yet">暂不启动</string>
<string name="continue_to_start">继续启动</string>
<string name="stop_speed_tips">停止加速可能会导致游戏断线,是否继续?</string>
<string name="stop_speed">停止加速</string>
<string name="cancel">取消</string>
<string name="select_the_acceleration_zone">选择加速区服</string>
<string name="network_acceleration">网络加速</string>
<string name="accelerating_with_progress">加速中...%1$s%%</string>
<string name="enter_game">进入游戏</string>
<string name="speed_not_installed_tips">检测到您尚未安装对应游戏,请先安装游戏后再启动加速器!</string>
<string name="customer_service_qq_number_has_been_copied">已复制客服QQ号</string>
<string name="real_name_tips">实名提示</string>
<string name="acceleration_service_without_real_name_description">根据相关政策要求,该游戏需通过认证后才能进行加速</string>
<string name="go_to_real_name_authentication">前往实名认证</string>
<string name="recharge_without_real_name_description">响应国家号召,本平台仅对成年人提供充值服务,请先完成实名认证</string>
<string name="recharge_with_minors_description">响应国家号召,保护未成年人健康参与游戏,本平台暂不对未成年人提供充值服务</string>
<string name="recharge_with_verifying_description">您实名认证处于【认证中】,暂不能进行充值,请等待完成认证</string>
</resources>

View File

@ -20,10 +20,6 @@
android:alpha="0"
motion:framePosition="20"
motion:motionTarget="@+id/iv_arrow" />
<KeyAttribute
android:alpha="0"
motion:framePosition="20"
motion:motionTarget="@+id/tv_my_assets" />
</KeyFrameSet>
</Transition>
@ -101,14 +97,6 @@
motion:layout_constraintBottom_toBottomOf="parent"
motion:layout_constraintEnd_toEndOf="parent" />
<Constraint
android:id="@+id/tv_my_assets"
android:layout_width="72dp"
android:layout_height="28dp"
android:layout_marginEnd="20dp"
android:alpha="1"
motion:layout_constraintBottom_toBottomOf="@id/personal_user_icon"
motion:layout_constraintEnd_toEndOf="parent" />
</ConstraintSet>
<ConstraintSet android:id="@+id/end">
@ -200,17 +188,5 @@
android:alpha="0"
motion:layout_constraintBottom_toBottomOf="parent"
motion:layout_constraintEnd_toEndOf="parent" />
<Constraint
android:id="@+id/tv_my_assets"
android:layout_width="72dp"
android:layout_height="28dp"
android:layout_marginEnd="20dp"
android:alpha="0"
android:scaleX="0.875"
android:scaleY="0.875"
android:translationY="57dp"
motion:layout_constraintBottom_toBottomOf="@id/personal_user_icon"
motion:layout_constraintEnd_toEndOf="parent" />
</ConstraintSet>
</MotionScene>

View File

@ -149,8 +149,6 @@ ext {
volcTlsVersion = "1.1.4"
xcrashVersion = "3.1.0"
aliPayVersion = "15.8.17"
acceleratorVersion = "1.0.1"
}
apply from: 'dependencies_vasdk.gradle'

View File

@ -1,48 +0,0 @@
plugins {
id 'com.android.library'
id 'org.jetbrains.kotlin.android'
id 'kotlin-kapt'
id 'kotlin-parcelize'
id 'com.google.devtools.ksp'
}
android {
namespace 'com.gh.gamecenter.accelerator'
compileSdk 34
defaultConfig {
minSdk 22
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
repositories {
flatDir {
dirs 'libs'
}
}
}
buildTypes {
release {
minifyEnabled false
consumerProguardFiles 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = '1.8'
}
}
dependencies {
implementation fileTree(include: ['*.jar', '*.aar'], dir: 'libs')
implementation(project(path: ":module_common")) {
exclude group: 'androidx.swiperefreshlayout'
}
implementation(project(path: ":module_core_feature"))
ksp "cn.therouter:apt:${routerVersion}"
implementation "com.lg:accelerator:${acceleratorVersion}"
}

View File

@ -1,21 +0,0 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile

View File

@ -1,9 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.gh.gamecenter.accelerator">
<application>
</application>
</manifest>

View File

@ -1,242 +0,0 @@
package com.gh.gamecenter.accelerator.provider
import android.app.Application
import com.gh.gamecenter.core.callback.AccelerateState
import com.gh.gamecenter.core.callback.OnAccelerateListener
import com.gh.gamecenter.core.provider.IAcceleratorProvider
import com.gh.gamecenter.feature.entity.AcctGameInfo
import com.gh.gamecenter.feature.entity.VipEntity
import com.gh.gamecenter.feature.utils.SentryHelper
import com.lightgame.utils.Utils
import com.qeeyou.qyvpn.QyAccelerator
import com.qeeyou.qyvpn.bean.AccNotifyConfigBean
import com.qeeyou.qyvpn.bean.QyAcctGameInfo
import com.qeeyou.qyvpn.bean.QyGameInfoBean
import com.qeeyou.qyvpn.strategy.QyUnifiedProcessStrategy
import com.qeeyou.qyvpn.utils.OnQyAccelerateListener
import com.qeeyou.qyvpn.utils.QyAccConfig
/**
* 单例模式,可以用户保存一些加速器全局状态信息
*/
@com.therouter.inject.ServiceProvider
class AcceleratorProviderImpl : IAcceleratorProvider {
private var vipEntity: VipEntity? = null
private var _token = ""
// 根据包名回调
private val listeners = hashMapOf<String, OnAccelerateListener>()
// 所有包名都回调(pkgName.isBlank())
private val allListener = mutableSetOf<OnAccelerateListener>()
private var curAcctGameInfo: AcctGameInfo? = null
private val qyListener = object : OnQyAccelerateListener {
override fun onAccCurrentProgress(progress: Int, curGamePkgName: String?, curGameZoneFlag: String?) {
listeners[curGamePkgName]?.onProgress(progress, curGamePkgName, curGameZoneFlag)
allListener.forEach {
it.onProgress(progress, curGamePkgName, curGameZoneFlag)
}
}
override fun onAccCurrentStatus(
status: QyAccelerator.QyStatus,
curGamePkgName: String?,
curGameZoneFlag: String?,
eventCode: Int,
eventMsg: String?,
extraParam: Any?
) {
Utils.log(LOG_TAG, "onAccCurrentStatus:$status -- code:$eventCode -- msg:$eventMsg")
val state = when (status) {
QyAccelerator.QyStatus.AccNormal -> AccelerateState.Normal(eventCode)
QyAccelerator.QyStatus.AccStarting -> AccelerateState.Starting(eventCode)
QyAccelerator.QyStatus.AccSuccess -> AccelerateState.Success(curAcctGameInfo, eventCode)
QyAccelerator.QyStatus.AccFailure -> {
SentryHelper.onEvent(SENTRY_EVENT_ID, KEY_ACC_FAILURE_ERROR, "$eventCode($eventMsg)")
AccelerateState.Failure(eventCode)
}
QyAccelerator.QyStatus.AccOkStopping -> AccelerateState.OkStopping(eventCode)
QyAccelerator.QyStatus.AccErrStopping -> AccelerateState.ErrStopping(eventCode)
}
listeners[curGamePkgName]?.onStateChanged(state)
allListener.forEach {
it.onStateChanged(state)
}
}
override fun onAccEventCallBack(
eventCode: Int,
eventMsg: String?,
curGamePkgName: String?,
curGameZoneFlag: String?
) = Unit
override fun onAccExtraInfoEvent(
eventFlag: QyAccelerator.QyExtra,
extraInfo: Any?,
curGamePkgName: String?,
curGameZoneFlag: String?
) = ""
}
override fun init(application: Application, version: String) {
Utils.log(LOG_TAG, "init:$version")
val qyAccConfigBuilder = QyAccConfig.Builder().setAppId("QyAccSdk")
.setDebug(false)
.setAppVersion(version)
.setServerAddressEnv(QyAccConfig.ServerAddressEnv.Release)
.build()
QyAccelerator.getInstance().init(application, qyAccConfigBuilder, QyAccelerator.QyAccStrategy.HaloRing)
QyAccelerator.getInstance().bindQyAccRelatedListener(qyListener)
}
override fun setQyUserToken(token: String, callback: ((Boolean) -> Unit)?) {
Utils.log(LOG_TAG, "setQyUserToken")
// if (_token == token) {
// // 避免外部多次设置相同的token
// return
// }
println("kayn -->setQyUserToken:$token")
QyAccelerator.getInstance().setQyUserToken(token, setResultCallback = { isSuccess, errMsg ->
Utils.log(LOG_TAG, "setQyUserToken:$token --isSuccess:$isSuccess --errMsg:$errMsg")
if (isSuccess) {
_token = token
} else {
// 将setToken错误事件上报的sentry便于后期分析原因
SentryHelper.onEvent(SENTRY_EVENT_ID, KEY_SET_TOKEN_ERROR_MESSAGE, errMsg)
}
callback?.invoke(isSuccess)
})
}
override fun setVipEntity(vip: Any) {
Utils.log(LOG_TAG, "setVipEntity:$vip")
if (vip is VipEntity) {
if (vipEntity != vip) {
vipEntity = vip
listeners.values.forEach {
it.onVipStatusChanged(vip.isNewUser, vip.vipStatus)
}
allListener.forEach {
it.onVipStatusChanged(vip.isNewUser, vip.vipStatus)
}
}
}
}
override fun isVip(): Boolean = vipEntity?.vipStatus ?: false
override fun isNewUser(): Boolean = vipEntity?.isNewUser ?: false
override fun isPaidUser(): Boolean = isVip() && !(vipEntity?.isTryVip ?: false)
override fun getMemberType(): String = when {
isPaidUser() -> MEMBER_TYPE_PAID_MEMBER
isVip() -> MEMBER_TYPE_FREE_MEMBER
else -> MEMBER_TYPE_NONE_MEMBER
}
override fun deleteQyUserToken(): Boolean {
Utils.log(LOG_TAG, "deleteQyUserToken")
if (isCurAccSuccess()) {
stopQyGameAccelerate("退出登录!")
}
// 退出登录的时候才会调用
val isDeleted = QyAccelerator.getInstance().delQyUserToken()
_token = ""
listeners.clear()
allListener.clear()
vipEntity = null
return isDeleted
}
override fun startQyGameAccelerate(accGameInfo: Any) {
Utils.log(LOG_TAG, "startQyGameAccelerate:$accGameInfo")
if (accGameInfo is AcctGameInfo) {
val qyAcctGameInfo = QyAcctGameInfo(
accGameInfo.accGamePkgName,
accGameInfo.zoneInfo.id.toString(),
accNotifyConfig = AccNotifyConfigBean(
notifyGameName = accGameInfo.notifyGameName,
notifyGameTxtTitle = accGameInfo.notifyGameTxtTitle,
notifyGameSmallLogo = accGameInfo.notifyGameSmallLogo,
notifyGameLargeLogo = accGameInfo.notifyGameLargeLogo,
notifyClickParam = accGameInfo.notifyClickParam
)
)
curAcctGameInfo = accGameInfo
QyAccelerator.getInstance().startQyGameAccelerate(qyAcctGameInfo)
}
}
override fun stopQyGameAccelerate(appLayerCallStopMsg: String?): Boolean {
Utils.log(LOG_TAG, "stopQyGameAccelerate:$appLayerCallStopMsg")
return QyAccelerator.getInstance().stopQyGameAccelerate(appLayerCallStopMsg)
}
override fun bindAccRelatedListener(pkgName: String, listener: OnAccelerateListener) {
if (pkgName.isBlank()) {
allListener.add(listener)
} else {
listeners[pkgName] = listener
}
}
override fun unBindAccRelatedListener(listener: OnAccelerateListener) {
listeners.values.remove(listener)
allListener.remove(listener)
}
override fun loadQyGameZoneData(packageName: String, callback: (List<Any>) -> Unit) {
Utils.log(LOG_TAG, "loadQyGameZoneData:$packageName")
QyAccelerator.getInstance()
.loadQyGameZoneData(
packageName,
object : QyUnifiedProcessStrategy.OnLoadQyGameZoneDataCallBack {
override fun loadQyGameZoneData(
isSuccess: Boolean,
errCode: Int?,
errMsg: String?,
gameZoneMap: MutableMap<String, List<QyGameInfoBean.Game.ZoneInfo?>?>?
) {
if (!gameZoneMap.isNullOrEmpty()) {
val zoneList = arrayListOf<AcctGameInfo>()
gameZoneMap.iterator().forEach {
it.value?.forEach { value ->
zoneList.add(
AcctGameInfo(
it.key,
AcctGameInfo.ZoneInfo(value?.id ?: 0, value?.cn_name, value?.en_name)
)
)
}
}
callback(zoneList)
} else {
Utils.log(LOG_TAG, "区服数据为空")
callback(listOf())
}
}
})
}
override fun isCurAccSuccess(): Boolean {
return QyAccelerator.getInstance().isCurAccSuccess()
}
companion object {
private const val LOG_TAG = "AcceleratorProviderImpl"
private const val MEMBER_TYPE_PAID_MEMBER = "付费会员"
private const val MEMBER_TYPE_FREE_MEMBER = "免费会员"
private const val MEMBER_TYPE_NONE_MEMBER = "非会员"
private const val SENTRY_EVENT_ID = "ACCELERATOR_SET_TOKEN_ERROR"
private const val KEY_SET_TOKEN_ERROR_MESSAGE = "set_token_error"
private const val KEY_ACC_FAILURE_ERROR = "key_acc_failure_error"
}
}

View File

@ -1,7 +0,0 @@
<resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. -->
<style name="Base.Theme.Assistantandroid2" parent="Theme.Material3.DayNight.NoActionBar">
<!-- Customize your dark theme here. -->
<!-- <item name="colorPrimary">@color/my_dark_primary</item> -->
</style>
</resources>

View File

@ -1,3 +0,0 @@
<resources>
<string name="app_name">accelerator</string>
</resources>

View File

@ -1,42 +0,0 @@
plugins {
id 'com.android.library'
id 'org.jetbrains.kotlin.android'
id 'kotlin-kapt'
id 'kotlin-parcelize'
id 'com.google.devtools.ksp'
}
android {
namespace 'com.game.gamecenter.alipay'
compileSdk 34
defaultConfig {
minSdk 22
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = '1.8'
}
}
dependencies {
implementation "com.alipay.sdk:alipaysdk-android:$aliPayVersion"
implementation(project(path: ":module_common")) {
exclude group: 'androidx.swiperefreshlayout'
}
implementation(project(path: ":module_core_feature"))
ksp "cn.therouter:apt:${routerVersion}"
}

View File

@ -1,21 +0,0 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile

View File

@ -1,13 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<application android:networkSecurityConfig="@xml/network_security_config">
</application>
</manifest>

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