Compare commits
34 Commits
release
...
chen/accel
| Author | SHA1 | Date | |
|---|---|---|---|
| d98b00f2dc | |||
| 8127ba7bd0 | |||
| 158c36a6b1 | |||
| c4184b9cbb | |||
| 585153cc0e | |||
| 112ce8da4c | |||
| 88cfb99a12 | |||
| b9fbad85b2 | |||
| 86f8aaf1e1 | |||
| 59da6eb171 | |||
| 4d5af5044f | |||
| 30105b3cc2 | |||
| f0b4085455 | |||
| 4e896ceccf | |||
| 52a3d4a9a7 | |||
| 8df60fcc1d | |||
| 9946dd0df3 | |||
| e3e218dd2b | |||
| e089347f8c | |||
| 174ca03ce4 | |||
| 6adae085b1 | |||
| 6a3b164177 | |||
| d08d1bf8e9 | |||
| 7ece9b0d4e | |||
| c45a2c34eb | |||
| 06b4c3f8ab | |||
| 7f71c1d740 | |||
| c1c2078294 | |||
| 34d31647c3 | |||
| e6badcb7c3 | |||
| 8e1973bad1 | |||
| d9a08037b5 | |||
| a65fb3535d | |||
| f6d5d6f719 |
@ -72,6 +72,8 @@ android_build:
|
||||
only:
|
||||
- dev
|
||||
- release
|
||||
- feat/GHZSCY-6976
|
||||
- feat/GHZSCY-6976-log
|
||||
|
||||
# 代码检查
|
||||
sonarqube_analysis:
|
||||
@ -103,6 +105,8 @@ sonarqube_analysis:
|
||||
only:
|
||||
- dev
|
||||
- release
|
||||
- feat/GHZSCY-6976
|
||||
- feat/GHZSCY-6976-log
|
||||
|
||||
## 发送简易检测结果报告
|
||||
send_sonar_report:
|
||||
@ -121,6 +125,8 @@ send_sonar_report:
|
||||
only:
|
||||
- dev
|
||||
- release
|
||||
- feat/GHZSCY-6976
|
||||
- feat/GHZSCY-6976-log
|
||||
|
||||
oss-upload&send-email:
|
||||
tags:
|
||||
@ -157,3 +163,5 @@ oss-upload&send-email:
|
||||
only:
|
||||
- dev
|
||||
- release
|
||||
- feat/GHZSCY-6976
|
||||
- feat/GHZSCY-6976-log
|
||||
|
||||
@ -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,6 +526,18 @@ 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')
|
||||
|
||||
@ -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,7 +197,9 @@
|
||||
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" />
|
||||
|
||||
@ -814,6 +816,14 @@
|
||||
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"-->
|
||||
|
||||
@ -22,7 +22,8 @@ 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.RouteConsts
|
||||
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.entity.NotificationUgc
|
||||
import com.gh.gamecenter.common.exposure.ExposureSource
|
||||
import com.gh.gamecenter.common.loghub.LoghubUtils
|
||||
@ -30,20 +31,23 @@ 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.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.core.utils.*
|
||||
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
|
||||
@ -55,6 +59,9 @@ 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.*
|
||||
@ -75,6 +82,7 @@ class DefaultJsApi(
|
||||
private var mBbsId: String? = "",
|
||||
private var mOriginUrl: String? = "",
|
||||
private val mForumName: String? = "",
|
||||
private val listener: OnWebClickListener? = null
|
||||
) {
|
||||
|
||||
companion object {
|
||||
@ -699,6 +707,84 @@ 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,可能为空
|
||||
*/
|
||||
@ -815,4 +901,15 @@ class DefaultJsApi(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
interface OnWebClickListener {
|
||||
|
||||
fun onPreOrderWithAli(order: OrderEntity)
|
||||
|
||||
fun onPreOrderWithWechat(order: OrderEntity)
|
||||
|
||||
fun onStartGameAccelerate(accInfo: AcctRecordEntity.AccInfo)
|
||||
|
||||
fun onStopGameAccelerate()
|
||||
}
|
||||
}
|
||||
|
||||
@ -8,12 +8,21 @@ import com.gh.gamecenter.feature.entity.GameEntity
|
||||
class PackageCheckHandler : DownloadChainHandler() {
|
||||
|
||||
override fun handleRequest(context: Context, gameEntity: GameEntity, asVGame: Boolean) {
|
||||
PackageCheckDialogFragment.show((context as AppCompatActivity), gameEntity) {
|
||||
fun nextOrProcessEnd() {
|
||||
if (hasNext()) {
|
||||
getNext()?.handleRequest(context, gameEntity, asVGame)
|
||||
} else {
|
||||
processEndCallback?.invoke(asVGame, null)
|
||||
}
|
||||
}
|
||||
|
||||
if (gameEntity.canSpeed) {
|
||||
nextOrProcessEnd()
|
||||
} else {
|
||||
PackageCheckDialogFragment.show((context as AppCompatActivity), gameEntity) {
|
||||
nextOrProcessEnd()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,61 @@
|
||||
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
|
||||
)
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -5,6 +5,8 @@ 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;
|
||||
@ -41,7 +43,8 @@ public class DetailDownloadUtils {
|
||||
|
||||
/**
|
||||
* 更新底部下载区域
|
||||
* @param viewHolder 下载区域的包裹
|
||||
*
|
||||
* @param viewHolder 下载区域的包裹
|
||||
* @param ignoreDownloadEntity 忽略下载实体(往往用于下载异常时)
|
||||
*/
|
||||
public static void updateViewHolder(DetailViewHolder viewHolder, boolean ignoreDownloadEntity) {
|
||||
@ -52,6 +55,11 @@ 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)) {
|
||||
@ -219,7 +227,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)
|
||||
@ -246,16 +254,24 @@ 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);
|
||||
|
||||
@ -6,6 +6,7 @@ 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
|
||||
@ -89,4 +90,12 @@ object TempCertificationUtils {
|
||||
return stringBuffer.toString()
|
||||
}
|
||||
|
||||
/**
|
||||
* 检测光环是否实名
|
||||
*/
|
||||
fun isUserVerified(): Boolean {
|
||||
val idCard = UserManager.getInstance().userInfoEntity?.idCard
|
||||
// 账号已实名
|
||||
return idCard != null && idCard.status == 0
|
||||
}
|
||||
}
|
||||
81
app/src/main/java/com/gh/gamecenter/BatchRegisterActivity.kt
Normal file
81
app/src/main/java/com/gh/gamecenter/BatchRegisterActivity.kt
Normal file
@ -0,0 +1,81 @@
|
||||
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()
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@ -14,8 +14,6 @@ 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
|
||||
@ -32,13 +30,14 @@ 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
|
||||
@ -90,8 +89,10 @@ 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点击这里进行预设置渠道")
|
||||
@ -103,7 +104,7 @@ class SplashScreenActivity : BaseActivity(), ISplashScreen {
|
||||
executeDex2OatInAdvance()
|
||||
DialogHelper.showDialog(
|
||||
context = this,
|
||||
title ="选择环境",
|
||||
title = "选择环境",
|
||||
content = spanBuilder,
|
||||
confirmText = "正式环境",
|
||||
cancelText = "测试环境",
|
||||
@ -130,6 +131,7 @@ 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, "")
|
||||
|
||||
@ -6,17 +6,19 @@ import android.os.Bundle
|
||||
import android.text.TextUtils
|
||||
import android.view.KeyEvent
|
||||
import android.view.View
|
||||
import com.therouter.router.Route
|
||||
import com.gh.common.constant.Config
|
||||
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() {
|
||||
@ -29,6 +31,8 @@ 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)
|
||||
}
|
||||
@ -305,5 +309,17 @@ 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
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -4,8 +4,11 @@ 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
|
||||
@ -13,6 +16,7 @@ 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
|
||||
@ -45,6 +49,7 @@ 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
|
||||
@ -62,7 +67,8 @@ class DetailViewHolder(
|
||||
name: String?,
|
||||
title: String?,
|
||||
val traceEvent: ExposureEvent?,
|
||||
val isSupportDualButton: Boolean = false // 是否支持双下载按钮,不支持的时候跟普通列表意义选用优先级高的那个来显示
|
||||
val isSupportDualButton: Boolean = false, // 是否支持双下载按钮,不支持的时候跟普通列表意义选用优先级高的那个来显示,
|
||||
val acceleratorUiHelper: GameDetailAcceleratorUiHelper? = null // 网速加速,只有游戏详情才有
|
||||
) {
|
||||
var context: Context
|
||||
var downloadBottom: View
|
||||
@ -90,6 +96,12 @@ 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)
|
||||
@ -104,6 +116,10 @@ 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()
|
||||
@ -158,7 +174,9 @@ 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("游戏详情页")
|
||||
@ -176,6 +194,19 @@ 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?,
|
||||
@ -334,7 +365,19 @@ class DetailViewHolder(
|
||||
if (mAsVGame) {
|
||||
VHelper.installOrLaunch(mViewHolder.context, mGameEntity, null)
|
||||
} else {
|
||||
PackageLauncher.launchApp(mViewHolder.context, mGameEntity, mGameEntity.getUniquePackageName())
|
||||
// 如果游戏配置了加速,则启动时需要进行包名检测
|
||||
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()
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
} else {
|
||||
GamePermissionDialogFragment.show(
|
||||
@ -594,8 +637,9 @@ 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)
|
||||
|
||||
@ -0,0 +1,13 @@
|
||||
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()
|
||||
}
|
||||
}
|
||||
@ -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.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.entity.*
|
||||
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,7 +86,6 @@ 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
|
||||
@ -101,6 +100,7 @@ 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,6 +155,8 @@ 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) {
|
||||
@ -265,7 +267,8 @@ class GameDetailFragment : BaseLazyFragment(), IScrollable {
|
||||
name = "游戏详情",
|
||||
title = mGameEntity!!.name ?: "",
|
||||
traceEvent = mTraceEvent,
|
||||
isSupportDualButton = true
|
||||
isSupportDualButton = true,
|
||||
acceleratorUiHelper
|
||||
)
|
||||
|
||||
private val contentCardClick: (contentCard: ContentCardEntity, position: Int) -> Unit =
|
||||
@ -412,6 +415,7 @@ class GameDetailFragment : BaseLazyFragment(), IScrollable {
|
||||
mVideoBinding = mBodyBinding.gameDetailVideo
|
||||
mDownloadBinding = mBinding.detailLlBottom
|
||||
mRecommendBinding = mBinding.gameDetailRecommendView
|
||||
acceleratorUiHelper = GameDetailAcceleratorUiHelper(mDownloadBinding)
|
||||
}.root
|
||||
}
|
||||
|
||||
@ -548,7 +552,12 @@ 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
|
||||
@ -669,7 +678,9 @@ 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)
|
||||
@ -768,6 +779,8 @@ class GameDetailFragment : BaseLazyFragment(), IScrollable {
|
||||
if (gameResource.status == Status.SUCCESS) {
|
||||
mViewModel.logHistory(gameResource.data!!)
|
||||
mGameEntity = gameResource.data
|
||||
acceleratorUiHelper.setGame(gameResource.data)
|
||||
loadAccelerationData(mGameEntity!!)
|
||||
showBrowserInstallHintIfNeeded()
|
||||
controlInstallHint()
|
||||
// 添加启动弹窗的相关信息
|
||||
@ -787,7 +800,9 @@ 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({
|
||||
@ -839,7 +854,12 @@ 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) {
|
||||
@ -994,6 +1014,32 @@ 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 显示的顺序为:详情>云存档>评价>专区>论坛
|
||||
@ -1032,7 +1078,8 @@ 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))
|
||||
@ -1040,7 +1087,8 @@ 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
|
||||
@ -1056,7 +1104,8 @@ 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
|
||||
@ -1073,7 +1122,8 @@ 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)
|
||||
@ -1081,7 +1131,8 @@ 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)
|
||||
}
|
||||
@ -1181,7 +1232,8 @@ 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 ?: ""
|
||||
@ -1193,7 +1245,8 @@ 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 ?: "",
|
||||
@ -1206,7 +1259,8 @@ 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 ?: "",
|
||||
@ -1214,7 +1268,8 @@ class GameDetailFragment : BaseLazyFragment(), IScrollable {
|
||||
)
|
||||
},
|
||||
{
|
||||
SensorsBridge.trackEvent("GameDetailDialogClick",
|
||||
SensorsBridge.trackEvent(
|
||||
"GameDetailDialogClick",
|
||||
"game_id", mGameEntity?.id ?: "",
|
||||
"game_name", mGameEntity?.name ?: "",
|
||||
"game_type", mGameEntity?.categoryChinese ?: "",
|
||||
@ -1386,7 +1441,12 @@ 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(
|
||||
@ -1853,8 +1913,7 @@ class GameDetailFragment : BaseLazyFragment(), IScrollable {
|
||||
requireContext(),
|
||||
mGameEntity,
|
||||
callback = getCallback(),
|
||||
|
||||
)
|
||||
)
|
||||
} else {
|
||||
ReservationHelper.showCancelReservationDialog(requireContext(), mGameEntity) {
|
||||
ReservationHelper.cancelReservation(mGameEntity!!) {
|
||||
@ -2214,7 +2273,8 @@ 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
|
||||
@ -2374,6 +2434,9 @@ class GameDetailFragment : BaseLazyFragment(), IScrollable {
|
||||
}
|
||||
|
||||
override fun onBackPressed(): Boolean {
|
||||
if (acceleratorUiHelper.onBack()) {
|
||||
return true
|
||||
}
|
||||
mOrientationUtils?.backToProtVideo()
|
||||
|
||||
val trendsTabPosition = getTabPositionFromTabType(EntranceConsts.TAB_TYPE_TRENDS)
|
||||
@ -2434,6 +2497,11 @@ class GameDetailFragment : BaseLazyFragment(), IScrollable {
|
||||
NewFlatLogUtils.logGameDetailExit(mGameEntity?.name ?: "", mGameEntity?.id ?: "")
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
acceleratorUiHelper.clear()
|
||||
super.onDestroyView()
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
releaseVideo()
|
||||
@ -2527,9 +2595,21 @@ 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()))
|
||||
@ -2541,7 +2621,11 @@ 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"))
|
||||
@ -2553,7 +2637,11 @@ 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)) {
|
||||
@ -2586,6 +2674,7 @@ 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
|
||||
@ -2594,6 +2683,7 @@ 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
|
||||
}
|
||||
|
||||
@ -5,14 +5,10 @@ import android.app.Application
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.text.TextUtils
|
||||
import androidx.lifecycle.AndroidViewModel
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.lifecycle.*
|
||||
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
|
||||
@ -20,28 +16,53 @@ 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.*
|
||||
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.entity.RecommendPopupEntity
|
||||
import com.gh.gamecenter.entity.UnifiedUserTrendEntity
|
||||
import com.gh.gamecenter.feature.entity.*
|
||||
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.entity.*
|
||||
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.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,
|
||||
@ -69,6 +90,10 @@ 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()
|
||||
}
|
||||
@ -85,9 +110,17 @@ 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)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// 获取游戏摘要
|
||||
@ -162,6 +195,11 @@ 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
|
||||
@ -659,6 +697,66 @@ 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?,
|
||||
|
||||
@ -0,0 +1,76 @@
|
||||
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()
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,35 @@
|
||||
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()
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,25 @@
|
||||
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?>
|
||||
}
|
||||
@ -0,0 +1,182 @@
|
||||
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
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,401 @@
|
||||
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()
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,54 @@
|
||||
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 = "",
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,28 @@
|
||||
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
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,29 @@
|
||||
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()
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,18 @@
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,20 @@
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,26 @@
|
||||
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()
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,37 @@
|
||||
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)
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,71 @@
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -0,0 +1,31 @@
|
||||
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
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,241 @@
|
||||
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
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,116 @@
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,197 @@
|
||||
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)
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,258 @@
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -61,7 +61,14 @@ 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"))
|
||||
}
|
||||
|
||||
@ -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); // 下载按钮ViewHolder
|
||||
return new DetailViewHolder(mCachedView, mGameEntity, false, mEntrance, mName, mTitle, null, false, null); // 下载按钮ViewHolder
|
||||
}
|
||||
|
||||
public LibaoEntity getLibaoEntity() {
|
||||
|
||||
@ -192,7 +192,8 @@ public class NewsDetailFragment extends ToolbarFragment {
|
||||
"新闻详情",
|
||||
adapter.getTitle(),
|
||||
mExposureEvent,
|
||||
false); // 下载按钮ViewHolder
|
||||
false,
|
||||
null); // 下载按钮ViewHolder
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -28,10 +28,7 @@ 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.CollectionActivity
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.ShareGhActivity
|
||||
import com.gh.gamecenter.WebActivity
|
||||
import com.gh.gamecenter.*
|
||||
import com.gh.gamecenter.common.base.fragment.BaseLazyFragment
|
||||
import com.gh.gamecenter.common.constant.Constants
|
||||
import com.gh.gamecenter.common.constant.EntranceConsts
|
||||
@ -118,9 +115,11 @@ 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()
|
||||
}
|
||||
@ -137,15 +136,24 @@ class HaloPersonalFragment : BaseLazyFragment() {
|
||||
SensorsBridge.trackHaloSelfClick("用户信息", "立即登录", "", "", "")
|
||||
CheckLoginUtils.checkLogin(context, "我的光环-立即登录", null)
|
||||
} else {
|
||||
mStubBinding.ivArrow.performClick()
|
||||
NewFlatLogUtils.logHaloSelfClick("用户信息", "个人主页")
|
||||
SensorsBridge.trackHaloSelfClick("用户信息", "个人主页", "", "", "")
|
||||
DirectUtils.directToHomeActivity(
|
||||
requireContext(),
|
||||
UserManager.getInstance().userId,
|
||||
"",
|
||||
"我的光环"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
mStubBinding.toolbarContainer -> {
|
||||
if (mUserInfoEntity == null) {
|
||||
NewFlatLogUtils.logHaloSelfLogin()
|
||||
CheckLoginUtils.checkLogin(context, "我的光环-立即登录", null)
|
||||
}
|
||||
}
|
||||
|
||||
mStubBinding.darkModeIv -> {
|
||||
if (!ClickUtils.isFastDoubleClick(v.id, 1000)) {
|
||||
NewFlatLogUtils.logHaloSelfClick("右上角", "切换模式")
|
||||
@ -182,6 +190,7 @@ class HaloPersonalFragment : BaseLazyFragment() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mStubBinding.personalMsg -> {
|
||||
// 优先进入有数字提醒的消息tab,其次是有红点提醒的游戏动态,最后是没有提醒的消息tab
|
||||
val defaultTabIndex = if ((mUnreadViewModel.messageUnreadCountLiveData.value?.message
|
||||
@ -208,6 +217,7 @@ class HaloPersonalFragment : BaseLazyFragment() {
|
||||
|
||||
DirectUtils.directToMessageCenter(defaultTabIndex, "我的光环-消息")
|
||||
}
|
||||
|
||||
mStubBinding.personalUserIcon,
|
||||
mStubBinding.personalUserName -> {
|
||||
if (mUserInfoEntity != null) {
|
||||
@ -226,22 +236,21 @@ class HaloPersonalFragment : BaseLazyFragment() {
|
||||
CheckLoginUtils.checkLogin(context, "我的光环-立即登录", null)
|
||||
}
|
||||
}
|
||||
mStubBinding.ivArrow -> {
|
||||
|
||||
mStubBinding.tvMyAssets -> {
|
||||
if (mUserInfoEntity != null) {
|
||||
NewFlatLogUtils.logHaloSelfClick("用户信息", "个人主页")
|
||||
SensorsBridge.trackHaloSelfClick("用户信息", "个人主页", "", "", "")
|
||||
DirectUtils.directToHomeActivity(
|
||||
requireContext(),
|
||||
UserManager.getInstance().userId,
|
||||
"",
|
||||
"我的光环"
|
||||
)
|
||||
SensorsBridge.trackMyAssetsPageShow("无", "无", "无", "我的光环")
|
||||
val intent = WebActivity.getMyAssetsIntent(requireContext())
|
||||
startActivity(intent)
|
||||
} else {
|
||||
NewFlatLogUtils.logHaloSelfClick("用户信息", "立即登录")
|
||||
SensorsBridge.trackHaloSelfClick("用户信息", "立即登录", "", "", "")
|
||||
CheckLoginUtils.checkLogin(context, "我的光环-个人主页", null)
|
||||
}
|
||||
}
|
||||
|
||||
mStubBinding.personalBadge -> {
|
||||
NewFlatLogUtils.logHaloSelfClick("用户信息", "我的徽章")
|
||||
SensorsBridge.trackHaloSelfClick("用户信息", "我的徽章", "", "", "")
|
||||
@ -252,6 +261,7 @@ class HaloPersonalFragment : BaseLazyFragment() {
|
||||
mUserInfoEntity?.icon
|
||||
)
|
||||
}
|
||||
|
||||
mStubBinding.myGameTv -> {
|
||||
if (UserManager.getInstance().isLoggedIn) {
|
||||
NewFlatLogUtils.logHaloSelfClick("常用功能", "我的游戏")
|
||||
@ -268,6 +278,7 @@ class HaloPersonalFragment : BaseLazyFragment() {
|
||||
CheckLoginUtils.checkLogin(requireContext(), "我的光环-我的游戏") {}
|
||||
}
|
||||
}
|
||||
|
||||
mStubBinding.myPostTv -> {
|
||||
if (UserManager.getInstance().isLoggedIn) {
|
||||
NewFlatLogUtils.logHaloSelfClick("常用功能", "我的发布")
|
||||
@ -284,6 +295,7 @@ class HaloPersonalFragment : BaseLazyFragment() {
|
||||
CheckLoginUtils.checkLogin(requireContext(), "我的光环-我的发布") { }
|
||||
}
|
||||
}
|
||||
|
||||
mStubBinding.myGameCollectionTv -> {
|
||||
if (UserManager.getInstance().isLoggedIn) {
|
||||
NewFlatLogUtils.logHaloSelfClick("常用功能", "我的游戏单")
|
||||
@ -300,6 +312,7 @@ class HaloPersonalFragment : BaseLazyFragment() {
|
||||
CheckLoginUtils.checkLogin(requireContext(), "我的光环-我的游戏单") { }
|
||||
}
|
||||
}
|
||||
|
||||
mStubBinding.historyTv -> {
|
||||
NewFlatLogUtils.logHaloSelfClick("常用功能", "浏览记录")
|
||||
SensorsBridge.trackHaloSelfClick(
|
||||
@ -311,6 +324,7 @@ class HaloPersonalFragment : BaseLazyFragment() {
|
||||
)
|
||||
startActivity(HistoryActivity.getHistoryIntent(requireContext(), "我的光环-浏览记录"))
|
||||
}
|
||||
|
||||
mStubBinding.myCollectionTv -> {
|
||||
if (UserManager.getInstance().isLoggedIn) {
|
||||
NewFlatLogUtils.logHaloSelfClick("常用功能", "我的收藏")
|
||||
@ -606,7 +620,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(
|
||||
@ -637,16 +651,30 @@ 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.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)
|
||||
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())
|
||||
@ -681,6 +709,8 @@ 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())
|
||||
}
|
||||
@ -706,7 +736,6 @@ class HaloPersonalFragment : BaseLazyFragment() {
|
||||
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)
|
||||
|
||||
@ -714,7 +743,7 @@ class HaloPersonalFragment : BaseLazyFragment() {
|
||||
mStubBinding.toolbarContainer.setOnClickListener(this)
|
||||
mStubBinding.darkModeIv.setOnClickListener(this)
|
||||
mStubBinding.personalMsg.setOnClickListener(this)
|
||||
mStubBinding.ivArrow.setOnClickListener(this)
|
||||
mStubBinding.tvMyAssets.setOnClickListener(this)
|
||||
mStubBinding.personalUserName.setOnClickListener(this)
|
||||
mStubBinding.personalUserIcon.setOnClickListener(this)
|
||||
mStubBinding.personalBadge.setOnClickListener(this)
|
||||
@ -724,6 +753,12 @@ 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()
|
||||
@ -799,7 +834,10 @@ 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)
|
||||
@ -977,6 +1015,7 @@ class HaloPersonalFragment : BaseLazyFragment() {
|
||||
MotionEvent.ACTION_DOWN -> {
|
||||
mStubBinding.listRefresh.isEnabled = false
|
||||
}
|
||||
|
||||
MotionEvent.ACTION_UP -> {
|
||||
mStubBinding.listRefresh.isEnabled = true
|
||||
}
|
||||
@ -1084,7 +1123,7 @@ class HaloPersonalFragment : BaseLazyFragment() {
|
||||
fun onEventMainThread(busNetworkState: EBNetworkState) {
|
||||
if (busNetworkState.isNetworkConnected
|
||||
&& UserManager.getInstance().isLoggedIn
|
||||
&& (mUserInfoEntity == null || TextUtils.isEmpty(UserManager.getInstance().token))
|
||||
&& (mUserViewModel.loginObsUserinfo.value == null)
|
||||
) {
|
||||
mUserViewModel.retryCheckLogin()
|
||||
}
|
||||
@ -1164,6 +1203,9 @@ 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()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -101,12 +101,14 @@ 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;
|
||||
@ -128,9 +130,12 @@ 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;
|
||||
@ -146,6 +151,7 @@ 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;
|
||||
@ -3424,6 +3430,7 @@ public interface ApiService {
|
||||
*/
|
||||
@PATCH("app/{module}/diverter_visit_time")
|
||||
Single<ResponseBody> patchDiverterVisitTime(@Path("module") String module, @Body RequestBody body);
|
||||
|
||||
/**
|
||||
* 游戏单搜索(复用 游戏单合集-内容列表 (适用于刷新轮换) 接口实体)
|
||||
*/
|
||||
@ -3435,4 +3442,22 @@ 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);
|
||||
|
||||
}
|
||||
@ -0,0 +1,33 @@
|
||||
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()
|
||||
}
|
||||
}
|
||||
@ -57,6 +57,7 @@ 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;
|
||||
@ -420,6 +421,11 @@ public class HaloApp extends MultiDexApplication {
|
||||
});
|
||||
}
|
||||
}, delay);
|
||||
|
||||
IAcceleratorProvider acceleratorProvider = TheRouter.get(IAcceleratorProvider.class);
|
||||
if (acceleratorProvider != null) {
|
||||
acceleratorProvider.init(this, PackageUtils.getGhVersionName());
|
||||
}
|
||||
}
|
||||
|
||||
public void getWebviewAbiList() {
|
||||
|
||||
@ -15,6 +15,7 @@ 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.*
|
||||
@ -35,7 +36,10 @@ 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
|
||||
@ -44,11 +48,29 @@ 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
|
||||
@ -61,6 +83,8 @@ 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
|
||||
@ -114,6 +138,19 @@ 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)
|
||||
@ -311,7 +348,132 @@ 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)
|
||||
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)
|
||||
}
|
||||
|
||||
@SuppressLint("SetJavaScriptEnabled")
|
||||
@ -362,6 +524,20 @@ 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, "")
|
||||
@ -599,6 +775,42 @@ 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)) {
|
||||
@ -609,6 +821,7 @@ class WebFragment : LazyFragment(), IScrollable {
|
||||
removeJavascriptObject("share")
|
||||
removeJavascriptObject("internal")
|
||||
}
|
||||
TheRouter.get(IAcceleratorProvider::class.java)?.unBindAccRelatedListener(acctListener)
|
||||
}
|
||||
|
||||
private fun getNewsCommentNum() {
|
||||
@ -681,6 +894,16 @@ 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? -> }
|
||||
|
||||
@ -0,0 +1,14 @@
|
||||
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()
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,30 @@
|
||||
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()
|
||||
}
|
||||
}
|
||||
181
app/src/main/java/com/halo/assistant/member/MemberRepository.kt
Normal file
181
app/src/main/java/com/halo/assistant/member/MemberRepository.kt
Normal file
@ -0,0 +1,181 @@
|
||||
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 = ""
|
||||
)
|
||||
}
|
||||
147
app/src/main/java/com/halo/assistant/member/MemberUseCase.kt
Normal file
147
app/src/main/java/com/halo/assistant/member/MemberUseCase.kt
Normal file
@ -0,0 +1,147 @@
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
144
app/src/main/res/drawable-night/bg_accelerator_guide.xml
Normal file
144
app/src/main/res/drawable-night/bg_accelerator_guide.xml
Normal file
File diff suppressed because one or more lines are too long
125
app/src/main/res/drawable/bg_accelerator_guide.xml
Normal file
125
app/src/main/res/drawable/bg_accelerator_guide.xml
Normal file
File diff suppressed because one or more lines are too long
@ -0,0 +1,7 @@
|
||||
<?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>
|
||||
10
app/src/main/res/drawable/ic_basic_accelerator.xml
Normal file
10
app/src/main/res/drawable/ic_basic_accelerator.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<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>
|
||||
14
app/src/main/res/drawable/ic_basic_x.xml
Normal file
14
app/src/main/res/drawable/ic_basic_x.xml
Normal file
@ -0,0 +1,14 @@
|
||||
<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>
|
||||
14
app/src/main/res/drawable/ic_basic_x_18.xml
Normal file
14
app/src/main/res/drawable/ic_basic_x_18.xml
Normal file
@ -0,0 +1,14 @@
|
||||
<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>
|
||||
24
app/src/main/res/drawable/ic_free_vip_tag.xml
Normal file
24
app/src/main/res/drawable/ic_free_vip_tag.xml
Normal file
@ -0,0 +1,24 @@
|
||||
<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>
|
||||
21
app/src/main/res/drawable/ic_new_function_text.xml
Normal file
21
app/src/main/res/drawable/ic_new_function_text.xml
Normal file
File diff suppressed because one or more lines are too long
9
app/src/main/res/drawable/ic_triangle_down.xml
Normal file
9
app/src/main/res/drawable/ic_triangle_down.xml
Normal file
@ -0,0 +1,9 @@
|
||||
<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>
|
||||
16
app/src/main/res/layout/activity_batch_register.xml
Normal file
16
app/src/main/res/layout/activity_batch_register.xml
Normal file
@ -0,0 +1,16 @@
|
||||
<?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>
|
||||
@ -279,6 +279,7 @@
|
||||
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">
|
||||
@ -313,7 +314,8 @@
|
||||
app:download_button_show_progress="true"
|
||||
app:download_button_text_size="@dimen/primary_text_size"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@id/cl_speed_container"
|
||||
app:layout_constraintHorizontal_weight="76"
|
||||
app:layout_constraintStart_toEndOf="@+id/localDownloadContainer"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_goneMarginStart="24dp" />
|
||||
@ -387,6 +389,167 @@
|
||||
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>
|
||||
|
||||
34
app/src/main/res/layout/dialog_fragment_accelerator_zone.xml
Normal file
34
app/src/main/res/layout/dialog_fragment_accelerator_zone.xml
Normal file
@ -0,0 +1,34 @@
|
||||
<?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>
|
||||
49
app/src/main/res/layout/dialog_fragment_speed_failure.xml
Normal file
49
app/src/main/res/layout/dialog_fragment_speed_failure.xml
Normal file
@ -0,0 +1,49 @@
|
||||
<?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>
|
||||
@ -0,0 +1,65 @@
|
||||
<?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>
|
||||
@ -0,0 +1,49 @@
|
||||
<?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>
|
||||
@ -0,0 +1,35 @@
|
||||
<?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>
|
||||
@ -132,11 +132,18 @@
|
||||
tools:visibility="visible" />
|
||||
</RelativeLayout>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/iv_arrow"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:srcCompat="@drawable/ic_jump" />
|
||||
<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" />
|
||||
|
||||
</com.gh.common.view.CollapsingMotionLayout>
|
||||
</com.google.android.material.appbar.AppBarLayout>
|
||||
|
||||
40
app/src/main/res/layout/layout_accelerator_guide_page.xml
Normal file
40
app/src/main/res/layout/layout_accelerator_guide_page.xml
Normal file
@ -0,0 +1,40 @@
|
||||
<?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>
|
||||
14
app/src/main/res/layout/recycler_accelerator_zone.xml
Normal file
14
app/src/main/res/layout/recycler_accelerator_zone.xml
Normal file
@ -0,0 +1,14 @@
|
||||
<?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="选择区服" />
|
||||
@ -650,5 +650,30 @@
|
||||
<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>
|
||||
|
||||
|
||||
@ -650,4 +650,29 @@
|
||||
<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>
|
||||
|
||||
@ -20,6 +20,10 @@
|
||||
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>
|
||||
|
||||
@ -97,6 +101,14 @@
|
||||
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">
|
||||
@ -188,5 +200,17 @@
|
||||
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>
|
||||
@ -149,6 +149,8 @@ ext {
|
||||
volcTlsVersion = "1.1.4"
|
||||
|
||||
xcrashVersion = "3.1.0"
|
||||
aliPayVersion = "15.8.17"
|
||||
acceleratorVersion = "1.0.1"
|
||||
}
|
||||
|
||||
apply from: 'dependencies_vasdk.gradle'
|
||||
|
||||
48
feature/accelerator/build.gradle
Normal file
48
feature/accelerator/build.gradle
Normal file
@ -0,0 +1,48 @@
|
||||
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}"
|
||||
}
|
||||
21
feature/accelerator/proguard-rules.pro
vendored
Normal file
21
feature/accelerator/proguard-rules.pro
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
# 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
|
||||
9
feature/accelerator/src/main/AndroidManifest.xml
Normal file
9
feature/accelerator/src/main/AndroidManifest.xml
Normal file
@ -0,0 +1,9 @@
|
||||
<?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>
|
||||
@ -0,0 +1,242 @@
|
||||
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"
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,7 @@
|
||||
<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>
|
||||
3
feature/accelerator/src/main/res/values/strings.xml
Normal file
3
feature/accelerator/src/main/res/values/strings.xml
Normal file
@ -0,0 +1,3 @@
|
||||
<resources>
|
||||
<string name="app_name">accelerator</string>
|
||||
</resources>
|
||||
42
feature/ali_pay/build.gradle
Normal file
42
feature/ali_pay/build.gradle
Normal file
@ -0,0 +1,42 @@
|
||||
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}"
|
||||
}
|
||||
21
feature/ali_pay/proguard-rules.pro
vendored
Normal file
21
feature/ali_pay/proguard-rules.pro
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
# 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
|
||||
13
feature/ali_pay/src/main/AndroidManifest.xml
Normal file
13
feature/ali_pay/src/main/AndroidManifest.xml
Normal file
@ -0,0 +1,13 @@
|
||||
<?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>
|
||||
@ -0,0 +1,44 @@
|
||||
package com.game.gamecenter.alipay
|
||||
|
||||
import android.app.Activity
|
||||
import com.alipay.sdk.app.PayTask
|
||||
import com.gh.gamecenter.core.provider.IAliPayProvider
|
||||
import com.gh.gamecenter.feature.eventbus.EBPayState
|
||||
import io.reactivex.Single
|
||||
|
||||
@com.therouter.inject.ServiceProvider
|
||||
class AliPayProviderImpl : IAliPayProvider {
|
||||
override fun sendRequest(activity: Activity, orderNo: String): Single<Int> {
|
||||
return Single.create {
|
||||
val pay = PayTask(activity)
|
||||
val result = pay.payV2(orderNo, true)
|
||||
val statusCode = result[KEY_RESULT_STATUS]
|
||||
val resultCode = when (statusCode) {
|
||||
PAY_RESULT_CODE_SUCCESS, PAY_RESULT_CODE_HANDLING, PAY_RESULT_CODE_UNKNOWN -> 0
|
||||
|
||||
PAY_RESULT_CODE_CANCEL -> 1
|
||||
|
||||
else -> 2
|
||||
|
||||
}
|
||||
it.onSuccess(resultCode)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
// 订单支付成功。
|
||||
private const val PAY_RESULT_CODE_SUCCESS = "9000"
|
||||
|
||||
// 正在处理中,支付结果未知(有可能已经支付成功),请查询商家订单列表中订单的支付状态
|
||||
private const val PAY_RESULT_CODE_HANDLING = "8000"
|
||||
|
||||
// 支付结果未知(有可能已经支付成功),请查询商家订单列表中订单的支付状态
|
||||
private const val PAY_RESULT_CODE_UNKNOWN = "6004"
|
||||
|
||||
private const val PAY_RESULT_CODE_CANCEL = "6001"
|
||||
|
||||
private const val KEY_RESULT_STATUS = "resultStatus"
|
||||
|
||||
private const val DELAY_DURATION = 1000L
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,78 @@
|
||||
package com.game.gamecenter.alipay
|
||||
|
||||
import android.app.Activity
|
||||
import android.os.Bundle
|
||||
import android.text.TextUtils
|
||||
import android.view.View
|
||||
import android.webkit.CookieManager
|
||||
import android.webkit.WebView
|
||||
import android.webkit.WebViewClient
|
||||
import android.widget.LinearLayout
|
||||
import com.alipay.sdk.app.PayTask
|
||||
|
||||
class H5PayActivity : Activity() {
|
||||
|
||||
private var _webView: WebView? = null
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
val layout = LinearLayout(applicationContext)
|
||||
val params =
|
||||
LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT)
|
||||
layout.orientation = LinearLayout.VERTICAL
|
||||
setContentView(layout)
|
||||
|
||||
_webView = WebView(applicationContext)
|
||||
params.weight = 1F
|
||||
_webView?.let {
|
||||
it.visibility = View.VISIBLE
|
||||
layout.addView(it, params)
|
||||
|
||||
initWebView(it)
|
||||
}
|
||||
}
|
||||
|
||||
private fun initWebView(webView: WebView) {
|
||||
with(webView.settings) {
|
||||
javaScriptEnabled = true
|
||||
javaScriptCanOpenWindowsAutomatically = true
|
||||
CookieManager.getInstance().setAcceptThirdPartyCookies(webView, true)
|
||||
domStorageEnabled = true
|
||||
}
|
||||
with(webView) {
|
||||
webViewClient = MyWebViewClient()
|
||||
loadUrl("url")
|
||||
}
|
||||
}
|
||||
|
||||
private inner class MyWebViewClient : WebViewClient() {
|
||||
override fun shouldOverrideUrlLoading(view: WebView, url: String): Boolean {
|
||||
if (!(url.startsWith("http") || url.startsWith("https"))) {
|
||||
return true
|
||||
}
|
||||
|
||||
/**
|
||||
* 推荐采用的新的二合一接口(payInterceptorWithUrl),只需调用一次
|
||||
*/
|
||||
val task = PayTask(this@H5PayActivity)
|
||||
val isIntercepted = task.payInterceptorWithUrl(url, true) { result ->
|
||||
val url = result.getReturnUrl()
|
||||
if (!TextUtils.isEmpty(url)) {
|
||||
this@H5PayActivity.runOnUiThread {
|
||||
view.loadUrl(url)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否成功拦截
|
||||
* 若成功拦截,则无需继续加载该URL;否则继续加载
|
||||
*/
|
||||
if (!isIntercepted) {
|
||||
view.loadUrl(url)
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
7
feature/ali_pay/src/main/res/values-night/themes.xml
Normal file
7
feature/ali_pay/src/main/res/values-night/themes.xml
Normal file
@ -0,0 +1,7 @@
|
||||
<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>
|
||||
5
feature/ali_pay/src/main/res/values/colors.xml
Normal file
5
feature/ali_pay/src/main/res/values/colors.xml
Normal file
@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<color name="black">#FF000000</color>
|
||||
<color name="white">#FFFFFFFF</color>
|
||||
</resources>
|
||||
3
feature/ali_pay/src/main/res/values/strings.xml
Normal file
3
feature/ali_pay/src/main/res/values/strings.xml
Normal file
@ -0,0 +1,3 @@
|
||||
<resources>
|
||||
<string name="app_name">ali_pay</string>
|
||||
</resources>
|
||||
9
feature/ali_pay/src/main/res/values/themes.xml
Normal file
9
feature/ali_pay/src/main/res/values/themes.xml
Normal file
@ -0,0 +1,9 @@
|
||||
<resources xmlns:tools="http://schemas.android.com/tools">
|
||||
<!-- Base application theme. -->
|
||||
<style name="Base.Theme.Assistantandroid2" parent="Theme.Material3.DayNight.NoActionBar">
|
||||
<!-- Customize your light theme here. -->
|
||||
<!-- <item name="colorPrimary">@color/my_light_primary</item> -->
|
||||
</style>
|
||||
|
||||
<style name="Theme.Assistantandroid2" parent="Base.Theme.Assistantandroid2" />
|
||||
</resources>
|
||||
@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<network-security-config>
|
||||
<base-config cleartextTrafficPermitted="true" />
|
||||
</network-security-config>
|
||||
40
feature/wechat_pay/build.gradle
Normal file
40
feature/wechat_pay/build.gradle
Normal file
@ -0,0 +1,40 @@
|
||||
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.wechat.pay'
|
||||
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(project(path: ":module_common")) {
|
||||
exclude group: 'androidx.swiperefreshlayout'
|
||||
}
|
||||
implementation(project(path: ":module_core_feature"))
|
||||
ksp "cn.therouter:apt:${routerVersion}"
|
||||
}
|
||||
21
feature/wechat_pay/proguard-rules.pro
vendored
Normal file
21
feature/wechat_pay/proguard-rules.pro
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
# 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
|
||||
17
feature/wechat_pay/src/main/AndroidManifest.xml
Normal file
17
feature/wechat_pay/src/main/AndroidManifest.xml
Normal file
@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.gh.gamecenter.wechat.pay">
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
|
||||
<application android:networkSecurityConfig="@xml/network_security_config">
|
||||
<activity
|
||||
android:name="${applicationId}.wxapi.WXPayEntryActivity"
|
||||
android:exported="true"
|
||||
android:label="@string/app_name"
|
||||
android:launchMode="singleTop"
|
||||
android:theme="@android:style/Theme.Translucent.NoTitleBar">
|
||||
</activity>
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
@ -0,0 +1,56 @@
|
||||
package com.gh.gamecenter
|
||||
|
||||
import com.gh.gamecenter.core.HaloApp
|
||||
import com.gh.gamecenter.core.provider.IConfigProvider
|
||||
import com.gh.gamecenter.core.provider.IWechatPayProvider
|
||||
import com.gh.gamecenter.feature.entity.OrderEntity
|
||||
import com.gh.gamecenter.feature.entity.WechatPayEntity
|
||||
import com.tencent.mm.opensdk.modelpay.PayReq
|
||||
import com.tencent.mm.opensdk.openapi.IWXAPI
|
||||
import com.tencent.mm.opensdk.openapi.WXAPIFactory
|
||||
import com.therouter.TheRouter
|
||||
|
||||
/**
|
||||
* 这里必须使用单例模式,需要保存 orderNo,以便后续查询订单使用
|
||||
*/
|
||||
@com.therouter.inject.ServiceProvider
|
||||
class WechatPayProviderImpl : IWechatPayProvider {
|
||||
private var api: IWXAPI
|
||||
|
||||
private var _orderNo: String = ""
|
||||
override val orderNo: String
|
||||
get() = _orderNo
|
||||
|
||||
private var _order: OrderEntity? = null
|
||||
override val order: Any?
|
||||
get() = _order
|
||||
|
||||
init {
|
||||
val config = TheRouter.get(IConfigProvider::class.java)
|
||||
api = WXAPIFactory.createWXAPI(HaloApp.getInstance().applicationContext, config?.getWechatAppId(), false)
|
||||
}
|
||||
|
||||
override fun payRequest(order: Any, payRequest: Any) {
|
||||
if (order is OrderEntity) {
|
||||
_order = order
|
||||
}
|
||||
if (payRequest is WechatPayEntity) {
|
||||
_orderNo = payRequest.orderNo
|
||||
val request = PayReq().apply {
|
||||
appId = payRequest.appId
|
||||
partnerId = payRequest.partnerId
|
||||
prepayId = payRequest.prepayId
|
||||
packageValue = payRequest.packageValue
|
||||
nonceStr = payRequest.nonceStr
|
||||
timeStamp = payRequest.timestamp
|
||||
sign = payRequest.sign
|
||||
}
|
||||
api.sendReq(request)
|
||||
}
|
||||
}
|
||||
|
||||
override fun clear() {
|
||||
_orderNo = ""
|
||||
_order = null
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,88 @@
|
||||
package com.gh.gamecenter.wxapi
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import com.gh.gamecenter.WechatPayProviderImpl
|
||||
import com.gh.gamecenter.common.utils.SensorsBridge
|
||||
import com.gh.gamecenter.core.provider.IConfigProvider
|
||||
import com.gh.gamecenter.core.provider.IWechatPayProvider
|
||||
import com.gh.gamecenter.core.provider.IWechatPayResultProvider
|
||||
import com.gh.gamecenter.feature.entity.OrderEntity
|
||||
import com.gh.gamecenter.feature.eventbus.EBPayState
|
||||
import com.tencent.mm.opensdk.constants.ConstantsAPI
|
||||
import com.tencent.mm.opensdk.modelbase.BaseReq
|
||||
import com.tencent.mm.opensdk.modelbase.BaseResp
|
||||
import com.tencent.mm.opensdk.openapi.IWXAPI
|
||||
import com.tencent.mm.opensdk.openapi.IWXAPIEventHandler
|
||||
import com.tencent.mm.opensdk.openapi.WXAPIFactory
|
||||
import com.therouter.TheRouter
|
||||
|
||||
class WXPayEntryActivity : Activity(), IWXAPIEventHandler {
|
||||
|
||||
private lateinit var api: IWXAPI
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
val config = TheRouter.get(IConfigProvider::class.java)
|
||||
api = WXAPIFactory.createWXAPI(this, config!!.getWechatAppId(), false)
|
||||
api.handleIntent(intent, this)
|
||||
}
|
||||
|
||||
override fun onNewIntent(intent: Intent?) {
|
||||
super.onNewIntent(intent)
|
||||
setIntent(intent)
|
||||
api.handleIntent(intent, this)
|
||||
}
|
||||
|
||||
override fun onReq(reqeust: BaseReq?) {
|
||||
}
|
||||
|
||||
override fun onResp(response: BaseResp) {
|
||||
if (response.type == ConstantsAPI.COMMAND_PAY_BY_WX) {
|
||||
val payProvider = TheRouter.get(IWechatPayProvider::class.java)
|
||||
val order = payProvider?.order as? OrderEntity
|
||||
when (response.errCode) {
|
||||
PAY_RESULT_SUCCESSFULLY -> {
|
||||
|
||||
if (payProvider is WechatPayProviderImpl) {
|
||||
val nonceStr = payProvider.orderNo
|
||||
TheRouter.get(IWechatPayResultProvider::class.java)?.onPayComplete(nonceStr, order)
|
||||
}
|
||||
}
|
||||
|
||||
PAY_RESULT_FAILURE -> {
|
||||
SensorsBridge.trackMemberRechargeResult(
|
||||
PAYMENT_TYPE_WECHAT,
|
||||
order?.setMenuName ?: "",
|
||||
order?.paymentAmount ?: "",
|
||||
RECHARGE_RESULT_FAILURE
|
||||
)
|
||||
|
||||
org.greenrobot.eventbus.EventBus.getDefault().post(EBPayState.PayFail)
|
||||
}
|
||||
|
||||
PAY_RESULT_CANCEL -> {
|
||||
SensorsBridge.trackMemberRechargeResult(
|
||||
PAYMENT_TYPE_WECHAT,
|
||||
order?.setMenuName ?: "",
|
||||
order?.paymentAmount ?: "",
|
||||
RECHARGE_RESULT_CANCEL
|
||||
)
|
||||
org.greenrobot.eventbus.EventBus.getDefault().post(EBPayState.PayCancel)
|
||||
}
|
||||
}
|
||||
payProvider?.clear()
|
||||
finish()
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val PAY_RESULT_SUCCESSFULLY = 0
|
||||
private const val PAY_RESULT_FAILURE = -1
|
||||
private const val PAY_RESULT_CANCEL = -2
|
||||
private const val PAYMENT_TYPE_WECHAT = "微信"
|
||||
private const val RECHARGE_RESULT_CANCEL = "充值取消"
|
||||
private const val RECHARGE_RESULT_FAILURE = "充值失败"
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
<resources>
|
||||
<string name="app_name">光環助手</string>
|
||||
</resources>
|
||||
3
feature/wechat_pay/src/main/res/values/strings.xml
Normal file
3
feature/wechat_pay/src/main/res/values/strings.xml
Normal file
@ -0,0 +1,3 @@
|
||||
<resources>
|
||||
<string name="app_name">光环助手</string>
|
||||
</resources>
|
||||
@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<network-security-config>
|
||||
<base-config cleartextTrafficPermitted="true" />
|
||||
</network-security-config>
|
||||
@ -299,6 +299,10 @@ public class Constants {
|
||||
// 腾讯企点地址
|
||||
public static final String TENCENT_QIDIAN_ADDRESS = "https://admin.qidian.qq.com/template/blue/mp/menu/qr-code-jump.html?linkType=0&env=ol&kfuin=2355094296&fid=457&key=c76dcb2e3d582b6ffbfb5bb22cde85ff&cate=1&source=&isLBS=&isCustomEntry=&type=16&ftype=1&_type=wpa&qidian=true";
|
||||
|
||||
// 企点qq连接
|
||||
public static final String QQ_QIDIAN_ADDRESS = "https://wpa1.qq.com/XqJqVq2d?_type=wpa&qidian=true";
|
||||
|
||||
|
||||
//版规声明
|
||||
public static final String FORUM_REGULATIONS_NEWS_ID = "5f4db9cc34d44d01b92fd670";
|
||||
|
||||
@ -345,6 +349,10 @@ public class Constants {
|
||||
//游戏单管理规范
|
||||
public static final String GAME_COLLECTION_RULE = "https://and-static.ghzs66.com/page/privacy_policies/game_collection.html";
|
||||
|
||||
// 我的资产页面
|
||||
public static final String MY_ASSETS_DEV = "https://dev-and-static.ghzs.com/web/qiyou-acc/index.html";
|
||||
public static final String MY_ASSETS = "https://and-static.ghzs.com/web/qiyou-acc/index.html";
|
||||
|
||||
public static final String SP_IS_DEV_ENV = "is_dev_env";
|
||||
|
||||
public static final String[] REPORT_LIST = new String[]{"垃圾广告营销", "恶意攻击谩骂", "淫秽色情信息", "违法有害信息", "其他原因"};
|
||||
@ -482,4 +490,9 @@ public class Constants {
|
||||
|
||||
public static final String SP_VIDEO_COVER_CACHE = "sp_video_cover_cache";
|
||||
|
||||
public static final String SP_HAS_SHOW_ACCELERATION_GUIDE_LAYER = "sp_has_show_acceleration_guide_layer";
|
||||
|
||||
public static final String SP_MEMBER_RECHARGE_BUTTON_CLICK = "sp_member_recharge_button_click";
|
||||
public static final String SP_MEMBER_PAYMENT_BUTTON_CLICK = "sp_member_payment_button_click";
|
||||
|
||||
}
|
||||
|
||||
@ -369,4 +369,10 @@ public class EntranceConsts {
|
||||
public static final String KEY_UID = "uid";
|
||||
|
||||
public static final String KEY_DISPLAY_TYPE = "display_type";
|
||||
|
||||
public static final String KEY_ACCT_GAME_INFO = "acct_game_info";
|
||||
public static final String KEY_IS_NEED_RECORD = "is_need_record";
|
||||
public static final String KEY_HAS_MULTI_ZONE = "has_multi_zone";
|
||||
public static final String KEY_SPEED_TYPE = "speed_type";
|
||||
public static final String KEY_ACCELERATOR_REQUEST = "accelerator_request";
|
||||
}
|
||||
|
||||
@ -76,7 +76,7 @@ object SensorsBridge {
|
||||
private const val KEY_GAME_FORUM_TYPE = "game_forum_type"
|
||||
private const val KEY_STAY_LENGTH = "stay_length"
|
||||
private const val KEY_SHARE_TYPE = "share_type"
|
||||
private const val KEY_IS_FIRST_TIME = "\$is_first_time"
|
||||
const val KEY_IS_FIRST_TIME = "\$is_first_time"
|
||||
private const val KEY_TAB_TYPE = "tab_type"
|
||||
private const val KEY_BANNER_NAME = "banner_name"
|
||||
private const val KEY_TOPPING_TYPE = "topping_type"
|
||||
@ -123,6 +123,14 @@ object SensorsBridge {
|
||||
private const val KEY_WECHAT_REMIND = "wechat_remind"
|
||||
private const val KEY_MESSAGE_REMIND = "message_remind"
|
||||
private const val KEY_AUTOMATIC_DOWNLOAD = "automatic_download"
|
||||
private const val KEY_PACKAGE_NAME = "package_name"
|
||||
private const val KEY_MEMBER_TYPE = "member_type"
|
||||
private const val KEY_DISTRICT_SERVER = "district_server"
|
||||
private const val KEY_SCENE_TYPE = "scene_type"
|
||||
private const val KEY_SET_MENU_NAME = "set_menu_name"
|
||||
private const val KEY_PAYMENT_AMOUNT = "payment_amount"
|
||||
private const val KEY_PAYMENT_TYPE = "payment_type"
|
||||
const val EVENT_NAME = "event_name"
|
||||
|
||||
private const val EVENT_GAME_DETAIL_PAGE_TAB_SELECT = "GameDetailPageTabSelect"
|
||||
private const val EVENT_GAME_DETAIL_PAGE_TAG_CLICK = "GameDetailPageGameTagClick"
|
||||
@ -307,6 +315,23 @@ object SensorsBridge {
|
||||
private const val EVENT_APPOINTMENT_GAME_ONLINE_DIALOG_CLICK = "AppointmentGameOnlineDialogClick"
|
||||
private const val EVENT_JIGUANG_PUSH_CLICK = "JiGuangPushClick"
|
||||
|
||||
private const val EVENT_NETWORK_ACCELERATION_GUIDANCE_DIAGRAM_SHOW = "NetworkAccelerationGuidanceDiagramShow"
|
||||
private const val EVENT_NETWORK_ACCELERATION_BUTTON_CLICK = "NetworkAccelerationButtonClick"
|
||||
private const val EVENT_NETWORK_ACCELERATION_START_UP = "NetworkAccelerationStartup"
|
||||
private const val EVENT_NETWORK_ACCELERATION_START_UP_RESULT = "NetworkAccelerationStartupResult"
|
||||
private const val EVENT_NETWORK_ACCELERATION_OTHER_BUTTON_CLICK = "NetworkAccelerationOtherButtonClick"
|
||||
private const val EVENT_MEMBERSHIP_ACTIVATION_DIALOG_SHOW = "MembershipActivationDialogShow"
|
||||
private const val EVENT_MEMBERSHIP_ACTIVATION_DIALOG_CLICK = "MembershipActivationDialogClick"
|
||||
private const val EVENT_NETWORK_ACCELERATION_FAILURE_DIALOG_SHOW = "NetworkAccelerationFailureDialogShow"
|
||||
private const val EVENT_NETWORK_ACCELERATION_FAILURE_DIALOG_CLICK = "NetworkAccelerationFailureDialogClick"
|
||||
private const val EVENT_NETWORK_ACCELERATION_CONFLICT_DIALOG_SHOW = "NetworkAccelerationConflictDialogShow"
|
||||
private const val EVENT_NETWORK_ACCELERATION_CONFLICT_DIALOG_CLICK = "NetworkAccelerationConflictDialogClick"
|
||||
private const val EVENT_MY_ASSETS_PAGE_SHOW = "MyAssetsPageShow"
|
||||
const val EVENT_MEMBER_RECHARGE_BUTTON_CLICK = "MemberRechargeButtonClick"
|
||||
private const val EVENT_MEMBER_PAYMENT_BUTTON_CLICK = "MemberPaymentButtonClick"
|
||||
private const val EVENT_MEMBER_RECHARGE_RESULT = "MemberRechargeResult"
|
||||
private const val EVENT_MY_ASSETS_PAGE_CONTACT_CUSTOMER_SERVICE_CLICK = "MyAssetsPageContactCustomerServiceClick"
|
||||
|
||||
private var mIsSensorsEnabled = false
|
||||
|
||||
private val mSensor by lazy {
|
||||
@ -5002,6 +5027,7 @@ object SensorsBridge {
|
||||
}
|
||||
trackEvent(EVENT_APPOINTMENT_GAME_ONLINE_DIALOG_CLICK, json)
|
||||
}
|
||||
|
||||
/**
|
||||
* 事件ID:SearchDiscoveryClick
|
||||
* 事件名称:搜索发现点击事件
|
||||
@ -5050,4 +5076,341 @@ object SensorsBridge {
|
||||
}
|
||||
trackEvent(EVENT_JIGUANG_PUSH_CLICK, json)
|
||||
}
|
||||
|
||||
/**
|
||||
* 事件ID:NetworkAccelerationGuidanceDiagramShow
|
||||
* 事件名称:网络加速引导图展示事件
|
||||
* 触发时机:网络加速引导图展示触发
|
||||
*/
|
||||
fun trackNetworkAccelerationGuidanceDiagramShow(
|
||||
packageName: String,
|
||||
gameId: String,
|
||||
gameName: String
|
||||
) {
|
||||
val json = json {
|
||||
KEY_PACKAGE_NAME to packageName
|
||||
KEY_GAME_ID to gameId
|
||||
KEY_GAME_NAME to gameName
|
||||
}
|
||||
trackEvent(EVENT_NETWORK_ACCELERATION_GUIDANCE_DIAGRAM_SHOW, json)
|
||||
}
|
||||
|
||||
/**
|
||||
* 事件ID:NetworkAccelerationButtonClick
|
||||
* 事件名称:网络加速按钮点击事件
|
||||
* 触发时机:用户点击网络加速按钮时触发上报以及点击时的具体场景以及用户的相关属性
|
||||
*/
|
||||
fun trackNetworkAccelerationButtonClick(
|
||||
packageName: String,
|
||||
gameId: String,
|
||||
gameName: String,
|
||||
memberType: String,
|
||||
districtServer: String,
|
||||
sceneType: String,
|
||||
sourceEntrance: String
|
||||
) {
|
||||
val json = json {
|
||||
KEY_PACKAGE_NAME to packageName
|
||||
KEY_GAME_ID to gameId
|
||||
KEY_GAME_NAME to gameName
|
||||
KEY_MEMBER_TYPE to memberType
|
||||
KEY_DISTRICT_SERVER to districtServer
|
||||
KEY_SCENE_TYPE to sceneType
|
||||
KEY_SOURCE_ENTRANCE to sourceEntrance
|
||||
}
|
||||
trackEvent(EVENT_NETWORK_ACCELERATION_BUTTON_CLICK, json)
|
||||
}
|
||||
|
||||
/**
|
||||
* 事件ID:NetworkAccelerationStartup
|
||||
* 事件名称:网络加速启动事件
|
||||
* 触发时机:调用奇游SDK进行加速时进行上报
|
||||
*/
|
||||
fun trackNetworkAccelerationStartup(
|
||||
packageName: String,
|
||||
gameId: String,
|
||||
gameName: String,
|
||||
memberType: String,
|
||||
districtServer: String,
|
||||
sourceEntrance: String
|
||||
) {
|
||||
val json = json {
|
||||
KEY_PACKAGE_NAME to packageName
|
||||
KEY_GAME_ID to gameId
|
||||
KEY_GAME_NAME to gameName
|
||||
KEY_MEMBER_TYPE to memberType
|
||||
KEY_DISTRICT_SERVER to districtServer
|
||||
KEY_SOURCE_ENTRANCE to sourceEntrance
|
||||
}
|
||||
trackEvent(EVENT_NETWORK_ACCELERATION_START_UP, json)
|
||||
}
|
||||
|
||||
/**
|
||||
* 事件ID:NetworkAccelerationStartupResult
|
||||
* 事件名称:网络加速启动结果事件
|
||||
* 触发时机:调用奇游SDK进行加速时成功\失败时触发上报,失败是需上报具体的code码
|
||||
*/
|
||||
fun trackNetworkAccelerationStartupResult(
|
||||
packageName: String,
|
||||
gameId: String,
|
||||
gameName: String,
|
||||
memberType: String,
|
||||
districtServer: String,
|
||||
result: String,
|
||||
sourceEntrance: String
|
||||
) {
|
||||
val json = json {
|
||||
KEY_PACKAGE_NAME to packageName
|
||||
KEY_GAME_ID to gameId
|
||||
KEY_GAME_NAME to gameName
|
||||
KEY_MEMBER_TYPE to memberType
|
||||
KEY_DISTRICT_SERVER to districtServer
|
||||
KEY_RESULT to result
|
||||
KEY_SOURCE_ENTRANCE to sourceEntrance
|
||||
}
|
||||
trackEvent(EVENT_NETWORK_ACCELERATION_START_UP_RESULT, json)
|
||||
}
|
||||
|
||||
/**
|
||||
* 事件ID:NetworkAccelerationOtherButtonClick
|
||||
* 事件名称:网络加速其他按钮点击事件
|
||||
* 触发时机:点击【进入游戏\停止加速】时,触发上报
|
||||
*/
|
||||
fun trackNetworkAccelerationOtherButtonClick(
|
||||
packageName: String,
|
||||
gameId: String,
|
||||
gameName: String,
|
||||
memberType: String,
|
||||
buttonName: String,
|
||||
sourceEntrance: String
|
||||
) {
|
||||
val json = json {
|
||||
KEY_PACKAGE_NAME to packageName
|
||||
KEY_GAME_ID to gameId
|
||||
KEY_GAME_NAME to gameName
|
||||
KEY_MEMBER_TYPE to memberType
|
||||
KEY_BUTTON_NAME to buttonName
|
||||
KEY_SOURCE_ENTRANCE to sourceEntrance
|
||||
}
|
||||
trackEvent(EVENT_NETWORK_ACCELERATION_OTHER_BUTTON_CLICK, json)
|
||||
}
|
||||
|
||||
/**
|
||||
* 事件ID:MembershipActivationDialogShow
|
||||
* 事件名称:会员开通提示弹窗展示事件
|
||||
* 触发时机:会员提示弹窗展示时触发上报
|
||||
*/
|
||||
fun trackMembershipActivationDialogShow(
|
||||
packageName: String,
|
||||
gameId: String,
|
||||
gameName: String,
|
||||
sourceEntrance: String
|
||||
) {
|
||||
val json = json {
|
||||
KEY_PACKAGE_NAME to packageName
|
||||
KEY_GAME_ID to gameId
|
||||
KEY_GAME_NAME to gameName
|
||||
KEY_SOURCE_ENTRANCE to sourceEntrance
|
||||
}
|
||||
trackEvent(EVENT_MEMBERSHIP_ACTIVATION_DIALOG_SHOW, json)
|
||||
}
|
||||
|
||||
/**
|
||||
* 事件ID:MembershipActivationDialogClick
|
||||
* 事件名称:会员开通提示弹窗点击事件
|
||||
* 触发时机:用户点击会员提示弹窗的按钮【去开通】时触发上报
|
||||
*/
|
||||
fun trackMembershipActivationDialogClick(
|
||||
packageName: String,
|
||||
gameId: String,
|
||||
gameName: String,
|
||||
sourceEntrance: String
|
||||
) {
|
||||
val json = json {
|
||||
KEY_PACKAGE_NAME to packageName
|
||||
KEY_GAME_ID to gameId
|
||||
KEY_GAME_NAME to gameName
|
||||
KEY_SOURCE_ENTRANCE to sourceEntrance
|
||||
}
|
||||
trackEvent(EVENT_MEMBERSHIP_ACTIVATION_DIALOG_CLICK, json)
|
||||
}
|
||||
|
||||
/**
|
||||
* 事件ID:NetworkAccelerationFailureDialogShow
|
||||
* 事件名称:加速失败提示弹窗展示事件
|
||||
* 触发时机:加速失败提示弹窗展示时触发上报
|
||||
*/
|
||||
fun trackNetworkAccelerationFailureDialogShow(
|
||||
packageName: String,
|
||||
gameId: String,
|
||||
gameName: String,
|
||||
sourceEntrance: String
|
||||
) {
|
||||
val json = json {
|
||||
KEY_PACKAGE_NAME to packageName
|
||||
KEY_GAME_ID to gameId
|
||||
KEY_GAME_NAME to gameName
|
||||
KEY_SOURCE_ENTRANCE to sourceEntrance
|
||||
}
|
||||
trackEvent(EVENT_NETWORK_ACCELERATION_FAILURE_DIALOG_SHOW, json)
|
||||
}
|
||||
|
||||
/**
|
||||
* 事件ID:NetworkAccelerationFailureDialogClick
|
||||
* 事件名称:加速失败提示弹窗点击事件
|
||||
* 触发时机:用户点击加速失败提示弹窗的按钮【联系客服】时触发上报
|
||||
*/
|
||||
fun trackNetworkAccelerationFailureDialogClick(
|
||||
packageName: String,
|
||||
gameId: String,
|
||||
gameName: String,
|
||||
sourceEntrance: String
|
||||
) {
|
||||
val json = json {
|
||||
KEY_PACKAGE_NAME to packageName
|
||||
KEY_GAME_ID to gameId
|
||||
KEY_GAME_NAME to gameName
|
||||
KEY_SOURCE_ENTRANCE to sourceEntrance
|
||||
}
|
||||
trackEvent(EVENT_NETWORK_ACCELERATION_FAILURE_DIALOG_CLICK, json)
|
||||
}
|
||||
|
||||
/**
|
||||
* 事件ID:NetworkAccelerationConflictDialogShow
|
||||
* 事件名称:加速冲突提示弹窗展示事件
|
||||
* 触发时机:加速冲突提示弹窗展示时触发上报
|
||||
*/
|
||||
fun trackNetworkAccelerationConflictDialogShow(
|
||||
packageName: String,
|
||||
gameId: String,
|
||||
gameName: String,
|
||||
sourceEntrance: String
|
||||
) {
|
||||
val json = json {
|
||||
KEY_PACKAGE_NAME to packageName
|
||||
KEY_GAME_ID to gameId
|
||||
KEY_GAME_NAME to gameName
|
||||
KEY_SOURCE_ENTRANCE to sourceEntrance
|
||||
}
|
||||
trackEvent(EVENT_NETWORK_ACCELERATION_CONFLICT_DIALOG_SHOW, json)
|
||||
}
|
||||
|
||||
/**
|
||||
* 事件ID:NetworkAccelerationConflictDialogClick
|
||||
* 事件名称:加速冲突提示弹窗点击事件
|
||||
* 触发时机:用户点击加速冲突提示弹窗的按钮【暂不启动】\【继续启动】时触发上报
|
||||
*/
|
||||
fun trackNetworkAccelerationConflictDialogClick(
|
||||
packageName: String,
|
||||
gameId: String,
|
||||
gameName: String,
|
||||
buttonName: String,
|
||||
sourceEntrance: String
|
||||
) {
|
||||
val json = json {
|
||||
KEY_PACKAGE_NAME to packageName
|
||||
KEY_GAME_ID to gameId
|
||||
KEY_GAME_NAME to gameName
|
||||
KEY_BUTTON_NAME to buttonName
|
||||
KEY_SOURCE_ENTRANCE to sourceEntrance
|
||||
}
|
||||
trackEvent(EVENT_NETWORK_ACCELERATION_CONFLICT_DIALOG_CLICK, json)
|
||||
}
|
||||
|
||||
/**
|
||||
* 事件ID:MyAssetsPageShow
|
||||
* 事件名称:我的资产页面展示事件
|
||||
* 触发时机:进入我的资产页面时触发上报
|
||||
*/
|
||||
fun trackMyAssetsPageShow(
|
||||
packageName: String,
|
||||
gameId: String,
|
||||
gameName: String,
|
||||
sourceEntrance: String
|
||||
) {
|
||||
val json = json {
|
||||
KEY_PACKAGE_NAME to packageName
|
||||
KEY_GAME_ID to gameId
|
||||
KEY_GAME_NAME to gameName
|
||||
KEY_SOURCE_ENTRANCE to sourceEntrance
|
||||
}
|
||||
trackEvent(EVENT_MY_ASSETS_PAGE_SHOW, json)
|
||||
}
|
||||
|
||||
/**
|
||||
* 事件ID:MemberRechargeButtonClick
|
||||
* 事件名称:会员充值按钮点击事件
|
||||
* 触发时机:用户点击立即支付按钮时触发上报
|
||||
* note:这个事件目前有 web 调用调用原生方法上报
|
||||
*/
|
||||
fun trackMemberRechargeButtonClick(
|
||||
isFirstTime: Boolean,
|
||||
setMenuName: String,
|
||||
paymentAmount: String
|
||||
) {
|
||||
val json = json {
|
||||
KEY_IS_FIRST_TIME to isFirstTime
|
||||
KEY_SET_MENU_NAME to setMenuName
|
||||
KEY_PAYMENT_AMOUNT to paymentAmount
|
||||
}
|
||||
trackEvent(EVENT_MEMBER_RECHARGE_BUTTON_CLICK, json)
|
||||
}
|
||||
|
||||
/**
|
||||
* 事件ID:MemberPaymentButtonClick
|
||||
* 事件名称:会员充值按钮点击事件
|
||||
* 触发时机:用户点击立即支付按钮时触发上报
|
||||
*/
|
||||
fun trackMemberPaymentButtonClick(
|
||||
isFirstTime: Boolean,
|
||||
paymentType: String,
|
||||
setMenuName: String,
|
||||
paymentAmount: String
|
||||
) {
|
||||
val json = json {
|
||||
KEY_IS_FIRST_TIME to isFirstTime
|
||||
KEY_SET_MENU_NAME to setMenuName
|
||||
KEY_PAYMENT_AMOUNT to paymentAmount
|
||||
KEY_PAYMENT_TYPE to paymentType
|
||||
}
|
||||
trackEvent(EVENT_MEMBER_PAYMENT_BUTTON_CLICK, json)
|
||||
}
|
||||
|
||||
/**
|
||||
* 事件ID:MemberRechargeResult
|
||||
* 事件名称:会员充值结果返回事件
|
||||
* 触发时机:支付的回调结果返回时触发上报
|
||||
*/
|
||||
fun trackMemberRechargeResult(
|
||||
paymentType: String,
|
||||
setMenuName: String,
|
||||
paymentAmount: String,
|
||||
result: String
|
||||
) {
|
||||
val json = json {
|
||||
KEY_PAYMENT_TYPE to paymentType
|
||||
KEY_SET_MENU_NAME to setMenuName
|
||||
KEY_PAYMENT_AMOUNT to paymentAmount
|
||||
KEY_RESULT to result
|
||||
}
|
||||
trackEvent(EVENT_MEMBER_RECHARGE_RESULT, json)
|
||||
}
|
||||
|
||||
/**
|
||||
* 事件ID:MyAssetsPageContactCustomerServiceClick
|
||||
* 事件名称:我的资产联系客服点击事件
|
||||
* 触发时机:用户在【我的资产】点击联系客服时触发上报
|
||||
*/
|
||||
fun trackMyAssetsPageContactCustomerServiceClick() {
|
||||
trackEvent(EVENT_MY_ASSETS_PAGE_CONTACT_CUSTOMER_SERVICE_CLICK)
|
||||
}
|
||||
|
||||
fun trackSensorsAnalyticsFromWeb(eventName: String, hashmap: HashMap<String, Any>) {
|
||||
val json = json {
|
||||
hashmap.iterator().forEach { (key, value) ->
|
||||
key to value
|
||||
}
|
||||
}
|
||||
trackEvent(eventName, json)
|
||||
}
|
||||
}
|
||||
16
module_common/src/main/res/layout/activity_member.xml
Normal file
16
module_common/src/main/res/layout/activity_member.xml
Normal file
@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<com.gh.gamecenter.common.view.StatusBarView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@color/primary_theme_20"/>
|
||||
|
||||
<FrameLayout
|
||||
android:id="@id/layout_activity_content"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
</LinearLayout>
|
||||
@ -5,6 +5,8 @@
|
||||
<color name="primary_theme">#2888E0</color>
|
||||
<!-- 蓝-10 -->
|
||||
<color name="primary_theme_10">#1A2888E0</color>
|
||||
<!-- 蓝-20 -->
|
||||
<color name="primary_theme_20">#332888E0</color>
|
||||
<!-- 蓝-30 -->
|
||||
<color name="primary_theme_30">#4D2888E0</color>
|
||||
<!-- 蓝-70 -->
|
||||
|
||||
@ -5,6 +5,8 @@
|
||||
<color name="primary_theme">#2496FF</color>
|
||||
<!-- 蓝-10 -->
|
||||
<color name="primary_theme_10">#1A2496FF</color>
|
||||
<!-- 蓝-20 -->
|
||||
<color name="primary_theme_20">#332496FF</color>
|
||||
<!-- 蓝-30 -->
|
||||
<color name="primary_theme_30">#4D2496FF</color>
|
||||
<!-- 蓝-70 -->
|
||||
|
||||
@ -0,0 +1,41 @@
|
||||
package com.gh.gamecenter.core.callback
|
||||
|
||||
interface OnAccelerateListener {
|
||||
|
||||
fun onStateChanged(state: AccelerateState)
|
||||
|
||||
fun onProgress(progress: Int, curGamePkgName: String?, curGameZoneFlag: String?)
|
||||
|
||||
fun onVipStatusChanged(isNewUser: Boolean, isVip: Boolean)
|
||||
}
|
||||
|
||||
sealed class AccelerateState(val code: Int) {
|
||||
// token 过期
|
||||
val isTokenExpired: Boolean
|
||||
get() = code == ACCT_CODE_TOKEN_EXPIRED
|
||||
|
||||
val isTokenEmpty: Boolean
|
||||
get() = code == ACCT_CODE_TOKEN_EMPTY
|
||||
|
||||
val isSkipError: Boolean
|
||||
get() = skipErrorCodes.any { it == code }
|
||||
|
||||
data class Normal(private val _code: Int) : AccelerateState(_code)
|
||||
|
||||
data class Starting(private val _code: Int) : AccelerateState(_code)
|
||||
|
||||
data class Success(val acctGameInfo: Any?, private val _code: Int) : AccelerateState(_code)
|
||||
|
||||
data class Failure(private val _code: Int) : AccelerateState(_code)
|
||||
|
||||
data class OkStopping(private val _code: Int) : AccelerateState(_code)
|
||||
|
||||
data class ErrStopping(private val _code: Int) : AccelerateState(_code)
|
||||
|
||||
companion object {
|
||||
private const val ACCT_CODE_TOKEN_EMPTY = 102
|
||||
private const val ACCT_CODE_TOKEN_EXPIRED = 200 // token过期
|
||||
private const val ACCT_CODE_PERMISSION_DENIED = 290 // 用户拒绝权限
|
||||
private val skipErrorCodes = arrayOf(ACCT_CODE_PERMISSION_DENIED)
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,37 @@
|
||||
package com.gh.gamecenter.core.provider
|
||||
|
||||
import android.app.Application
|
||||
import com.gh.gamecenter.core.callback.OnAccelerateListener
|
||||
import com.therouter.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
interface IAcceleratorProvider {
|
||||
|
||||
fun init(application: Application, version: String)
|
||||
|
||||
fun setQyUserToken(token: String, callback: ((Boolean) -> Unit)? = null)
|
||||
|
||||
fun setVipEntity(vip: Any)
|
||||
|
||||
fun isNewUser(): Boolean
|
||||
|
||||
fun isVip(): Boolean
|
||||
|
||||
fun isPaidUser(): Boolean
|
||||
|
||||
fun getMemberType(): String
|
||||
|
||||
fun deleteQyUserToken(): Boolean
|
||||
|
||||
fun startQyGameAccelerate(accGameInfo: Any)
|
||||
|
||||
fun stopQyGameAccelerate(appLayerCallStopMsg: String? = null): Boolean
|
||||
|
||||
fun bindAccRelatedListener(pkgName: String, listener: OnAccelerateListener)
|
||||
|
||||
fun unBindAccRelatedListener(listener: OnAccelerateListener)
|
||||
|
||||
fun loadQyGameZoneData(packageName: String, callback: (List<Any>) -> Unit)
|
||||
|
||||
fun isCurAccSuccess(): Boolean
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user