Compare commits
34 Commits
feat/apk_m
...
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
|
||||
|
||||
@ -346,7 +346,7 @@ repositories {
|
||||
android.applicationVariants.configureEach { variant ->
|
||||
variant.mergeAssets.doLast {
|
||||
def assetDir = variant.mergeAssetsProvider.get().outputDir.get()
|
||||
def unwantedAssets = ['1832823466', 'gdt_plugin/gdtadv2.jar']
|
||||
def unwantedAssets = ['2011394667', 'gdt_plugin/gdtadv2.jar']
|
||||
|
||||
unwantedAssets.each { assetPath ->
|
||||
def file = new File([assetDir, assetPath].join(File.separator))
|
||||
@ -515,7 +515,6 @@ dependencies {
|
||||
}
|
||||
|
||||
implementation(project(':feature:media_select'))
|
||||
implementation(project(':feature:apk_manager'))
|
||||
|
||||
implementation(project(":module_va_api"))
|
||||
implementation(project(":va-archive-common"))
|
||||
|
||||
@ -20,7 +20,6 @@
|
||||
-keep class com.gh.gamecenter.db.info.* {*;}
|
||||
-keep class com.gh.gamecenter.entity.** {<fields>;}
|
||||
-keep class com.gh.gamecenter.qa.entity.** {<fields>;}
|
||||
-keep class com.gh.gamecenter.gamedetail.entity.** {<fields>;}
|
||||
-keep class com.gh.download.DownloadDataSimpleEntity {<fields>;}
|
||||
-keep class com.gh.gamecenter.floatingwindow.FloatingWindowEntity {<fields>;}
|
||||
-keep class com.gh.gamecenter.BR
|
||||
|
||||
@ -83,9 +83,29 @@
|
||||
tv.danmaku.ijk.media.exo2,
|
||||
pl.droidsonroids.gif,
|
||||
com.lzf.easyfloat,
|
||||
com.airbnb.lottie.compose,
|
||||
androidx.compose.ui.platform,
|
||||
androidx.compose.material.icons,
|
||||
androidx.activity.compose,
|
||||
androidx.compose.ui.tooling,
|
||||
androidx.compose.ui.tooling.data,
|
||||
androidx.compose.material.ripple,
|
||||
androidx.compose.foundation,
|
||||
androidx.compose.animation,
|
||||
androidx.compose.foundation.layout,
|
||||
androidx.compose.ui.text,
|
||||
androidx.compose.ui.graphics,
|
||||
androidx.compose.ui.unit,
|
||||
androidx.compose.ui.util,
|
||||
androidx.compose.ui.geometry,
|
||||
androidx.compose.runtime.saveable,
|
||||
androidx.compose.animation.core,
|
||||
androidx.constraintlayout.compose,
|
||||
androidx.compose.ui.test.manifest,
|
||||
com.bytedance.sdk.openadsdk,
|
||||
com.bykv.vk.openvk,
|
||||
com.bytedance.tools,
|
||||
androidx.compose.ui.tooling.preview,
|
||||
com.tencent.qqmini,
|
||||
com.tencent.qqmini.minigame.external,
|
||||
com.tencent.qqmini.minigame.opensdk,
|
||||
@ -797,7 +817,11 @@
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name="com.halo.assistant.accelerator.MyAssetsActivity"
|
||||
android:name="com.halo.assistant.member.MemberActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name=".BatchRegisterActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<!-- <activity-->
|
||||
|
||||
@ -27,8 +27,8 @@ import com.gh.gamecenter.MainActivity
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.base.activity.BaseActivity
|
||||
import com.gh.gamecenter.common.constant.Constants
|
||||
import com.gh.gamecenter.common.constant.RouteConsts
|
||||
import com.gh.gamecenter.common.exposure.ExposureSource
|
||||
import com.gh.gamecenter.common.exposure.meta.MetaUtil
|
||||
import com.gh.gamecenter.common.retrofit.BiResponse
|
||||
import com.gh.gamecenter.common.utils.*
|
||||
import com.gh.gamecenter.core.AppExecutor
|
||||
@ -178,15 +178,6 @@ object AdDelegateHelper {
|
||||
when (config.location) {
|
||||
"halo_launch" -> {
|
||||
config.ownerAd?.startAd?.let { it.id = config.ownerAd.id }
|
||||
|
||||
// HarmonyOS 2.2.0 版本不展示第三方开屏广告 (因为会引起奇怪的闪退)
|
||||
if (MetaUtil.getRom().name == "HarmonyOS"
|
||||
&& MetaUtil.getRom().versionName == "2.2.0"
|
||||
&& config.displayRule.adSource == "third_party_ads") {
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
mSplashAd = config
|
||||
}
|
||||
|
||||
|
||||
@ -19,10 +19,10 @@ import java.net.URLConnection
|
||||
|
||||
object AdPluginDownloadHelper : InnerDownloadListener {
|
||||
|
||||
private const val CSJ_FILE_NAME = "1832823466"
|
||||
private const val CSJ_FILE_NAME = "2011394667"
|
||||
private const val GDT_FILE_NAME = "gdt_plugin/gdtadv2.jar"
|
||||
|
||||
private const val CSJ_PLUGIN_URL = "https://and-static.ghzs66.com/android/static/1832823466"
|
||||
private const val CSJ_PLUGIN_URL = "https://and-static.ghzs66.com/android/static/2011394667"
|
||||
private const val GDT_PLUGIN_URL = "https://and-static.ghzs66.com/android/static/gdtadv2.jar"
|
||||
|
||||
private var csjDownloadedCallback: (() -> Unit)? = null
|
||||
|
||||
@ -2,9 +2,9 @@ package com.gh.base
|
||||
|
||||
import android.app.Activity
|
||||
import android.app.Application
|
||||
import android.content.res.Configuration
|
||||
import android.os.Bundle
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import com.therouter.TheRouter
|
||||
import com.gh.ad.AdDelegateHelper
|
||||
import com.gh.common.util.FloatingBackViewManager
|
||||
import com.gh.common.xapk.XapkInstaller
|
||||
@ -15,45 +15,27 @@ import com.gh.gamecenter.SplashAdActivity
|
||||
import com.gh.gamecenter.SplashScreenActivity
|
||||
import com.gh.gamecenter.authorization.AuthorizationActivity
|
||||
import com.gh.gamecenter.common.base.GlobalActivityManager
|
||||
import com.gh.gamecenter.common.constant.RouteConsts
|
||||
import com.gh.gamecenter.common.provider.IHelpAndFeedbackProvider
|
||||
import com.gh.gamecenter.common.utils.PackageFlavorHelper
|
||||
import com.gh.gamecenter.core.provider.IPushProvider
|
||||
import com.gh.gamecenter.login.utils.QuickLoginHelper
|
||||
import com.gh.gamecenter.login.view.LoginActivity
|
||||
import com.gh.gamecenter.va.VCore
|
||||
import com.gh.gamecenter.login.utils.QuickLoginHelper
|
||||
import com.gh.vspace.VHelper
|
||||
import com.halo.assistant.HaloApp
|
||||
import com.therouter.TheRouter
|
||||
|
||||
// TODO:移动到对应的模块
|
||||
class GlobalActivityLifecycleObserver : Application.ActivityLifecycleCallbacks {
|
||||
private var isFromBackgroundToForeground = false // 是否后台回到前台
|
||||
|
||||
override fun onActivityPreCreated(activity: Activity, savedInstanceState: Bundle?) {
|
||||
if (QuickLoginHelper.isLoginAuthPage(activity)) {
|
||||
try {
|
||||
val resources = activity.resources
|
||||
val config = Configuration(resources.configuration)
|
||||
config.fontScale = 1.0f
|
||||
|
||||
// 更新Resources配置
|
||||
val metrics = resources.displayMetrics
|
||||
metrics.scaledDensity = metrics.density
|
||||
resources.updateConfiguration(config, metrics)
|
||||
|
||||
} catch (e: Exception) {
|
||||
// 设置字体失败
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
override fun onActivityStarted(activity: Activity) {
|
||||
GlobalActivityManager.currentActivity = activity
|
||||
GlobalActivityManager.activityCount++
|
||||
GlobalActivityManager.activityCount ++
|
||||
if (GlobalActivityManager.activityCount == 1 && isFromBackgroundToForeground) {
|
||||
if (AdDelegateHelper.shouldShowStartUpAd(true)
|
||||
&& !HaloApp.getInstance().isDisableSplashAdTemporarily
|
||||
@ -129,7 +111,7 @@ class GlobalActivityLifecycleObserver : Application.ActivityLifecycleCallbacks {
|
||||
}
|
||||
|
||||
override fun onActivityStopped(activity: Activity) {
|
||||
GlobalActivityManager.activityCount--
|
||||
GlobalActivityManager.activityCount --
|
||||
isFromBackgroundToForeground = GlobalActivityManager.activityCount <= 0
|
||||
}
|
||||
|
||||
|
||||
@ -11,6 +11,7 @@ import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
import androidx.fragment.app.FragmentManager
|
||||
import com.therouter.TheRouter
|
||||
import com.gh.common.exposure.ExposureManager
|
||||
import com.gh.common.util.*
|
||||
import com.gh.common.util.LogUtils
|
||||
@ -35,6 +36,7 @@ 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
|
||||
@ -57,14 +59,13 @@ 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.accelerator.repository.AccelerationRepository.Companion.PAYMENT_TYPE_ALIPAY
|
||||
import com.halo.assistant.accelerator.repository.AccelerationRepository.Companion.PAYMENT_TYPE_WECHAT
|
||||
import com.halo.assistant.accelerator.repository.AcceleratorDataHolder
|
||||
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.*
|
||||
import com.lightgame.utils.Utils
|
||||
import com.therouter.TheRouter
|
||||
import org.greenrobot.eventbus.EventBus
|
||||
import org.greenrobot.eventbus.Subscribe
|
||||
import org.greenrobot.eventbus.ThreadMode
|
||||
@ -742,7 +743,13 @@ class DefaultJsApi(
|
||||
|
||||
@JavascriptInterface
|
||||
fun getCurAcctGameId(): String {
|
||||
return AcceleratorDataHolder.instance.getAcceleratingGameId()
|
||||
val isSpeeding = TheRouter.get(IAcceleratorProvider::class.java)?.isCurAccSuccess() ?: false
|
||||
val gameId = if (isSpeeding) {
|
||||
MemberRepository.instance.acctGameRecord.gameId
|
||||
} else {
|
||||
""
|
||||
}
|
||||
return gameId
|
||||
}
|
||||
|
||||
@JavascriptInterface
|
||||
|
||||
@ -201,8 +201,7 @@ public class BindingAdapters {
|
||||
gameEntity,
|
||||
traceEvent,
|
||||
entrance,
|
||||
location + ":" + gameEntity.getName(),
|
||||
null);
|
||||
location + ":" + gameEntity.getName());
|
||||
return null;
|
||||
});
|
||||
final DownloadChainHandler chainHandler = builder.buildHandlerChain();
|
||||
@ -247,8 +246,7 @@ public class BindingAdapters {
|
||||
gameEntity,
|
||||
traceEvent,
|
||||
entrance,
|
||||
location + ":" + gameEntity.getName(),
|
||||
null);
|
||||
location + ":" + gameEntity.getName());
|
||||
}
|
||||
break;
|
||||
case INSTALL_PLUGIN:
|
||||
|
||||
@ -7,20 +7,19 @@ import androidx.room.TypeConverters
|
||||
import androidx.room.migration.Migration
|
||||
import androidx.sqlite.db.SupportSQLiteDatabase
|
||||
import com.gh.gamecenter.entity.GamesCollectionEntity
|
||||
import com.gh.gamecenter.entity.HistoryGameDetailEntity
|
||||
import com.gh.gamecenter.entity.HistoryGameEntity
|
||||
import com.gh.gamecenter.entity.MyVideoEntity
|
||||
import com.gh.gamecenter.feature.entity.NewsEntity
|
||||
import com.gh.gamecenter.feature.entity.AnswerEntity
|
||||
import com.gh.gamecenter.feature.entity.ArticleEntity
|
||||
import com.gh.gamecenter.feature.entity.NewsEntity
|
||||
import com.gh.gamecenter.feature.room.converter.*
|
||||
import com.gh.gamecenter.room.converter.*
|
||||
import com.gh.gamecenter.room.dao.*
|
||||
import com.halo.assistant.HaloApp
|
||||
|
||||
@Database(
|
||||
entities = [AnswerEntity::class, ArticleEntity::class, NewsEntity::class, HistoryGameEntity::class, MyVideoEntity::class, GamesCollectionEntity::class, HistoryGameDetailEntity::class],
|
||||
version = 15,
|
||||
entities = [AnswerEntity::class, ArticleEntity::class, NewsEntity::class, HistoryGameEntity::class, MyVideoEntity::class, GamesCollectionEntity::class],
|
||||
version = 14,
|
||||
exportSchema = false
|
||||
)
|
||||
@TypeConverters(
|
||||
@ -54,7 +53,6 @@ abstract class HistoryDatabase : RoomDatabase() {
|
||||
abstract fun gameDao(): GameDao
|
||||
abstract fun videoHistoryDao(): VideoHistoryDao
|
||||
abstract fun gamesCollectionDao(): GamesCollectionDao
|
||||
abstract fun gameDetailDao(): GameDetailHistoryDao
|
||||
|
||||
companion object {
|
||||
|
||||
@ -154,12 +152,6 @@ abstract class HistoryDatabase : RoomDatabase() {
|
||||
}
|
||||
}
|
||||
|
||||
val MIGRATION_14_15: Migration = object : Migration(14, 15) {
|
||||
override fun migrate(database: SupportSQLiteDatabase) {
|
||||
database.execSQL("CREATE TABLE HistoryGameDetailEntity (id TEXT NOT NULL PRIMARY KEY, name TEXT DEFAULT '')")
|
||||
}
|
||||
}
|
||||
|
||||
val instance by lazy {
|
||||
Room.databaseBuilder(
|
||||
HaloApp.getInstance().application,
|
||||
@ -178,7 +170,6 @@ abstract class HistoryDatabase : RoomDatabase() {
|
||||
.addMigrations(MIGRATION_11_12)
|
||||
.addMigrations(MIGRATION_12_13)
|
||||
.addMigrations(MIGRATION_13_14)
|
||||
.addMigrations(MIGRATION_14_15)
|
||||
.build()
|
||||
}
|
||||
}
|
||||
|
||||
@ -44,20 +44,6 @@ object HistoryHelper {
|
||||
runOnIoThread { tryCatchInRelease { HistoryDatabase.instance.gameDao().addGame(historyGameEntity) } }
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun insertGameDetail(gameEntity: GameEntity) {
|
||||
val historyGameDetailEntity = HistoryGameDetailEntity(gameEntity.id, gameEntity.name)
|
||||
runOnIoThread { tryCatchInRelease { HistoryDatabase.instance.gameDetailDao().addGame(historyGameDetailEntity) } }
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun getHistoryGameDetailById(id: String): HistoryGameDetailEntity? =
|
||||
try {
|
||||
HistoryDatabase.instance.gameDetailDao().getHistoryGameDetailById(id)
|
||||
} catch (e: Throwable) {
|
||||
null
|
||||
}
|
||||
|
||||
private fun convertGameUpdateEntityToHistoryGameEntity(updateEntity: GameUpdateEntity): HistoryGameEntity {
|
||||
val historyGame = HistoryGameEntity()
|
||||
|
||||
@ -156,15 +142,6 @@ object HistoryHelper {
|
||||
}
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun deleteGameDetailEntity(gameId: String) {
|
||||
runOnIoThread {
|
||||
tryCatchInRelease {
|
||||
HistoryDatabase.instance.gameDetailDao().deleteGame(HistoryGameDetailEntity(id = gameId))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@JvmStatic
|
||||
fun emptyDatabase() {
|
||||
|
||||
@ -1,18 +0,0 @@
|
||||
package com.gh.common.provider
|
||||
|
||||
import com.gh.gamecenter.core.provider.IAcceleratorDataHolderProvider
|
||||
import com.gh.gamecenter.feature.entity.VipEntity
|
||||
import com.halo.assistant.accelerator.repository.AcceleratorDataHolder
|
||||
|
||||
@com.therouter.inject.ServiceProvider
|
||||
class IAcceleratorDataHolderProviderImpl : IAcceleratorDataHolderProvider {
|
||||
override fun setVipEntity(vip: Any) {
|
||||
if (vip is VipEntity) {
|
||||
AcceleratorDataHolder.instance.setVipEntity(vip)
|
||||
}
|
||||
}
|
||||
|
||||
override fun clear() {
|
||||
AcceleratorDataHolder.instance.clear()
|
||||
}
|
||||
}
|
||||
@ -7,6 +7,9 @@ import com.gh.gamecenter.feature.provider.IRegionSettingHelperProvider
|
||||
|
||||
@com.therouter.inject.ServiceProvider
|
||||
class RegionSettingHelperProviderImpl : IRegionSettingHelperProvider {
|
||||
override fun shouldThisGameDisplayMirrorInfo(gameId: String): Boolean {
|
||||
return RegionSettingHelper.shouldThisGameDisplayMirrorInfo(gameId)
|
||||
}
|
||||
|
||||
override fun getMirrorPosition(gameId: String): Int {
|
||||
return RegionSettingHelper.getMirrorPosition(gameId)
|
||||
|
||||
@ -3,18 +3,21 @@ 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.halo.assistant.accelerator.repository.AccelerationRepository
|
||||
import com.halo.assistant.accelerator.repository.AcceleratorDataHolder
|
||||
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 = AccelerationRepository.newInstance()
|
||||
private val repository = MemberRepository.instance
|
||||
|
||||
@SuppressLint("CheckResult")
|
||||
override fun onPayComplete(nonceStr: String, order: Any?) {
|
||||
@ -26,28 +29,32 @@ class WechatPayResultProviderImpl : IWechatPayResultProvider {
|
||||
EventBus.getDefault().post(EBPayState.PaySuccess)
|
||||
|
||||
// 先刷新本地状态,支付成功,肯定是付费会员
|
||||
AcceleratorDataHolder.instance.setVipEntity(
|
||||
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(
|
||||
AccelerationRepository.PAYMENT_TYPE_WECHAT,
|
||||
MemberRepository.PAYMENT_TYPE_WECHAT,
|
||||
orderEntity?.setMenuName ?: "",
|
||||
orderEntity?.paymentAmount ?: "",
|
||||
AccelerationRepository.RECHARGE_RESULT_SUCCESS
|
||||
MemberRepository.RECHARGE_RESULT_SUCCESS
|
||||
)
|
||||
}, {
|
||||
// 支付失败
|
||||
EventBus.getDefault().post(EBPayState.PayFail)
|
||||
SensorsBridge.trackMemberRechargeResult(
|
||||
AccelerationRepository.PAYMENT_TYPE_WECHAT,
|
||||
MemberRepository.PAYMENT_TYPE_WECHAT,
|
||||
orderEntity?.setMenuName ?: "",
|
||||
orderEntity?.paymentAmount ?: "",
|
||||
AccelerationRepository.RECHARGE_RESULT_FAILURE
|
||||
MemberRepository.RECHARGE_RESULT_FAILURE
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
@ -13,6 +13,7 @@ import com.therouter.TheRouter;
|
||||
import com.gh.ad.AdDelegateHelper;
|
||||
import com.gh.gamecenter.BuildConfig;
|
||||
import com.gh.gamecenter.common.constant.Constants;
|
||||
import com.gh.gamecenter.common.constant.RouteConsts;
|
||||
import com.gh.gamecenter.common.exposure.meta.MetaUtil;
|
||||
import com.gh.gamecenter.common.retrofit.BiResponse;
|
||||
import com.gh.gamecenter.common.utils.SensorsBridge;
|
||||
@ -149,7 +150,6 @@ public class DataUtils {
|
||||
/**
|
||||
* 获取应用 gid 绑定的实名信息
|
||||
*/
|
||||
// TODO 这个方法启动时会被调用多次,后面考虑优化优化
|
||||
@SuppressLint("CheckResult")
|
||||
public static void getDeviceCertification(String gid) {
|
||||
RetrofitManager.getInstance()
|
||||
|
||||
@ -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;
|
||||
@ -53,6 +55,9 @@ public class DetailDownloadUtils {
|
||||
if (viewHolder.getMultiVersionDownloadTv() != null) {
|
||||
viewHolder.getMultiVersionDownloadTv().setVisibility(View.GONE);
|
||||
}
|
||||
if (viewHolder.getSpeedContainer() != null) {
|
||||
viewHolder.getSpeedContainer().setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
viewHolder.setSpeedViewsVisible(false);
|
||||
|
||||
@ -138,12 +143,6 @@ public class DetailDownloadUtils {
|
||||
showDualDownloadButton,
|
||||
downloadEntity
|
||||
);
|
||||
|
||||
if(!showVGame){
|
||||
String rawBtnText = GameUtils.getDownloadBtnText(viewHolder.getContext(), gameEntity, false, showVGame, PluginLocation.only_game);
|
||||
viewHolder.checkIfShowSpeedUi(rawBtnText);
|
||||
}
|
||||
|
||||
} else {
|
||||
// 游戏包含多 APK 的情况
|
||||
viewHolder.getMultiVersionDownloadTv().setText("选择下载你的版本" + (TextUtils.isEmpty(downloadAddWord) ? "" : "-" + downloadAddWord));
|
||||
@ -255,22 +254,30 @@ 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);
|
||||
String size = viewHolder.getGameEntity().getApk().isEmpty() ? "" : viewHolder.getGameEntity().getApk().get(0).getSize();
|
||||
if (size != null) {
|
||||
String sizeWithoutDigit = convertSizeString(size);
|
||||
String sizeWithoutDigit = size.replaceAll("(?<=\\d)\\.[0-9]+(?!\\d)", "");
|
||||
viewHolder.getLocalDownloadSizeTv().setText(sizeWithoutDigit);
|
||||
}
|
||||
|
||||
@ -610,30 +617,6 @@ public class DetailDownloadUtils {
|
||||
return (int) Math.ceil(downloadEntity.getPercent());
|
||||
}
|
||||
|
||||
private static String convertSizeString(String sizeString) {
|
||||
String numberPart;
|
||||
String indicator;
|
||||
|
||||
// Check if the string ends with "MB"
|
||||
if (sizeString.endsWith("MB")) {
|
||||
numberPart = sizeString.substring(0, sizeString.length() - 2);
|
||||
indicator = "MB";
|
||||
} else if (sizeString.endsWith("G")) {
|
||||
numberPart = sizeString.substring(0, sizeString.length() - 1);
|
||||
indicator = "G";
|
||||
} else {
|
||||
return sizeString;
|
||||
}
|
||||
|
||||
// Round number
|
||||
double number = Double.parseDouble(numberPart);
|
||||
long roundedNumber = Math.round(number);
|
||||
|
||||
// Combine rounded number and size indicator
|
||||
return roundedNumber + indicator;
|
||||
}
|
||||
|
||||
|
||||
private static boolean handleDownloadButtonAsXapk(DownloadEntity downloadEntity, DownloadButton downloadButton) {
|
||||
String xapkStatus = downloadEntity.getMeta().get(XapkInstaller.XAPK_UNZIP_STATUS);
|
||||
|
||||
|
||||
@ -18,7 +18,6 @@ import com.gh.common.exposure.ExposureTraceUtils.appendTrace
|
||||
import com.gh.common.util.EntranceUtils.jumpActivity
|
||||
import com.gh.common.util.EntranceUtils.jumpActivityCompat
|
||||
import com.gh.gamecenter.*
|
||||
import com.gh.gamecenter.ShellActivity.Type
|
||||
import com.gh.gamecenter.amway.AmwayActivity
|
||||
import com.gh.gamecenter.category2.CategoryV2Activity
|
||||
import com.gh.gamecenter.common.base.activity.BaseActivity
|
||||
@ -56,7 +55,6 @@ import com.gh.gamecenter.gamecollection.detail.GameCollectionDetailActivity
|
||||
import com.gh.gamecenter.gamecollection.hotlist.GameCollectionHotListActivity
|
||||
import com.gh.gamecenter.gamecollection.hotlist.GameCollectionListDetailActivity
|
||||
import com.gh.gamecenter.gamecollection.square.GameCollectionSquareActivity
|
||||
import com.gh.gamecenter.gamedetail.entity.GameDetailTabEntity
|
||||
import com.gh.gamecenter.gamedetail.fuli.kaifu.ServersCalendarActivity
|
||||
import com.gh.gamecenter.gamedetail.fuli.kaifu.ServersSubscribedGameListActivity
|
||||
import com.gh.gamecenter.gamedetail.history.HistoryApkListActivity
|
||||
@ -195,8 +193,6 @@ object DirectUtils {
|
||||
"simulator",
|
||||
"teen_mode",
|
||||
"message_center",
|
||||
"archive",
|
||||
"my_assets",
|
||||
)
|
||||
|
||||
fun directToLinkPage(
|
||||
@ -617,10 +613,6 @@ object DirectUtils {
|
||||
|
||||
"message_center" -> directToMessageCenter(0, entrance)
|
||||
|
||||
"archive" -> directToCloudArchive(context, linkEntity.link ?: "", linkEntity.text ?: "", "", entrance)
|
||||
|
||||
"my_assets" -> navigateToMyAssetsPage(context, entrance)
|
||||
|
||||
"" -> {
|
||||
// do nothing
|
||||
}
|
||||
@ -857,37 +849,30 @@ object DirectUtils {
|
||||
traceEvent: ExposureEvent? = null
|
||||
) {
|
||||
if (id.isEmpty()) return
|
||||
|
||||
val uri = Uri.Builder()
|
||||
.path(RouteConsts.activity.gameDetailActivity)
|
||||
.appendQueryParameter(KEY_ENTRANCE, entrance)
|
||||
.appendQueryParameter(KEY_GAME_ID, id)
|
||||
.build()
|
||||
|
||||
TheRouter
|
||||
.build(uri.toString())
|
||||
.fillParams { bundle ->
|
||||
if (!TextUtils.isEmpty(tab)) {
|
||||
when (tab) {
|
||||
"comment" -> bundle.putString(KEY_TARGET, GameDetailTabEntity.TYPE_COMMENT)
|
||||
"desc" -> bundle.putString(KEY_TARGET, GameDetailTabEntity.TYPE_DETAIL)
|
||||
"forum" -> bundle.putString(KEY_TARGET, GameDetailTabEntity.TYPE_BBS)
|
||||
"zone" -> bundle.putString(KEY_TARGET, GameDetailTabEntity.TYPE_ZONE)
|
||||
}
|
||||
}
|
||||
if (traceEvent != null) {
|
||||
val clickEvent = createEvent(
|
||||
GameEntity(id = id, name = name),
|
||||
traceEvent.source,
|
||||
appendTrace(traceEvent),
|
||||
ExposureType.CLICK
|
||||
)
|
||||
log(clickEvent)
|
||||
bundle.putParcelable(KEY_TRACE_EVENT, clickEvent)
|
||||
}
|
||||
bundle.putBoolean(KEY_AUTO_DOWNLOAD, autoDownload ?: false)
|
||||
val bundle = Bundle()
|
||||
bundle.putString(KEY_ENTRANCE, entrance ?: ENTRANCE_BROWSER)
|
||||
bundle.putString(KEY_TO, GameDetailActivity::class.java.simpleName)
|
||||
bundle.putString(KEY_GAMEID, id)
|
||||
if (!TextUtils.isEmpty(tab)) {
|
||||
when (tab) {
|
||||
"comment" -> bundle.putString(KEY_TARGET, EntranceConsts.TAB_TYPE_RATING)
|
||||
"desc" -> bundle.putString(KEY_TARGET, EntranceConsts.TAB_TYPE_DESC)
|
||||
"forum" -> bundle.putString(KEY_TARGET, EntranceConsts.TAB_TYPE_BBS)
|
||||
"zone" -> bundle.putString(KEY_TARGET, EntranceConsts.TAB_TYPE_TRENDS)
|
||||
}
|
||||
.navigation(context)
|
||||
}
|
||||
if (traceEvent != null) {
|
||||
val clickEvent = createEvent(
|
||||
GameEntity(id = id, name = name),
|
||||
traceEvent.source,
|
||||
appendTrace(traceEvent),
|
||||
ExposureType.CLICK
|
||||
)
|
||||
log(clickEvent)
|
||||
bundle.putParcelable(KEY_TRACE_EVENT, clickEvent)
|
||||
}
|
||||
bundle.putBoolean(KEY_AUTO_DOWNLOAD, autoDownload ?: false)
|
||||
jumpActivity(context, bundle)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -918,7 +903,7 @@ object DirectUtils {
|
||||
bundle.putString(KEY_ENTRANCE, entrance)
|
||||
bundle.putString(KEY_GAMEID, id)
|
||||
bundle.putBoolean(KEY_OPEN_VIDEO_STREAMING, true)
|
||||
bundle.putString(KEY_TARGET, GameDetailTabEntity.TYPE_DETAIL)
|
||||
bundle.putString(KEY_TARGET, EntranceConsts.TAB_TYPE_DESC)
|
||||
jumpActivity(context, bundle)
|
||||
}
|
||||
|
||||
@ -926,21 +911,15 @@ object DirectUtils {
|
||||
fun directToGameDetail(
|
||||
context: Context,
|
||||
id: String,
|
||||
defaultTab: String = GameDetailTabEntity.TYPE_DETAIL,
|
||||
defaultTab: String = EntranceConsts.TAB_TYPE_DESC,
|
||||
entrance: String? = null
|
||||
) {
|
||||
val uri = Uri.Builder()
|
||||
.path(RouteConsts.activity.gameDetailActivity)
|
||||
.appendQueryParameter(KEY_ENTRANCE, entrance)
|
||||
.appendQueryParameter(KEY_GAME_ID, id)
|
||||
.build()
|
||||
|
||||
TheRouter
|
||||
.build(uri.toString())
|
||||
.fillParams { bundle ->
|
||||
bundle.putString(KEY_TARGET, defaultTab)
|
||||
}
|
||||
.navigation(context)
|
||||
val bundle = Bundle()
|
||||
bundle.putString(KEY_TO, GameDetailActivity::class.java.name)
|
||||
bundle.putString(KEY_ENTRANCE, entrance)
|
||||
bundle.putString(KEY_GAMEID, id)
|
||||
bundle.putString(KEY_TARGET, defaultTab)
|
||||
jumpActivity(context, bundle)
|
||||
}
|
||||
|
||||
// 专栏
|
||||
@ -1590,7 +1569,7 @@ object DirectUtils {
|
||||
response?.apply {
|
||||
if (zone.status == "on") {
|
||||
if (zone.style == "link") {
|
||||
directToGameDetail(context, gameId, GameDetailTabEntity.TYPE_ZONE, entrance)
|
||||
directToGameDetail(context, gameId, EntranceConsts.TAB_TYPE_TRENDS, entrance)
|
||||
} else {
|
||||
directToWebView(context, url, entrance)
|
||||
}
|
||||
@ -1703,7 +1682,7 @@ object DirectUtils {
|
||||
fun directToHelpAndFeedback(context: Context, bundle: Bundle? = null) {
|
||||
TheRouter.build(RouteConsts.activity.helpAndFeedbackActivity)
|
||||
.fillParams {
|
||||
bundle?.run { it.putAll(this) }
|
||||
it.putAll(bundle)
|
||||
}
|
||||
.navigation(context)
|
||||
}
|
||||
@ -2315,32 +2294,4 @@ object DirectUtils {
|
||||
.withBoolean(KEY_DISPLAY_TYPE, isLogoutStyle)
|
||||
.navigation()
|
||||
}
|
||||
|
||||
// 跳转云存档详情页
|
||||
@JvmStatic
|
||||
fun directToCloudArchive(
|
||||
context: Context,
|
||||
gameId: String,
|
||||
gameName: String,
|
||||
configUrl: String = "",
|
||||
entrance: String = ""
|
||||
) {
|
||||
val bundle = Bundle()
|
||||
val gameEntity = GameEntity(id = gameId, name = gameName)
|
||||
bundle.putParcelable(KEY_GAME_ENTITY, gameEntity)
|
||||
bundle.putString(KEY_ARCHIVE_CONFIG_URL, configUrl)
|
||||
bundle.putString(KEY_ENTRANCE, entrance)
|
||||
bundle.putBoolean(KEY_USE_ALTERNATIVE_LAYOUT, true)
|
||||
context.startActivity(ShellActivity.getIntent(context, Type.CLOUD_ARCHIVE, bundle))
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun navigateToMyAssetsPage(context: Context, entrance: String?) {
|
||||
if (CheckLoginUtils.isLogin()) {
|
||||
TheRouter.build(RouteConsts.activity.myAssetsActivity).navigation(context)
|
||||
} else {
|
||||
CheckLoginUtils.checkLogin(context, entrance, null)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@ -176,8 +176,7 @@ object DownloadItemUtils {
|
||||
pluginLocation: PluginLocation? = PluginLocation.only_game,
|
||||
hideDownloadBtnIfNoAvailableContent: Boolean = false,
|
||||
briefStyle: String? = null,
|
||||
isShowRecommendStar: Boolean = false,
|
||||
listener: DownloadButton.OnUpdateListener? = null
|
||||
isShowRecommendStar: Boolean = false
|
||||
) {
|
||||
holder.gameDownloadBtn.putObject(gameEntity)
|
||||
|
||||
@ -190,8 +189,7 @@ object DownloadItemUtils {
|
||||
holder.gameDownloadBtn,
|
||||
gameEntity,
|
||||
hideDownloadBtnIfNoAvailableContent,
|
||||
pluginLocation,
|
||||
listener
|
||||
pluginLocation
|
||||
)
|
||||
return
|
||||
}
|
||||
@ -212,8 +210,7 @@ object DownloadItemUtils {
|
||||
holder.gameDownloadBtn,
|
||||
gameEntity,
|
||||
hideDownloadBtnIfNoAvailableContent,
|
||||
pluginLocation,
|
||||
listener
|
||||
pluginLocation
|
||||
)
|
||||
}
|
||||
|
||||
@ -222,8 +219,7 @@ object DownloadItemUtils {
|
||||
downloadBtn: DownloadButton,
|
||||
gameEntity: GameEntity,
|
||||
hideDownloadBtnIfNoAvailableContent: Boolean = false,
|
||||
pluginLocation: PluginLocation? = PluginLocation.only_game,
|
||||
listener: DownloadButton.OnUpdateListener?
|
||||
pluginLocation: PluginLocation? = PluginLocation.only_game
|
||||
) {
|
||||
// 控制是否显示下载按钮
|
||||
downloadBtn.goneIf(context.getString(R.string.app_name) == gameEntity.name)
|
||||
@ -231,7 +227,6 @@ object DownloadItemUtils {
|
||||
if (SPUtils.getBoolean(Constants.SP_TEENAGER_MODE) || gameEntity.isSpecialDownload()) {
|
||||
downloadBtn.text = "查看"
|
||||
downloadBtn.buttonStyle = DownloadButton.ButtonStyle.TEENAGER_MODE
|
||||
listener?.completion(downloadBtn.text)
|
||||
return
|
||||
}
|
||||
if (gameEntity.isReservable) {
|
||||
@ -244,7 +239,6 @@ object DownloadItemUtils {
|
||||
buttonStyle = DownloadButton.ButtonStyle.RESERVED
|
||||
}
|
||||
}
|
||||
listener?.completion(downloadBtn.text)
|
||||
return
|
||||
}
|
||||
if (RegionSettingHelper.getGameH5DownloadByGameId(gameEntity.id) != null) {
|
||||
@ -254,7 +248,6 @@ object DownloadItemUtils {
|
||||
setBackgroundResource(com.gh.gamecenter.common.R.drawable.download_button_normal_style)
|
||||
setTextColor(com.gh.gamecenter.common.R.color.white.toColor(context))
|
||||
}
|
||||
listener?.completion(downloadBtn.text)
|
||||
return
|
||||
}
|
||||
if (gameEntity.isMiniGame()) {
|
||||
@ -272,7 +265,6 @@ object DownloadItemUtils {
|
||||
text = context.getString(com.gh.gamecenter.feature.R.string.quick_play)
|
||||
}
|
||||
}
|
||||
listener?.completion(downloadBtn.text)
|
||||
return
|
||||
}
|
||||
if (gameEntity.getApk().isEmpty() || gameEntity.downloadOffStatus != null) {
|
||||
@ -304,7 +296,6 @@ object DownloadItemUtils {
|
||||
downloadBtn.isClickable = false
|
||||
}
|
||||
}
|
||||
listener?.completion(downloadBtn.text)
|
||||
} else if (gameEntity.getApk().size == 1) {
|
||||
// 来自于下载管理的实体快照
|
||||
val entityFromDownloadManager = DownloadManager.getInstance().getDownloadEntitySnapshot(gameEntity)
|
||||
@ -363,60 +354,43 @@ object DownloadItemUtils {
|
||||
downloadBtn.apply {
|
||||
when (downloadEntity.status) {
|
||||
DownloadStatus.done -> {
|
||||
val xapkStatus = downloadEntity.meta[XapkInstaller.XAPK_UNZIP_STATUS]
|
||||
when {
|
||||
downloadEntity.isSimulatorGame() && gameEntity.simulator != null -> {
|
||||
GameUtils.setDownloadBtnStatus(
|
||||
context,
|
||||
gameEntity,
|
||||
downloadBtn,
|
||||
pluginLocation,
|
||||
listener
|
||||
)
|
||||
}
|
||||
|
||||
isVGamePreferred -> {
|
||||
buttonStyle =
|
||||
if (PackagesManager.isCanUpdate(
|
||||
downloadEntity.gameId,
|
||||
downloadEntity.packageName,
|
||||
asVGame = true
|
||||
)
|
||||
) {
|
||||
setText(com.gh.gamecenter.feature.R.string.update)
|
||||
DownloadButton.ButtonStyle.NORMAL
|
||||
} else {
|
||||
setText(com.gh.gamecenter.feature.R.string.launch)
|
||||
DownloadButton.ButtonStyle.LAUNCH_OR_OPEN
|
||||
}
|
||||
listener?.completion(downloadBtn.text)
|
||||
}
|
||||
|
||||
XapkUnzipStatus.SUCCESS.name == xapkStatus && isInstalling(downloadEntity.path) -> {
|
||||
if (downloadEntity.isSimulatorGame() && gameEntity.simulator != null) {
|
||||
GameUtils.setDownloadBtnStatus(context, gameEntity, downloadBtn, pluginLocation)
|
||||
} else if (isVGamePreferred) {
|
||||
buttonStyle =
|
||||
if (PackagesManager.isCanUpdate(
|
||||
downloadEntity.gameId,
|
||||
downloadEntity.packageName,
|
||||
asVGame = true
|
||||
)
|
||||
) {
|
||||
setText(com.gh.gamecenter.feature.R.string.update)
|
||||
DownloadButton.ButtonStyle.NORMAL
|
||||
} else {
|
||||
setText(com.gh.gamecenter.feature.R.string.launch)
|
||||
DownloadButton.ButtonStyle.LAUNCH_OR_OPEN
|
||||
}
|
||||
} else {
|
||||
val xapkStatus = downloadEntity.meta[XapkInstaller.XAPK_UNZIP_STATUS]
|
||||
if (XapkUnzipStatus.SUCCESS.name == xapkStatus && isInstalling(downloadEntity.path)) {
|
||||
progress = 100
|
||||
setText(com.gh.gamecenter.feature.R.string.installing)
|
||||
buttonStyle = DownloadButton.ButtonStyle.INSTALL_NORMAL
|
||||
listener?.completion(downloadBtn.text)
|
||||
return
|
||||
}
|
||||
|
||||
XapkUnzipStatus.UNZIPPING.name == xapkStatus -> {
|
||||
if (XapkUnzipStatus.UNZIPPING.name == xapkStatus) {
|
||||
val percent = downloadEntity.meta[XapkInstaller.XAPK_UNZIP_PERCENT]
|
||||
progress = (java.lang.Float.valueOf(percent) * 10).toInt()
|
||||
text = "$percent%"
|
||||
buttonStyle = DownloadButton.ButtonStyle.XAPK_UNZIPPING
|
||||
listener?.completion(downloadBtn.text)
|
||||
return
|
||||
}
|
||||
|
||||
XapkUnzipStatus.FAILURE.name == xapkStatus -> {
|
||||
} else if (XapkUnzipStatus.FAILURE.name == xapkStatus) {
|
||||
setText(com.gh.gamecenter.feature.R.string.install)
|
||||
buttonStyle = DownloadButton.ButtonStyle.INSTALL_NORMAL
|
||||
listener?.completion(downloadBtn.text)
|
||||
return
|
||||
}
|
||||
|
||||
PackagesManager.isInstalled(downloadEntity.packageName) && !downloadEntity.isUpdate -> {
|
||||
if (PackagesManager.isInstalled(downloadEntity.packageName) && !downloadEntity.isUpdate) {
|
||||
// 双下载按钮快速安装时存在已下载的安装包过时,需要重新下载的情况
|
||||
if (PackagesManager.isCanUpdate(
|
||||
downloadEntity.gameId,
|
||||
@ -429,13 +403,9 @@ object DownloadItemUtils {
|
||||
buttonStyle = DownloadButton.ButtonStyle.LAUNCH_OR_OPEN
|
||||
setText(com.gh.gamecenter.feature.R.string.launch)
|
||||
}
|
||||
listener?.completion(downloadBtn.text)
|
||||
}
|
||||
|
||||
else -> {
|
||||
} else {
|
||||
buttonStyle = DownloadButton.ButtonStyle.INSTALL_NORMAL
|
||||
setText(com.gh.gamecenter.feature.R.string.install)
|
||||
listener?.completion(downloadBtn.text)
|
||||
}
|
||||
}
|
||||
buttonStyle =
|
||||
@ -455,24 +425,22 @@ object DownloadItemUtils {
|
||||
DownloadStatus.overflow -> {
|
||||
buttonStyle = DownloadButton.ButtonStyle.NORMAL
|
||||
setText(com.gh.gamecenter.feature.R.string.resume)
|
||||
listener?.completion(downloadBtn.text)
|
||||
}
|
||||
|
||||
DownloadStatus.cancel -> {
|
||||
GameUtils.setDownloadBtnStatus(context, gameEntity, downloadBtn, pluginLocation, listener)
|
||||
GameUtils.setDownloadBtnStatus(context, gameEntity, downloadBtn, pluginLocation)
|
||||
}
|
||||
|
||||
else -> {
|
||||
// do nothing
|
||||
listener?.completion(downloadBtn.text)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
GameUtils.setDownloadBtnStatus(context, gameEntity, downloadBtn, pluginLocation, listener)
|
||||
GameUtils.setDownloadBtnStatus(context, gameEntity, downloadBtn, pluginLocation)
|
||||
}
|
||||
} else {
|
||||
GameUtils.setDownloadBtnStatus(context, gameEntity, downloadBtn, pluginLocation, listener)
|
||||
GameUtils.setDownloadBtnStatus(context, gameEntity, downloadBtn, pluginLocation)
|
||||
}
|
||||
}
|
||||
|
||||
@ -542,18 +510,13 @@ object DownloadItemUtils {
|
||||
DownloadStatus.downloading -> {
|
||||
if (isMultiVersion) {
|
||||
holder.gameDownloadBtn.buttonStyle = DownloadButton.ButtonStyle.NORMAL
|
||||
val darkMode =
|
||||
(holder.gameDownloadTips?.getTag(com.gh.gamecenter.common.R.string.is_dark_mode_on_id) as? Boolean)
|
||||
?: false
|
||||
val darkMode = (holder.gameDownloadTips?.getTag(com.gh.gamecenter.common.R.string.is_dark_mode_on_id) as? Boolean) ?: false
|
||||
val isDarkModeChanged = DarkModeUtils.isDarkModeOn(context) != darkMode
|
||||
if (holder.gameDownloadTips?.visibility == View.GONE || holder.gameDownloadTips?.isAnimating == false || isDarkModeChanged) {
|
||||
holder.gameDownloadTips?.visibility = View.VISIBLE
|
||||
holder.gameDownloadTips?.setDownloadTipsAnimation(true)
|
||||
}
|
||||
holder.gameDownloadTips?.setTag(
|
||||
com.gh.gamecenter.common.R.string.is_dark_mode_on_id,
|
||||
DarkModeUtils.isDarkModeOn(context)
|
||||
)
|
||||
holder.gameDownloadTips?.setTag(com.gh.gamecenter.common.R.string.is_dark_mode_on_id, DarkModeUtils.isDarkModeOn(context))
|
||||
} else {
|
||||
holder.gameDownloadTips?.visibility = View.GONE
|
||||
holder.gameDownloadBtn.buttonStyle = DownloadButton.ButtonStyle.DOWNLOADING_NORMAL
|
||||
@ -998,8 +961,7 @@ object DownloadItemUtils {
|
||||
traceEvent: ExposureEvent? = null,
|
||||
refreshCallback: EmptyCallback? = null
|
||||
) {
|
||||
val str =
|
||||
if (downloadBtn is DownloadButton) downloadBtn.text else context.getString(com.gh.gamecenter.feature.R.string.download)
|
||||
val str = if (downloadBtn is DownloadButton) downloadBtn.text else context.getString(com.gh.gamecenter.feature.R.string.download)
|
||||
if (gameEntity.getApk().isEmpty()) return
|
||||
val apk = gameEntity.getApk().safelyGetInRelease(0) ?: return
|
||||
|
||||
@ -1018,16 +980,7 @@ object DownloadItemUtils {
|
||||
addHandler(CheckDownloadHandler())
|
||||
}
|
||||
.setProcessEndCallback(gameEntity.id) { asVGame, isSubscribe ->
|
||||
download(
|
||||
context,
|
||||
gameEntity,
|
||||
downloadBtn,
|
||||
entrance,
|
||||
location,
|
||||
asVGame,
|
||||
isSubscribe as Boolean,
|
||||
traceEvent
|
||||
)
|
||||
download(context, gameEntity, downloadBtn, entrance, location, asVGame, isSubscribe as Boolean, traceEvent)
|
||||
}
|
||||
.buildHandlerChain()
|
||||
?.handleRequest(context, gameEntity, shouldPerformAsVGame)
|
||||
@ -1046,16 +999,7 @@ object DownloadItemUtils {
|
||||
addHandler(CheckDownloadHandler())
|
||||
}
|
||||
.setProcessEndCallback(gameEntity.id) { asVGame, isSubscribe ->
|
||||
download(
|
||||
context,
|
||||
gameEntity,
|
||||
downloadBtn,
|
||||
entrance,
|
||||
location,
|
||||
asVGame,
|
||||
isSubscribe as Boolean,
|
||||
traceEvent
|
||||
)
|
||||
download(context, gameEntity, downloadBtn, entrance, location, asVGame, isSubscribe as Boolean, traceEvent)
|
||||
}
|
||||
.buildHandlerChain()
|
||||
?.handleRequest(context, gameEntity, shouldPerformAsVGame)
|
||||
@ -1074,16 +1018,7 @@ object DownloadItemUtils {
|
||||
addHandler(CheckDownloadHandler())
|
||||
}
|
||||
.setProcessEndCallback(gameEntity.id) { asVGame, isSubscribe ->
|
||||
download(
|
||||
context,
|
||||
gameEntity,
|
||||
downloadBtn,
|
||||
entrance,
|
||||
location,
|
||||
asVGame,
|
||||
isSubscribe as Boolean,
|
||||
traceEvent
|
||||
)
|
||||
download(context, gameEntity, downloadBtn, entrance, location, asVGame, isSubscribe as Boolean, traceEvent)
|
||||
}
|
||||
.buildHandlerChain()
|
||||
?.handleRequest(context, gameEntity, shouldPerformAsVGame)
|
||||
|
||||
@ -25,10 +25,7 @@ object GameUtils {
|
||||
/**
|
||||
* 去除与重复sourceList相同的数据
|
||||
*/
|
||||
fun removeDuplicateData(
|
||||
sourceList: MutableList<GameEntity>?,
|
||||
rawList: MutableList<GameEntity>?
|
||||
): MutableList<GameEntity>? {
|
||||
fun removeDuplicateData(sourceList: MutableList<GameEntity>?, rawList: MutableList<GameEntity>?): MutableList<GameEntity>? {
|
||||
if (sourceList.isNullOrEmpty() || rawList.isNullOrEmpty()) {
|
||||
return rawList
|
||||
}
|
||||
@ -55,8 +52,7 @@ object GameUtils {
|
||||
context: Context,
|
||||
gameEntity: GameEntity,
|
||||
downloadBtn: DownloadButton,
|
||||
pluginLocation: PluginLocation?,
|
||||
listener: DownloadButton.OnUpdateListener? = null
|
||||
pluginLocation: PluginLocation?
|
||||
) {
|
||||
// getDownloadBtnText 里包括查询数据库、根据包名读取包体 meta 信息等
|
||||
lightWeightIoExecutor.execute {
|
||||
@ -77,7 +73,6 @@ object GameUtils {
|
||||
} else {
|
||||
downloadBtn.buttonStyle = DownloadButton.ButtonStyle.NORMAL
|
||||
}
|
||||
listener?.completion(downloadBtn.text)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -90,13 +85,11 @@ object GameUtils {
|
||||
*/
|
||||
@WorkerThread
|
||||
@JvmStatic
|
||||
fun getDownloadBtnText(
|
||||
context: Context,
|
||||
gameEntity: GameEntity,
|
||||
isFromList: Boolean,
|
||||
fixedAsVGame: Boolean,
|
||||
pluginLocation: PluginLocation?
|
||||
): String {
|
||||
fun getDownloadBtnText(context: Context,
|
||||
gameEntity: GameEntity,
|
||||
isFromList: Boolean,
|
||||
fixedAsVGame: Boolean,
|
||||
pluginLocation: PluginLocation?): String {
|
||||
if (gameEntity.getApk().size > 1) {
|
||||
return ""
|
||||
}
|
||||
@ -145,8 +138,7 @@ object GameUtils {
|
||||
} else if (!isFromList) {
|
||||
if (!performAsVGame
|
||||
&& gameEntity.isDualBtnModeEnabled()
|
||||
&& downloadEntity?.isVGameDownloadInDualDownloadMode() == true
|
||||
) {
|
||||
&& downloadEntity?.isVGameDownloadInDualDownloadMode() == true) {
|
||||
// 下载的任务是由畅玩触发的,并且双下载按钮启用,游戏详情页不需判定为需要安装
|
||||
downloadEntity = null
|
||||
} else if (performAsVGame && downloadEntity?.isLocalDownloadInDualDownloadMode() == true) {
|
||||
|
||||
@ -14,26 +14,25 @@ import androidx.core.content.ContextCompat;
|
||||
import com.gh.gamecenter.BuildConfig;
|
||||
import com.gh.gamecenter.R;
|
||||
import com.gh.gamecenter.adapter.LibaoDetailAdapter;
|
||||
import com.gh.gamecenter.common.constant.Constants;
|
||||
import com.gh.gamecenter.common.entity.NotificationUgc;
|
||||
import com.gh.gamecenter.common.eventbus.EBReuse;
|
||||
import com.gh.gamecenter.common.retrofit.JSONObjectResponse;
|
||||
import com.gh.gamecenter.common.retrofit.Response;
|
||||
import com.gh.gamecenter.common.utils.DialogHelper;
|
||||
import com.gh.gamecenter.common.utils.ExtensionsKt;
|
||||
import com.gh.gamecenter.common.utils.NotificationHelper;
|
||||
import com.gh.gamecenter.common.utils.SensorsBridge;
|
||||
import com.gh.gamecenter.core.utils.ToastUtils;
|
||||
import com.gh.gamecenter.core.utils.UrlFilterUtils;
|
||||
import com.gh.gamecenter.eventbus.EBUISwitch;
|
||||
import com.gh.gamecenter.feature.entity.ApkEntity;
|
||||
import com.gh.gamecenter.feature.entity.LibaoEntity;
|
||||
import com.gh.gamecenter.feature.entity.LibaoStatusEntity;
|
||||
import com.gh.gamecenter.feature.entity.MeEntity;
|
||||
import com.gh.gamecenter.common.entity.NotificationUgc;
|
||||
import com.gh.gamecenter.feature.entity.UserDataLibaoEntity;
|
||||
import com.gh.gamecenter.common.eventbus.EBReuse;
|
||||
import com.gh.gamecenter.eventbus.EBUISwitch;
|
||||
import com.gh.gamecenter.feature.utils.PlatformUtils;
|
||||
import com.gh.gamecenter.geetest.GeetestUtils;
|
||||
import com.gh.gamecenter.login.user.UserManager;
|
||||
import com.gh.gamecenter.common.retrofit.JSONObjectResponse;
|
||||
import com.gh.gamecenter.common.retrofit.Response;
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager;
|
||||
import com.halo.assistant.HaloApp;
|
||||
import com.lightgame.utils.Utils;
|
||||
@ -481,7 +480,7 @@ public class LibaoUtils {
|
||||
UserDataLibaoEntity me = new UserDataLibaoEntity(libaoCode, "ling", Utils.getTime(context));
|
||||
initLibaoCode(libaoEntity, me);
|
||||
if (adapter != null) adapter.initLibaoCode(me);
|
||||
EventBus.getDefault().post(new EBReuse(Constants.LIBAO_CHANGED_TAG));
|
||||
EventBus.getDefault().post(new EBReuse("libaoChanged"));
|
||||
if (listener != null) listener.onLibaoStatusChange();
|
||||
uploadEvent(libaoEntity, true, entrance);
|
||||
String des;
|
||||
@ -621,7 +620,7 @@ public class LibaoUtils {
|
||||
UserDataLibaoEntity me = new UserDataLibaoEntity(libaoCode, "ling", Utils.getTime(context));
|
||||
initLibaoCode(libaoEntity, me);
|
||||
if (listener != null) listener.onLibaoStatusChange();
|
||||
EventBus.getDefault().post(new EBReuse(Constants.LIBAO_CHANGED_TAG));
|
||||
EventBus.getDefault().post(new EBReuse("libaoChanged"));
|
||||
uploadEvent(libaoEntity, false, entrance);
|
||||
|
||||
if (adapter != null) {
|
||||
|
||||
@ -12,7 +12,6 @@ import androidx.fragment.app.FragmentActivity
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import com.gh.common.constant.Config
|
||||
import com.gh.download.server.BrowserInstallHelper
|
||||
import com.gh.gamecenter.common.retrofit.BiResponse
|
||||
import com.gh.gamecenter.common.utils.DialogHelper
|
||||
import com.gh.gamecenter.common.utils.PermissionHelper
|
||||
@ -25,6 +24,7 @@ import com.gh.gamecenter.core.utils.SPUtils
|
||||
import com.gh.gamecenter.entity.WhitePackageListEntity
|
||||
import com.gh.gamecenter.feature.entity.GameEntity
|
||||
import com.gh.gamecenter.feature.entity.SettingsEntity
|
||||
import com.gh.gamecenter.feature.utils.SentryHelper
|
||||
import com.gh.gamecenter.manager.PackagesManager
|
||||
import com.gh.gamecenter.packagehelper.PackageRepository
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager
|
||||
@ -459,9 +459,6 @@ object PackageHelper {
|
||||
PackageRepository.initData {
|
||||
refreshLocalPackageList()
|
||||
refreshPackageNameList()
|
||||
|
||||
// 初始化使用浏览器安装的条件
|
||||
BrowserInstallHelper.initIfConditionMatched(Config.getNewSettingsEntity())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -69,24 +69,18 @@ object PackageInstaller {
|
||||
val isDownloadAsVGame = downloadEntity.getMetaExtra(Constants.EXTRA_DOWNLOAD_TYPE) == Constants.VGAME
|
||||
|| downloadEntity.getMetaExtra(Constants.EXTRA_DOWNLOAD_TYPE) == Constants.DUAL_DOWNLOAD_VGAME
|
||||
|
||||
val properContext = if (context is AppCompatActivity && !context.isFinishing) {
|
||||
context
|
||||
} else {
|
||||
AppManager.getInstance().currentActivity()
|
||||
}
|
||||
|
||||
properContext ?: return
|
||||
val currentActivity = AppManager.getInstance().currentActivity() ?: return
|
||||
|
||||
if (!ignoreAsVGame && isDownloadAsVGame) {
|
||||
VHelper.install(properContext, downloadEntity)
|
||||
VHelper.install(currentActivity, downloadEntity)
|
||||
return
|
||||
}
|
||||
|
||||
// 已知问题
|
||||
// 1. 此处可能遇到 activity 是 WXEntryActivity,因为 WXEntryActivity 不是 AppCompatActivity 调不起弹窗
|
||||
// 2. 当 activity 全部出栈,但是应用还在下载游戏,下载完会唤不起安装
|
||||
if (properContext is AppCompatActivity && !properContext.isFinishing) {
|
||||
InstallPermissionDialogFragment.show(properContext, downloadEntity) { isFromPermissionGrantedCallback ->
|
||||
if (currentActivity is AppCompatActivity && !currentActivity.isFinishing) {
|
||||
InstallPermissionDialogFragment.show(currentActivity, downloadEntity) { isFromPermissionGrantedCallback ->
|
||||
// 取消状态栏下载完成的通知,若存在
|
||||
downloadEntity.meta[Constants.MARK_ALREADY_TRIGGERED_INSTALLATION] = "YES"
|
||||
DownloadNotificationHelper.addOrUpdateDownloadNotification(downloadEntity)
|
||||
|
||||
@ -32,7 +32,6 @@ import okhttp3.RequestBody
|
||||
import okhttp3.RequestBody.Companion.toRequestBody
|
||||
import okhttp3.ResponseBody
|
||||
import org.json.JSONArray
|
||||
import org.json.JSONException
|
||||
import org.json.JSONObject
|
||||
import java.util.*
|
||||
|
||||
@ -230,19 +229,15 @@ object UsageStatsHelper {
|
||||
mApi.getUsageStatusUpdateTime(HaloApp.getInstance().gid)
|
||||
.subscribe(object : BiResponse<ResponseBody>() {
|
||||
override fun onSuccess(data: ResponseBody) {
|
||||
try {
|
||||
val body = JSONObject(data.string())
|
||||
val lastPostTime = body.getLong("update_time") * 1000
|
||||
val body = JSONObject(data.string())
|
||||
val lastPostTime = body.getLong("update_time") * 1000
|
||||
|
||||
val beginTime = if (lastPostTime == 0L) {
|
||||
getDefaultBeginTime()
|
||||
} else {
|
||||
lastPostTime
|
||||
}
|
||||
postUsageStats(beginTime)
|
||||
} catch (e: JSONException) {
|
||||
Utils.log("UsageStats: 获取上次上传时间失败,错误信息:${e.message}")
|
||||
val beginTime = if (lastPostTime == 0L) {
|
||||
getDefaultBeginTime()
|
||||
} else {
|
||||
lastPostTime
|
||||
}
|
||||
postUsageStats(beginTime)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@ -19,7 +19,7 @@ import com.gh.gamecenter.game.columncollection.detail.ColumnCollectionDetailFrag
|
||||
import com.gh.gamecenter.game.commoncollection.detail.CustomCommonCollectionDetailFragment
|
||||
import com.gh.gamecenter.gamecollection.hotlist.GameCollectionHotListWrapperFragment
|
||||
import com.gh.gamecenter.gamecollection.square.GameCollectionSquareFragment
|
||||
import com.gh.gamecenter.gamedetail.GameDetailWrapperFragment
|
||||
import com.gh.gamecenter.gamedetail.GameDetailFragment
|
||||
import com.gh.gamecenter.info.InfoWrapperFragment
|
||||
import com.gh.gamecenter.libao.LibaoDetailFragment
|
||||
import com.gh.gamecenter.libao.LibaoFragment
|
||||
@ -88,7 +88,7 @@ object ViewPagerFragmentHelper {
|
||||
// 游戏详情页
|
||||
TYPE_GAME -> {
|
||||
bundle.putString(EntranceConsts.KEY_GAMEID, linkEntity.link)
|
||||
GameDetailWrapperFragment().with(bundle)
|
||||
GameDetailFragment().with(bundle)
|
||||
}
|
||||
// 我的光环
|
||||
TYPE_MY_HALO -> {
|
||||
@ -149,11 +149,11 @@ object ViewPagerFragmentHelper {
|
||||
NewQuestionDetailFragment().with(bundle)
|
||||
}
|
||||
// 其他原来带Toolbar的Fragment
|
||||
else -> createToolbarWrapperFragment(bundle, linkEntity, isTabWrapper)
|
||||
else -> createToolbarWrapperFragment(parentFragment, bundle, linkEntity, isTabWrapper)
|
||||
}
|
||||
}
|
||||
|
||||
private fun createToolbarWrapperFragment(bundle: Bundle, entity: LinkEntity, isTabWrapper: Boolean): Fragment {
|
||||
private fun createToolbarWrapperFragment(parentFragment: Fragment?, bundle: Bundle, entity: LinkEntity, isTabWrapper: Boolean): Fragment {
|
||||
var className = ReloadFragment::class.java.name
|
||||
|
||||
when (entity.type) {
|
||||
|
||||
@ -32,7 +32,6 @@ class FlexLinearLayout @JvmOverloads constructor(context: Context, attrs: Attrib
|
||||
private var mLastItemWidth = 0//最后更多按钮宽度
|
||||
private var mTotalWidth = 0
|
||||
private var mStrokeWidth = 0
|
||||
private var mShowMore = true
|
||||
var onClickListener: OnItemClickListener? = null
|
||||
|
||||
init {
|
||||
@ -45,12 +44,11 @@ class FlexLinearLayout @JvmOverloads constructor(context: Context, attrs: Attrib
|
||||
mTextSize = ta.getDimension(R.styleable.FlexLinearLayout_itemTextSize, 10F.sp2px().toFloat())
|
||||
mLastItemWidth = ta.getDimensionPixelSize(R.styleable.FlexLinearLayout_lastItemWidth, 18F.dip2px())
|
||||
mStrokeWidth = ta.getDimensionPixelSize(R.styleable.FlexLinearLayout_strokeWidth, 0.5F.dip2px())
|
||||
mShowMore = ta.getBoolean(R.styleable.FlexLinearLayout_showMore, true)
|
||||
|
||||
ta.recycle()
|
||||
}
|
||||
|
||||
fun setTags(tags: List<TagStyleEntity>) {
|
||||
fun setTags(tags: ArrayList<TagStyleEntity>) {
|
||||
mTags.clear()
|
||||
mTotalCount = tags.size
|
||||
mTotalWidth = measuredWidth
|
||||
@ -88,7 +86,7 @@ class FlexLinearLayout @JvmOverloads constructor(context: Context, attrs: Attrib
|
||||
mTags.forEachIndexed { index, tag ->
|
||||
addView(createView(tag, index))
|
||||
}
|
||||
if (mShowMore && mTotalCount != mTags.size) {
|
||||
if (mTotalCount != mTags.size) {
|
||||
val imageView = ImageView(context).apply {
|
||||
val params = LayoutParams(mLastItemWidth, mItemHeight)
|
||||
layoutParams = params
|
||||
|
||||
@ -3,15 +3,9 @@ package com.gh.common.xapk
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.os.Environment
|
||||
import android.provider.DocumentsContract
|
||||
import android.provider.Settings
|
||||
import androidx.activity.result.ActivityResultLauncher
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.documentfile.provider.DocumentFile
|
||||
import com.gh.common.constant.Config
|
||||
import com.gh.common.util.DirectUtils
|
||||
import com.gh.common.util.DownloadNotificationHelper
|
||||
@ -30,7 +24,6 @@ import com.gh.gamecenter.xapk.core.XApkUnZipCallback
|
||||
import com.gh.gamecenter.xapk.core.XApkUnZipEntry
|
||||
import com.gh.gamecenter.xapk.core.XApkUnZipOutputFactory
|
||||
import com.gh.gamecenter.xapk.io.NonSplitApksOutput
|
||||
import com.gh.gamecenter.xapk.io.OBBDocOutput
|
||||
import com.gh.gamecenter.xapk.io.OBBFileOutput
|
||||
import com.gh.gamecenter.xapk.io.SplitApksOutput
|
||||
import com.gh.gamecenter.xapk.io.XApkFileOutput
|
||||
@ -41,8 +34,6 @@ import com.lightgame.download.DownloadEntity
|
||||
import com.lightgame.utils.Utils
|
||||
import java.io.File
|
||||
import java.util.*
|
||||
import androidx.core.net.toUri
|
||||
import com.gh.gamecenter.core.utils.SPUtils
|
||||
|
||||
/**
|
||||
* 目前已知的Xapk内容是:只有一个apk包和一个或做多个obb数据包(多余文件不解压,如果存在多个apk包,则以下安装无效)
|
||||
@ -74,10 +65,6 @@ object XapkInstaller : XApkUnZipCallback, XApkUnZipOutputFactory {
|
||||
systemMatched && fileListMatched
|
||||
}
|
||||
|
||||
// 是否使用 DocumentUi 的方式访问 obb 文件夹
|
||||
private var useDocStyleToUnzip = false
|
||||
private var tempLauncher: ActivityResultLauncher<Uri>? = null
|
||||
|
||||
private const val GUIDE_TYPE_MIUI_OPTIMIZATION = "miui_optimization"
|
||||
private const val MIUI_OPTIMIZATION_WARNING_DIALOG_ENTRANCE = "MIUI优化关闭提示弹窗"
|
||||
|
||||
@ -134,39 +121,13 @@ object XapkInstaller : XApkUnZipCallback, XApkUnZipOutputFactory {
|
||||
}
|
||||
|
||||
PermissionHelper.checkManageAllFilesOrStoragePermissionBeforeAction(context) {
|
||||
val unzipAction = {
|
||||
DownloadManager.getInstance().getDownloadEntitySnapshot(downloadEntity.url, downloadEntity.gameId)
|
||||
?.let {
|
||||
unzipXapkFile(it)
|
||||
if (showUnzipToast) {
|
||||
Utils.toast(mContext, "解压过程请勿退出光环助手!")
|
||||
}
|
||||
DownloadManager.getInstance().getDownloadEntitySnapshot(downloadEntity.url, downloadEntity.gameId)
|
||||
?.let {
|
||||
unzipXapkFile(it)
|
||||
if (showUnzipToast) {
|
||||
Utils.toast(mContext, "解压过程请勿退出光环助手!")
|
||||
}
|
||||
}
|
||||
|
||||
// XAPK (apks) 格式,不在乎 obb 文件夹是否可读
|
||||
if (downloadEntity.format == Constants.XAPK_APKS_FORMAT) {
|
||||
unzipAction.invoke()
|
||||
return@checkManageAllFilesOrStoragePermissionBeforeAction
|
||||
}
|
||||
|
||||
// 以 file 的方式访问 obb 文件夹是否可行
|
||||
val isFileStyleObbFolderReadable =
|
||||
if (systemHasFlaw) {
|
||||
File(Environment.getExternalStorageDirectory().path, "\u200bAndroid/obb").list() != null
|
||||
} else {
|
||||
File(Environment.getExternalStorageDirectory().path, "Android/obb").list() != null
|
||||
}
|
||||
|
||||
// 如果是文件夹风格的 obb 文件夹可读,或当前上下文不是 AppCompatActivity,或当前上下文已经被销毁,则直接解压
|
||||
if (isFileStyleObbFolderReadable
|
||||
|| context !is AppCompatActivity
|
||||
|| context.isFinishing
|
||||
) {
|
||||
unzipAction.invoke()
|
||||
} else {
|
||||
unzipWithCulpritHandled(context, downloadEntity.url, unzipAction)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
throwExceptionInDebug("如果是Apk包请使用PackageInstaller进行安装")
|
||||
@ -174,82 +135,6 @@ object XapkInstaller : XApkUnZipCallback, XApkUnZipOutputFactory {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 兜底解压方案,适用于一些奇葩系统
|
||||
*/
|
||||
private fun unzipWithCulpritHandled(activity: AppCompatActivity, xApkUrl: String, unzipAction: () -> Unit?) {
|
||||
if (Build.VERSION.SDK_INT == Build.VERSION_CODES.R
|
||||
|| Build.VERSION.SDK_INT == Build.VERSION_CODES.S
|
||||
) {
|
||||
val isDocStyleObbFolderReadable = isDocStyleObbFolderReadable(activity)
|
||||
|
||||
if (isDocStyleObbFolderReadable) {
|
||||
useDocStyleToUnzip = true
|
||||
unzipAction.invoke()
|
||||
} else {
|
||||
DialogHelper.showDialog(
|
||||
context = activity,
|
||||
title = "安装提示",
|
||||
content = "为了安装 XAPK 文件,请授予 OBB 文件夹的访问权限",
|
||||
confirmText = "确定",
|
||||
cancelText = "取消",
|
||||
confirmClickCallback = {
|
||||
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE)
|
||||
intent.setFlags(
|
||||
Intent.FLAG_GRANT_READ_URI_PERMISSION
|
||||
and Intent.FLAG_GRANT_WRITE_URI_PERMISSION
|
||||
and Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION
|
||||
and Intent.FLAG_GRANT_PREFIX_URI_PERMISSION
|
||||
)
|
||||
|
||||
val obbUri = OBBDocOutput.ANDROID_OBB_DOC_STYLE_URI.toUri()
|
||||
val df = DocumentFile.fromTreeUri(activity, obbUri)
|
||||
if (df != null) {
|
||||
intent.putExtra(DocumentsContract.EXTRA_INITIAL_URI, df.uri)
|
||||
}
|
||||
|
||||
tempLauncher =
|
||||
activity.registerActivityResultLauncher(ActivityResultContracts.OpenDocumentTree()) { uri ->
|
||||
if (uri != null) {
|
||||
activity.contentResolver.takePersistableUriPermission(
|
||||
uri,
|
||||
Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION
|
||||
)
|
||||
|
||||
useDocStyleToUnzip = true
|
||||
unzipAction.invoke()
|
||||
}
|
||||
|
||||
tempLauncher?.unregister()
|
||||
}
|
||||
|
||||
tempLauncher?.launch(obbUri)
|
||||
},
|
||||
cancelClickCallback = {
|
||||
unzipAction.invoke()
|
||||
}
|
||||
)
|
||||
}
|
||||
} else {
|
||||
PermissionHelper.checkStoragePermissionBeforeAction(activity) {
|
||||
// 设备大于 12,需要重启才能生效 (是的,我们又重启了!)
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
||||
// 记录应用重启前需要重解压的信息
|
||||
SPUtils.setString(Constants.SP_XAPK_UNZIP_ACTIVITY, activity.javaClass.name)
|
||||
SPUtils.setString(Constants.SP_XAPK_URL, xApkUrl)
|
||||
|
||||
val pm = activity.packageManager
|
||||
val intent = pm.getLaunchIntentForPackage(activity.packageName)
|
||||
val mainIntent = Intent.makeRestartActivityTask(intent!!.component)
|
||||
activity.startActivity(mainIntent)
|
||||
Runtime.getRuntime().exit(0)
|
||||
} else {
|
||||
unzipAction.invoke()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun unzipXapkFile(downloadEntity: DownloadEntity) {
|
||||
mXApkUnZipper.unzip(
|
||||
XApkUnZipEntry(
|
||||
@ -439,7 +324,7 @@ object XapkInstaller : XApkUnZipCallback, XApkUnZipOutputFactory {
|
||||
}
|
||||
|
||||
override fun onCreateOBBOutput(apk: XApkFile): XApkFileOutput<Unit> {
|
||||
return if (useDocStyleToUnzip) OBBDocOutput(mContext) else OBBFileOutput()
|
||||
return OBBFileOutput()
|
||||
}
|
||||
|
||||
override fun onCreateApkOutput(apk: XApkFile): XApkFileOutput<IPackageInstaller> {
|
||||
@ -455,16 +340,6 @@ object XapkInstaller : XApkUnZipCallback, XApkUnZipOutputFactory {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否能以 DocumentUi 的方式访问 obb 文件夹
|
||||
*/
|
||||
private fun isDocStyleObbFolderReadable(context: Context): Boolean {
|
||||
return context
|
||||
.contentResolver
|
||||
.persistedUriPermissions
|
||||
.any { it.uri == OBBDocOutput.ANDROID_OBB_URI.toUri() }
|
||||
}
|
||||
|
||||
private class SplitApksInstaller(
|
||||
private val xApkFile: XApkFile,
|
||||
private val sessionId: Int,
|
||||
@ -476,12 +351,7 @@ object XapkInstaller : XApkUnZipCallback, XApkUnZipOutputFactory {
|
||||
|
||||
mPendingSessionInfoMap[downloadEntity.path] = XapkPendingSessionInfo(downloadEntity.path, sessionId)
|
||||
AppExecutor.ioExecutor.execute {// 有可能卡顿造成anr
|
||||
PackageInstaller.installMultiple(
|
||||
applicationContext,
|
||||
downloadEntity.packageName,
|
||||
downloadEntity.path,
|
||||
sessionId
|
||||
)
|
||||
PackageInstaller.installMultiple(applicationContext, downloadEntity.packageName, downloadEntity.path, sessionId)
|
||||
NDataChanger.notifyDataChanged(downloadEntity)
|
||||
}
|
||||
}
|
||||
|
||||
@ -17,6 +17,15 @@ import androidx.collection.ArrayMap;
|
||||
import androidx.lifecycle.LiveData;
|
||||
import androidx.lifecycle.MutableLiveData;
|
||||
|
||||
import com.gh.gamecenter.common.base.GlobalActivityManager;
|
||||
import com.gh.gamecenter.common.utils.ExtensionsKt;
|
||||
import com.gh.gamecenter.common.utils.SensorsBridge;
|
||||
import com.gh.gamecenter.core.AppExecutor;
|
||||
import com.gh.gamecenter.common.constant.Constants;
|
||||
import com.gh.gamecenter.core.GHThreadFactory;
|
||||
import com.gh.gamecenter.feature.entity.TagStyleEntity;
|
||||
import com.gh.gamecenter.feature.entity.CustomPageTrackData;
|
||||
import com.gh.gamecenter.feature.exposure.ExposureEvent;
|
||||
import com.gh.common.exposure.ExposureUtils;
|
||||
import com.gh.common.history.HistoryHelper;
|
||||
import com.gh.common.simulator.SimulatorGameManager;
|
||||
@ -27,16 +36,10 @@ import com.gh.common.util.LunchType;
|
||||
import com.gh.common.util.PackageInstaller;
|
||||
import com.gh.common.util.PackageUtils;
|
||||
import com.gh.gamecenter.BuildConfig;
|
||||
import com.gh.gamecenter.common.base.GlobalActivityManager;
|
||||
import com.gh.gamecenter.common.constant.Constants;
|
||||
import com.gh.gamecenter.common.exposure.meta.MetaUtil;
|
||||
import com.gh.gamecenter.common.utils.DeviceUtils;
|
||||
import com.gh.gamecenter.common.utils.ExtensionsKt;
|
||||
import com.gh.gamecenter.common.utils.FileUtils;
|
||||
import com.gh.gamecenter.common.utils.NetworkUtils;
|
||||
import com.gh.gamecenter.common.utils.SensorsBridge;
|
||||
import com.gh.gamecenter.core.AppExecutor;
|
||||
import com.gh.gamecenter.core.GHThreadFactory;
|
||||
import com.gh.gamecenter.core.utils.GsonUtils;
|
||||
import com.gh.gamecenter.core.utils.PageSwitchDataHelper;
|
||||
import com.gh.gamecenter.core.utils.SPUtils;
|
||||
@ -45,11 +48,8 @@ import com.gh.gamecenter.entity.GameUpdateEntity;
|
||||
import com.gh.gamecenter.entity.HomePluggableFilterEntity;
|
||||
import com.gh.gamecenter.eventbus.EBDownloadStatus;
|
||||
import com.gh.gamecenter.feature.entity.ApkEntity;
|
||||
import com.gh.gamecenter.feature.entity.CustomPageTrackData;
|
||||
import com.gh.gamecenter.feature.entity.GameEntity;
|
||||
import com.gh.gamecenter.feature.entity.PluginLocation;
|
||||
import com.gh.gamecenter.feature.entity.TagStyleEntity;
|
||||
import com.gh.gamecenter.feature.exposure.ExposureEvent;
|
||||
import com.gh.gamecenter.feature.utils.SentryHelper;
|
||||
import com.gh.gamecenter.login.user.UserManager;
|
||||
import com.gh.gamecenter.manager.PackagesManager;
|
||||
@ -1296,7 +1296,7 @@ public class DownloadManager implements DownloadStatusListener {
|
||||
getInstance().packageExecutor.execute(() -> {
|
||||
boolean markHasChanged = false;
|
||||
|
||||
List<GameUpdateEntity> updates = PackageRepository.INSTANCE.getGameUpdate();
|
||||
ArrayList<GameUpdateEntity> updates = PackageRepository.INSTANCE.getGameUpdate();
|
||||
for (GameUpdateEntity update : updates) {
|
||||
if (update == null) continue;
|
||||
String mark = update.getId() + update.getPackageName();
|
||||
@ -1317,7 +1317,7 @@ public class DownloadManager implements DownloadStatusListener {
|
||||
* 将可用更新标记为已读的事件
|
||||
*/
|
||||
public void saveUpdateMarkToStorage() {
|
||||
List<GameUpdateEntity> updates = PackageRepository.INSTANCE.getGameUpdate();
|
||||
ArrayList<GameUpdateEntity> updates = PackageRepository.INSTANCE.getGameUpdate();
|
||||
if (updates.size() == mUpdateMarks.size()) {
|
||||
SPUtils.setStringSet(UPDATE_IS_READ_MARK, mUpdateMarks);
|
||||
return;
|
||||
|
||||
@ -15,8 +15,7 @@ import androidx.lifecycle.Observer
|
||||
import androidx.lifecycle.ViewModelProviders
|
||||
import androidx.recyclerview.widget.*
|
||||
import androidx.recyclerview.widget.RecyclerView.SmoothScroller
|
||||
import com.gh.common.util.DialogUtils
|
||||
import com.gh.common.util.DirectUtils
|
||||
import com.gh.common.util.*
|
||||
import com.gh.download.DownloadManager
|
||||
import com.gh.gamecenter.BuildConfig
|
||||
import com.gh.gamecenter.R
|
||||
@ -31,9 +30,9 @@ import com.gh.gamecenter.core.AppExecutor
|
||||
import com.gh.gamecenter.core.utils.TimeElapsedHelper
|
||||
import com.gh.gamecenter.databinding.DialogDownloadBinding
|
||||
import com.gh.gamecenter.entity.GamePlatform
|
||||
import com.gh.gamecenter.eventbus.EBPackage
|
||||
import com.gh.gamecenter.feature.entity.ApkEntity
|
||||
import com.gh.gamecenter.feature.entity.GameEntity
|
||||
import com.gh.gamecenter.eventbus.EBPackage
|
||||
import com.gh.gamecenter.feature.exposure.ExposureEvent
|
||||
import com.halo.assistant.HaloApp
|
||||
import com.lightgame.download.DataWatcher
|
||||
@ -71,8 +70,6 @@ class DownloadDialog : BaseDraggableDialogFragment() {
|
||||
private var mEntrance: String = "" // 入口位置
|
||||
private var mLocation: String = "" // 最终位置
|
||||
|
||||
private var onDownloadClickAction: ((Boolean) -> Unit)? = null
|
||||
|
||||
|
||||
private val mDataWatcher = object : DataWatcher() {
|
||||
override fun onDataChanged(downloadEntity: DownloadEntity) {
|
||||
@ -125,7 +122,7 @@ class DownloadDialog : BaseDraggableDialogFragment() {
|
||||
}
|
||||
mViewModel.listLiveData.observeNonNull(this, callback = { itemList ->
|
||||
mAdapter =
|
||||
DownloadDialogAdapter(requireContext(), mViewModel, itemList, false, mTraceEvent, mEntrance, mLocation, onDownloadClickAction)
|
||||
DownloadDialogAdapter(requireContext(), mViewModel, itemList, false, mTraceEvent, mEntrance, mLocation)
|
||||
mBinding.contentList.layoutManager = createLayoutManager(itemList)
|
||||
mBinding.contentList.adapter = mAdapter
|
||||
performAutoDownload(itemList, mBinding.contentList)
|
||||
@ -429,8 +426,7 @@ class DownloadDialog : BaseDraggableDialogFragment() {
|
||||
gameEntity: GameEntity,
|
||||
traceEvent: ExposureEvent?,
|
||||
entrance: String?,
|
||||
location: String?,
|
||||
onDownloadClickAction: ((Boolean) -> Unit)? = null
|
||||
location: String?
|
||||
) {
|
||||
val fragmentActivity: FragmentActivity = if (context is FragmentActivity) {
|
||||
context
|
||||
@ -456,7 +452,6 @@ class DownloadDialog : BaseDraggableDialogFragment() {
|
||||
bundle.putParcelable(EntranceConsts.KEY_TRACE_EVENT, traceEvent)
|
||||
arguments = bundle
|
||||
}
|
||||
downloadDialog.onDownloadClickAction = onDownloadClickAction
|
||||
downloadDialog.show(fragmentActivity.supportFragmentManager, DownloadDialog::class.java.name)
|
||||
}
|
||||
|
||||
|
||||
@ -24,8 +24,7 @@ class DownloadDialogAdapter(
|
||||
val isCollectionPage: Boolean,
|
||||
private val mTraceEvent: ExposureEvent?,
|
||||
private val mEntrance: String,
|
||||
private val mLocation: String,
|
||||
private val onDownloadClickAction: ((Boolean) -> Unit)? = null
|
||||
private val mLocation: String
|
||||
) : BaseRecyclerAdapter<RecyclerView.ViewHolder>(context) {
|
||||
|
||||
private val mPath = if (isCollectionPage) {
|
||||
@ -171,8 +170,7 @@ class DownloadDialogAdapter(
|
||||
mTraceEvent,
|
||||
mEntrance,
|
||||
mPath,
|
||||
mLocation,
|
||||
onDownloadClickAction
|
||||
mLocation
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@ -41,8 +41,7 @@ class DownloadDialogItemViewHolder(val binding: DownloadDialogItemBinding) : Bas
|
||||
traceEvent: ExposureEvent?,
|
||||
entrance: String,
|
||||
path: String,
|
||||
location: String,
|
||||
onDownloadClickAction: ((Boolean) -> Unit)? = null
|
||||
location: String
|
||||
) {
|
||||
|
||||
val apkEntity = listData[position].normal!!
|
||||
@ -182,7 +181,7 @@ class DownloadDialogItemViewHolder(val binding: DownloadDialogItemBinding) : Bas
|
||||
}
|
||||
}
|
||||
|
||||
setDownloadClickListener(itemView, apkEntity, viewModel, traceEvent, entrance, path, location, onDownloadClickAction)
|
||||
setDownloadClickListener(itemView, apkEntity, viewModel, traceEvent, entrance, path, location)
|
||||
}
|
||||
|
||||
private fun changeRecommendUI(apkEntity: ApkEntity, listData: List<DownloadDialogItemData>, position: Int) {
|
||||
@ -227,8 +226,7 @@ class DownloadDialogItemViewHolder(val binding: DownloadDialogItemBinding) : Bas
|
||||
traceEvent: ExposureEvent?,
|
||||
entrance: String,
|
||||
path: String,
|
||||
location: String,
|
||||
onDownloadClickAction: ((Boolean) -> Unit)? = null
|
||||
location: String
|
||||
) {
|
||||
|
||||
val gameEntity = viewModel.gameEntity
|
||||
@ -236,7 +234,6 @@ class DownloadDialogItemViewHolder(val binding: DownloadDialogItemBinding) : Bas
|
||||
when (itemView.getTag(DownloadDialogAdapter.ITEM_TAG_KEY)) {
|
||||
DownloadDialogItemStatus.DOWNLOAD -> {
|
||||
createDownloadTask(it.context, apkEntity, gameEntity, traceEvent, entrance, location)
|
||||
onDownloadClickAction?.invoke(false)
|
||||
}
|
||||
DownloadDialogItemStatus.LAUNCH -> {
|
||||
PackageLauncher.launchApp(it.context, gameEntity, apkEntity.packageName)
|
||||
@ -294,7 +291,6 @@ class DownloadDialogItemViewHolder(val binding: DownloadDialogItemBinding) : Bas
|
||||
}
|
||||
DownloadDialogItemStatus.UPDATE -> {
|
||||
createDownloadTask(it.context, apkEntity, gameEntity, traceEvent, entrance, location)
|
||||
onDownloadClickAction?.invoke(true)
|
||||
}
|
||||
DownloadDialogItemStatus.COLLECTION -> {
|
||||
val apkCollection = apkEntity.apkCollection
|
||||
|
||||
@ -3,7 +3,6 @@ package com.gh.download.server
|
||||
import android.content.Context
|
||||
import android.os.Build
|
||||
import android.util.Base64
|
||||
import androidx.annotation.WorkerThread
|
||||
import com.gh.common.constant.Config
|
||||
import com.gh.common.util.DirectUtils
|
||||
import com.gh.common.util.LogUtils
|
||||
@ -247,19 +246,6 @@ object BrowserInstallHelper {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化是否满足开启浏览器安装的条件(后续会使用缓存来判断)
|
||||
* @param settingsEntity 服务器返回的配置
|
||||
*
|
||||
* 因为可能需要查询已安装的应用,所以需要在子线程中调用
|
||||
*/
|
||||
@WorkerThread
|
||||
fun initIfConditionMatched(settingsEntity: NewSettingsEntity?) {
|
||||
settingsEntity?.let {
|
||||
isConditionMatched(it)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否满足开启浏览器安装的条件
|
||||
*/
|
||||
|
||||
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()
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@ -5,10 +5,15 @@ import android.content.ContextWrapper
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import com.therouter.router.Autowired
|
||||
import com.therouter.router.Route
|
||||
import com.therouter.TheRouter
|
||||
import com.gh.base.DownloadToolbarActivity
|
||||
import com.gh.common.exposure.ExposureManager
|
||||
import com.gh.common.exposure.ExposureTraceUtils.appendTrace
|
||||
import com.gh.gamecenter.common.base.GlobalActivityManager
|
||||
import com.gh.gamecenter.common.base.activity.ToolBarActivity.NORMAL_FRAGMENT_BUNDLE
|
||||
import com.gh.gamecenter.common.base.activity.ToolBarActivity.NORMAL_FRAGMENT_NAME
|
||||
import com.gh.gamecenter.common.constant.EntranceConsts
|
||||
import com.gh.gamecenter.common.constant.RouteConsts
|
||||
import com.gh.gamecenter.common.utils.toArrayList
|
||||
@ -19,11 +24,7 @@ import com.gh.gamecenter.feature.entity.GameEntity
|
||||
import com.gh.gamecenter.feature.exposure.ExposureEvent
|
||||
import com.gh.gamecenter.feature.exposure.ExposureEvent.Companion.createEvent
|
||||
import com.gh.gamecenter.feature.exposure.ExposureType
|
||||
import com.gh.gamecenter.gamedetail.GameDetailWrapperFragment
|
||||
import com.gh.gamecenter.gamedetail.entity.GameDetailTabEntity
|
||||
import com.therouter.TheRouter
|
||||
import com.therouter.router.Autowired
|
||||
import com.therouter.router.Route
|
||||
import com.gh.gamecenter.gamedetail.GameDetailFragment
|
||||
|
||||
@Route(
|
||||
path = RouteConsts.activity.gameDetailActivity,
|
||||
@ -73,11 +74,11 @@ class GameDetailActivity : DownloadToolbarActivity() {
|
||||
generateDataFromRoute()
|
||||
|
||||
super.onCreate(savedInstanceState)
|
||||
DisplayUtils.setStatusBarColor(this, com.gh.gamecenter.common.R.color.transparent, !mIsDarkModeOn)
|
||||
DisplayUtils.transparentStatusBar(this)
|
||||
}
|
||||
|
||||
override fun provideNormalIntent(): Intent {
|
||||
return getTargetIntent(this, GameDetailActivity::class.java, GameDetailWrapperFragment::class.java)
|
||||
return getTargetIntent(this, GameDetailActivity::class.java, GameDetailFragment::class.java)
|
||||
}
|
||||
|
||||
override fun getLayoutId() = R.layout.activity_game_detail
|
||||
@ -126,15 +127,10 @@ class GameDetailActivity : DownloadToolbarActivity() {
|
||||
private fun generateDataFromRoute() {
|
||||
val bundle = intent.extras
|
||||
|
||||
intent?.putExtra(NORMAL_FRAGMENT_NAME, GameDetailWrapperFragment::class.java.canonicalName)
|
||||
intent?.putExtra(NORMAL_FRAGMENT_NAME, GameDetailFragment::class.java.canonicalName)
|
||||
intent?.putExtra(NORMAL_FRAGMENT_BUNDLE, bundle)
|
||||
}
|
||||
|
||||
override fun onDarkModeChanged() {
|
||||
super.onDarkModeChanged()
|
||||
DisplayUtils.setStatusBarColor(this, com.gh.gamecenter.common.R.color.transparent, !mIsDarkModeOn)
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
@JvmStatic
|
||||
@ -194,12 +190,12 @@ class GameDetailActivity : DownloadToolbarActivity() {
|
||||
}
|
||||
|
||||
if (scrollToLibao) {
|
||||
bundle.putString(EntranceConsts.KEY_TARGET, GameDetailTabEntity.TYPE_DETAIL)
|
||||
bundle.putString(EntranceConsts.KEY_TARGET, EntranceConsts.TAB_TYPE_DESC)
|
||||
bundle.putBoolean(EntranceConsts.KEY_SCROLL_TO_LIBAO, true)
|
||||
}
|
||||
|
||||
if (scrollToServer) {
|
||||
bundle.putString(EntranceConsts.KEY_TARGET, GameDetailTabEntity.TYPE_DETAIL)
|
||||
bundle.putString(EntranceConsts.KEY_TARGET, EntranceConsts.TAB_TYPE_DESC)
|
||||
bundle.putBoolean(EntranceConsts.KEY_SCROLL_TO_SERVER, true)
|
||||
}
|
||||
|
||||
@ -306,7 +302,7 @@ class GameDetailActivity : DownloadToolbarActivity() {
|
||||
}
|
||||
if (openVideoStreaming) {
|
||||
bundle.putBoolean(EntranceConsts.KEY_OPEN_VIDEO_STREAMING, true)
|
||||
bundle.putString(EntranceConsts.KEY_TARGET, GameDetailTabEntity.TYPE_DETAIL)
|
||||
bundle.putString(EntranceConsts.KEY_TARGET, EntranceConsts.TAB_TYPE_DESC)
|
||||
}
|
||||
if (openPlatformWindow) {
|
||||
bundle.putBoolean(EntranceConsts.KEY_OPEN_PLATFORM_WINDOW, true)
|
||||
@ -320,7 +316,7 @@ class GameDetailActivity : DownloadToolbarActivity() {
|
||||
}
|
||||
}
|
||||
if (scrollToLibao) {
|
||||
bundle.putString(EntranceConsts.KEY_TARGET, GameDetailTabEntity.TYPE_DETAIL)
|
||||
bundle.putString(EntranceConsts.KEY_TARGET, EntranceConsts.TAB_TYPE_DESC)
|
||||
bundle.putBoolean(EntranceConsts.KEY_SCROLL_TO_LIBAO, true)
|
||||
}
|
||||
bundle.putString(EntranceConsts.KEY_GAME_ID, gameId)
|
||||
|
||||
@ -136,7 +136,6 @@ import io.reactivex.SingleSource;
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.functions.Function;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
import kotlin.Pair;
|
||||
import kotlin.Unit;
|
||||
import kotlin.jvm.functions.Function0;
|
||||
import okhttp3.RequestBody;
|
||||
@ -182,6 +181,7 @@ public class MainActivity extends BaseActivity {
|
||||
.get(MainWrapperViewModel.class);
|
||||
|
||||
DisplayUtils.transparentStatusBar(this);
|
||||
DisplayUtils.updateGlobalScreen(this);
|
||||
|
||||
super.onCreate(savedInstanceState);
|
||||
setStatusBarColor(Color.TRANSPARENT);
|
||||
@ -1084,12 +1084,4 @@ public class MainActivity extends BaseActivity {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Pair<String, String> getBusinessId() {
|
||||
if (mMainWrapperFragment != null) {
|
||||
return mMainWrapperFragment.getBusinessId();
|
||||
}
|
||||
return super.getBusinessId();
|
||||
}
|
||||
}
|
||||
|
||||
@ -91,6 +91,7 @@ open class SearchActivity : BaseActivity() {
|
||||
mSourceEntrance = intent.getStringExtra(EntranceConsts.KEY_SOURCE_ENTRANCE) ?: ""
|
||||
val hint = intent.getStringExtra(EntranceConsts.KEY_HINT)
|
||||
val searchImmediately = intent.getBooleanExtra(KEY_SEARCH_IMMEDIATELY, false)
|
||||
var ignoreTextChanges = savedInstanceState != null
|
||||
|
||||
mPublishSubject = PublishSubject.create()
|
||||
|
||||
@ -101,9 +102,12 @@ open class SearchActivity : BaseActivity() {
|
||||
.subscribe {
|
||||
if (searchEt.text.isNotEmpty()
|
||||
&& searchEt.text != searchEt.hint
|
||||
&& !ignoreTextChanges
|
||||
) {
|
||||
search(SearchType.AUTO, it)
|
||||
}
|
||||
|
||||
ignoreTextChanges = false
|
||||
}
|
||||
|
||||
initSearchBar()
|
||||
@ -198,6 +202,7 @@ open class SearchActivity : BaseActivity() {
|
||||
|
||||
protected open fun handleEmptySearch(newSearchKey: String) {
|
||||
popBackToFragment(SearchDefaultFragment::class.java.name)// 回退到搜索首页
|
||||
updateDisplayType(DisplayType.DEFAULT)
|
||||
mPublishSubject?.onNext(newSearchKey)
|
||||
}
|
||||
|
||||
|
||||
@ -5,12 +5,11 @@ import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.os.Parcelable
|
||||
import android.view.View
|
||||
import com.gh.gamecenter.amway.AmwaySuccessFragment
|
||||
import com.gh.gamecenter.common.base.activity.ToolBarActivity
|
||||
import com.gh.gamecenter.common.base.fragment.BaseFragment
|
||||
import com.gh.gamecenter.common.constant.EntranceConsts
|
||||
import com.gh.gamecenter.gamedetail.cloudarchive.CloudArchiveFragment
|
||||
import com.gh.gamecenter.gamedetail.libao.LibaoListFragment
|
||||
import com.gh.gamecenter.amway.AmwaySuccessFragment
|
||||
import com.gh.gamecenter.gamedetail.LibaoListFragment
|
||||
import com.halo.assistant.fragment.SwitchInstallMethodFragment
|
||||
import com.halo.assistant.fragment.user.ManuallyRealNameFragment
|
||||
import com.halo.assistant.fragment.user.RealNameInfoFragment
|
||||
@ -39,7 +38,6 @@ class ShellActivity : ToolBarActivity() {
|
||||
Type.REAL_NAME_INFO -> startFragment(RealNameInfoFragment().with(bundle))
|
||||
Type.MANUALLY_REAL_NAME -> startFragment(ManuallyRealNameFragment().with(extraData))
|
||||
Type.SIMPLE_LIBAO_LIST -> startFragment(LibaoListFragment.newInstance(extraData))
|
||||
Type.CLOUD_ARCHIVE -> startFragment(CloudArchiveFragment().with(extraData))
|
||||
}
|
||||
}
|
||||
|
||||
@ -74,8 +72,7 @@ class ShellActivity : ToolBarActivity() {
|
||||
SWITCH_INSTALL_METHOD("switch_install_method"),
|
||||
REAL_NAME_INFO("real_name_info"),
|
||||
MANUALLY_REAL_NAME("manually_real_name"),
|
||||
SIMPLE_LIBAO_LIST("simple_libao_list"),
|
||||
CLOUD_ARCHIVE("cloud_archive");
|
||||
SIMPLE_LIBAO_LIST("simple_libao_list");
|
||||
|
||||
companion object {
|
||||
fun fromString(typeString: String): Type {
|
||||
|
||||
@ -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.TheRouter
|
||||
import com.therouter.router.Route
|
||||
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,9 @@ 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)) {
|
||||
@ -104,7 +104,7 @@ class SplashScreenActivity : BaseActivity(), ISplashScreen {
|
||||
executeDex2OatInAdvance()
|
||||
DialogHelper.showDialog(
|
||||
context = this,
|
||||
title ="选择环境",
|
||||
title = "选择环境",
|
||||
content = spanBuilder,
|
||||
confirmText = "正式环境",
|
||||
cancelText = "测试环境",
|
||||
@ -131,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
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2,7 +2,6 @@ package com.gh.gamecenter.adapter;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.text.Html;
|
||||
import android.text.SpannableStringBuilder;
|
||||
import android.text.Spanned;
|
||||
@ -13,7 +12,6 @@ import android.text.style.ClickableSpan;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.LinearLayout;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.core.content.ContextCompat;
|
||||
@ -22,14 +20,9 @@ import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import androidx.recyclerview.widget.RecyclerView.ViewHolder;
|
||||
|
||||
import com.facebook.drawee.drawable.ScalingUtils;
|
||||
import com.facebook.drawee.generic.GenericDraweeHierarchyBuilder;
|
||||
import com.facebook.drawee.generic.RoundingParams;
|
||||
import com.facebook.drawee.view.SimpleDraweeView;
|
||||
import com.gh.common.util.DirectUtils;
|
||||
import com.gh.common.util.LibaoUtils;
|
||||
import com.gh.gamecenter.GameDetailActivity;
|
||||
import com.gh.gamecenter.ImageViewerActivity;
|
||||
import com.gh.gamecenter.R;
|
||||
import com.gh.gamecenter.adapter.viewholder.LibaoDetailContentViewHolder;
|
||||
import com.gh.gamecenter.adapter.viewholder.LibaoDetailTopViewHolder;
|
||||
@ -38,7 +31,6 @@ import com.gh.gamecenter.common.entity.SimpleGameEntity;
|
||||
import com.gh.gamecenter.common.entity.SuggestType;
|
||||
import com.gh.gamecenter.common.retrofit.Response;
|
||||
import com.gh.gamecenter.common.utils.ExtensionsKt;
|
||||
import com.gh.gamecenter.common.utils.ImageUtils;
|
||||
import com.gh.gamecenter.common.utils.PicassoImageGetter;
|
||||
import com.gh.gamecenter.common.viewholder.FooterViewHolder;
|
||||
import com.gh.gamecenter.core.utils.DisplayUtils;
|
||||
@ -87,7 +79,6 @@ public class LibaoDetailAdapter extends BaseRecyclerAdapter<ViewHolder> {
|
||||
private String mEntrance;
|
||||
private final int TYPE_FOOTER = 100;
|
||||
public LibaoDetailTopViewHolder libaoDetailTopViewHolder;
|
||||
private ArrayList<View> mImageViewList = new ArrayList<>();
|
||||
|
||||
public LibaoDetailAdapter(Context context, OnRequestCallBackListener onRequestCallBackListener,
|
||||
OnCodeScrollListener onCodeScrollListener, LibaoEntity libaoEntity,
|
||||
@ -326,35 +317,6 @@ public class LibaoDetailAdapter extends BaseRecyclerAdapter<ViewHolder> {
|
||||
holder.binding.libaodetailContentLl.setVisibility(View.VISIBLE);
|
||||
holder.binding.libaodetailContent.setText(Html.fromHtml(mLibaoEntity.getContent()));
|
||||
}
|
||||
if (mLibaoEntity.getMaterials().isEmpty()) {
|
||||
holder.binding.horizontalScrollView.setVisibility(View.GONE);
|
||||
} else {
|
||||
holder.binding.horizontalScrollView.setVisibility(View.VISIBLE);
|
||||
holder.binding.imagesContainer.removeAllViews();
|
||||
mImageViewList.clear();
|
||||
for (int i = 0; i < mLibaoEntity.getMaterials().size(); i++) {
|
||||
String imageUrl = mLibaoEntity.getMaterials().get(i).getImg();
|
||||
SimpleDraweeView imageView = new SimpleDraweeView(mContext);
|
||||
RoundingParams roundingParams = new RoundingParams();
|
||||
roundingParams.setCornersRadius(DisplayUtils.dip2px(4F));
|
||||
roundingParams.setOverlayColor(ContextCompat.getColor(mContext, com.gh.gamecenter.common.R.color.ui_surface));
|
||||
imageView.setHierarchy(new GenericDraweeHierarchyBuilder(mContext.getResources())
|
||||
.setFadeDuration(500)
|
||||
.setRoundingParams(roundingParams)
|
||||
.setPlaceholderImage(com.gh.gamecenter.common.R.drawable.occupy, ScalingUtils.ScaleType.FIT_XY)
|
||||
.build());
|
||||
ImageUtils.display(imageView, imageUrl);
|
||||
final int index = i;
|
||||
imageView.setOnClickListener(v -> {
|
||||
Intent intent = ImageViewerActivity.getIntent(mContext, mLibaoEntity.getMaterialImgList(), index, mImageViewList, mEntrance);
|
||||
mContext.startActivity(intent);
|
||||
});
|
||||
mImageViewList.add(imageView);
|
||||
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(DisplayUtils.dip2px(24F), DisplayUtils.dip2px(24F));
|
||||
layoutParams.setMargins(DisplayUtils.dip2px(i == 0 ? 8F : 16F), 0, 0, 0);
|
||||
holder.binding.imagesContainer.addView(imageView, layoutParams);
|
||||
}
|
||||
}
|
||||
if (mLibaoDetailEntity != null) {
|
||||
holder.binding.libaodetailTimeLl.setVisibility(View.VISIBLE);
|
||||
|
||||
|
||||
@ -35,6 +35,7 @@ import com.gh.gamecenter.common.base.GlobalActivityManager.getCurrentPageEntity
|
||||
import com.gh.gamecenter.common.base.GlobalActivityManager.getLastPageEntity
|
||||
import com.gh.gamecenter.common.constant.Constants
|
||||
import com.gh.gamecenter.common.constant.EntranceConsts
|
||||
import com.gh.gamecenter.common.eventbus.EBReuse
|
||||
import com.gh.gamecenter.common.utils.*
|
||||
import com.gh.gamecenter.common.utils.NewFlatLogUtils
|
||||
import com.gh.gamecenter.core.runOnIoThread
|
||||
@ -47,10 +48,9 @@ import com.gh.gamecenter.feature.entity.GameEntity
|
||||
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.GameDetailViewModel
|
||||
import com.gh.gamecenter.gamedetail.GameDetailFragment
|
||||
import com.gh.gamecenter.gamedetail.accelerator.GameDetailAcceleratorUiHelper
|
||||
import com.gh.gamecenter.gamedetail.dialog.GamePermissionDialogFragment
|
||||
import com.gh.gamecenter.gamedetail.entity.GameDetailTabEntity
|
||||
import com.gh.gamecenter.teenagermode.TeenagerModeActivity.Companion.getIntent
|
||||
import com.gh.vspace.VHelper
|
||||
import com.lightgame.download.DownloadEntity
|
||||
@ -61,7 +61,6 @@ import java.io.File
|
||||
// 虽然叫 ViewHolder,但其实就是一个用来临时放 View 和相关操作的包裹类
|
||||
class DetailViewHolder(
|
||||
view: View,
|
||||
val viewModel: GameDetailViewModel?,
|
||||
val gameEntity: GameEntity,
|
||||
val isNewsDetail: Boolean, // 新闻详情不显示下载的游戏名, 只显示下载状态
|
||||
entrance: String?,
|
||||
@ -69,8 +68,7 @@ class DetailViewHolder(
|
||||
title: String?,
|
||||
val traceEvent: ExposureEvent?,
|
||||
val isSupportDualButton: Boolean = false, // 是否支持双下载按钮,不支持的时候跟普通列表意义选用优先级高的那个来显示,
|
||||
val acceleratorUiHelper: GameDetailAcceleratorUiHelper? = null, // 网速加速,只有游戏详情才有
|
||||
onDownloadClickAction: ((Boolean) -> Unit)? = null
|
||||
val acceleratorUiHelper: GameDetailAcceleratorUiHelper? = null // 网速加速,只有游戏详情才有
|
||||
) {
|
||||
var context: Context
|
||||
var downloadBottom: View
|
||||
@ -133,8 +131,7 @@ class DetailViewHolder(
|
||||
mTitle = title ?: "",
|
||||
mAsVGame = false,
|
||||
mShowDualDownloadButton = gameDownloadMode == GameEntity.GAME_DOWNLOAD_BUTTON_MODE_DUAL,
|
||||
mTraceEvent = traceEvent,
|
||||
onDownloadClickAction = onDownloadClickAction
|
||||
mTraceEvent = traceEvent
|
||||
)
|
||||
|
||||
val vGameDownloadListener = OnDetailDownloadClickListener(
|
||||
@ -144,8 +141,7 @@ class DetailViewHolder(
|
||||
mTitle = title ?: "",
|
||||
mAsVGame = true,
|
||||
mShowDualDownloadButton = gameDownloadMode == GameEntity.GAME_DOWNLOAD_BUTTON_MODE_DUAL,
|
||||
mTraceEvent = traceEvent,
|
||||
onDownloadClickAction = onDownloadClickAction
|
||||
mTraceEvent = traceEvent
|
||||
)
|
||||
|
||||
// 不支持双下载按钮的情况时,优选一个下载方式显示
|
||||
@ -198,26 +194,12 @@ class DetailViewHolder(
|
||||
gamePermissionDialogFragment?.dismissAllowingStateLoss()
|
||||
}
|
||||
|
||||
fun hideSpeedUi() {
|
||||
acceleratorUiHelper?.showSpeedUi = false
|
||||
}
|
||||
|
||||
fun checkIfShowSpeedUi(rawBtnText: String) {
|
||||
acceleratorUiHelper?.let {
|
||||
when {
|
||||
rawBtnText == "启动" && gameEntity.canSpeed -> {
|
||||
downloadPb.goneIf(true)
|
||||
localDownloadButton?.goneIf(true)
|
||||
it.checkIfShowSpeedUi(true)
|
||||
}
|
||||
|
||||
rawBtnText == "更新" && gameEntity.canSpeed -> {
|
||||
it.checkIfShowSpeedUi(true)
|
||||
}
|
||||
|
||||
else -> {
|
||||
it.checkIfShowSpeedUi(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun showAcceleratorGuideLayer() {
|
||||
acceleratorUiHelper?.checkIfShowGuideLayer(context)
|
||||
}
|
||||
|
||||
fun setSpeedViewsVisible(isVisible: Boolean) {
|
||||
@ -232,8 +214,7 @@ class DetailViewHolder(
|
||||
private val mTitle: String,
|
||||
private val mAsVGame: Boolean,
|
||||
private val mShowDualDownloadButton: Boolean,
|
||||
private val mTraceEvent: ExposureEvent?,
|
||||
private val onDownloadClickAction: ((Boolean) -> Unit)? = null
|
||||
private val mTraceEvent: ExposureEvent?
|
||||
) : View.OnClickListener {
|
||||
|
||||
private val mGameEntity: GameEntity = mViewHolder.gameEntity
|
||||
@ -331,13 +312,11 @@ class DetailViewHolder(
|
||||
showLandPageAddressDialogIfNeeded()
|
||||
}
|
||||
}
|
||||
|
||||
"toast" -> {
|
||||
mViewHolder.viewModel?.performTabSelected(GameDetailTabEntity.TYPE_COMMENT)
|
||||
EventBus.getDefault().post(EBReuse(GameDetailFragment.SKIP_RATING))
|
||||
ToastUtils.toast("该游戏因故暂不提供下载,具体详情可在相关评论中查看,敬请谅解~")
|
||||
showLandPageAddressDialogIfNeeded()
|
||||
}
|
||||
|
||||
"third_party" -> {
|
||||
showLandPageAddressDialogIfNeeded()
|
||||
}
|
||||
@ -418,8 +397,7 @@ class DetailViewHolder(
|
||||
gameEntity = mGameEntity,
|
||||
traceEvent = mTraceEvent,
|
||||
entrance = StringUtils.buildString(mEntrance, "+(", mName, "[", mTitle, "])"),
|
||||
location = "$mName:$mTitle",
|
||||
onDownloadClickAction = onDownloadClickAction
|
||||
location = "$mName:$mTitle"
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -737,7 +715,6 @@ class DetailViewHolder(
|
||||
builder.addHandler(OverseaDownloadHandler())
|
||||
builder.addHandler(CheckDownloadHandler())
|
||||
builder.setProcessEndCallback(mGameEntity.id) { asVGame: Boolean, isSubscribe: Any? ->
|
||||
performDownloadClickAction()
|
||||
download(asVGame, isSubscribe as Boolean)
|
||||
}
|
||||
} else {
|
||||
@ -755,8 +732,7 @@ class DetailViewHolder(
|
||||
mTitle,
|
||||
"])"
|
||||
),
|
||||
"$mName:$mTitle",
|
||||
onDownloadClickAction
|
||||
"$mName:$mTitle"
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -767,20 +743,5 @@ class DetailViewHolder(
|
||||
mAsVGame
|
||||
)
|
||||
}
|
||||
|
||||
private fun performDownloadClickAction() {
|
||||
val buttonText = if (mShowDualDownloadButton && !mAsVGame) {
|
||||
mViewHolder.localDownloadTitleTv?.text?.ifEmpty {
|
||||
mViewHolder.downloadPb.text.ifEmpty {
|
||||
mViewHolder.overlayTv?.text ?: ""
|
||||
}
|
||||
}
|
||||
} else {
|
||||
mViewHolder.downloadPb.text.ifEmpty { mViewHolder.overlayTv?.text ?: "" }
|
||||
}
|
||||
val isUpdate =
|
||||
buttonText?.contains(mViewHolder.context.getString(com.gh.gamecenter.feature.R.string.update)) == true
|
||||
onDownloadClickAction?.invoke(isUpdate)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,7 +1,5 @@
|
||||
package com.gh.gamecenter.authorization
|
||||
|
||||
import android.app.Activity
|
||||
import android.app.Application.ActivityLifecycleCallbacks
|
||||
import android.app.Dialog
|
||||
import android.content.Intent
|
||||
import android.os.Build
|
||||
@ -24,7 +22,6 @@ import com.gh.gamecenter.login.user.UserManager
|
||||
import com.gh.gamecenter.login.user.UserRepository
|
||||
import com.gh.gamecenter.login.view.LoginActivity
|
||||
import com.gh.vspace.VHelper
|
||||
import com.halo.assistant.HaloApp
|
||||
import com.lightgame.utils.Utils
|
||||
|
||||
/**
|
||||
@ -142,7 +139,7 @@ class AuthorizationActivity : ToolBarActivity() {
|
||||
override fun onRestart() {
|
||||
super.onRestart()
|
||||
if (!CheckLoginUtils.isLogin()) {
|
||||
finishAndRemoveTask()
|
||||
finish()
|
||||
} else {
|
||||
initUserInfo()
|
||||
initData()
|
||||
@ -153,12 +150,12 @@ class AuthorizationActivity : ToolBarActivity() {
|
||||
private fun checkParam() {
|
||||
val uri = intent.data
|
||||
if (uri == null) {
|
||||
finishAndRemoveTask()
|
||||
finish()
|
||||
return
|
||||
}
|
||||
val host = uri.host
|
||||
if (host != "authorize") {
|
||||
finishAndRemoveTask()
|
||||
finish()
|
||||
return
|
||||
}
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1) {
|
||||
@ -171,7 +168,7 @@ class AuthorizationActivity : ToolBarActivity() {
|
||||
gameName = uri.getQueryParameter(EntranceConsts.KEY_GAME_NAME) ?: ""
|
||||
gameUid = uri.getQueryParameter(EntranceConsts.KEY_UID)?.toIntOrNull() ?: -1
|
||||
if (mRemotePkgName == null) {
|
||||
finishAndRemoveTask()
|
||||
finish()
|
||||
return
|
||||
}
|
||||
}
|
||||
@ -224,7 +221,7 @@ class AuthorizationActivity : ToolBarActivity() {
|
||||
val remotePkgName = mRemotePkgName
|
||||
if (remotePkgName == null) {
|
||||
logAuthResult(false)
|
||||
finishAndRemoveTask()
|
||||
finish()
|
||||
return
|
||||
}
|
||||
if (mToken.isEmpty()) {
|
||||
@ -245,44 +242,13 @@ class AuthorizationActivity : ToolBarActivity() {
|
||||
intent.putExtra(EntranceConsts.KEY_USER_NAME, username)
|
||||
intent.putExtra(EntranceConsts.KEY_USER_AVATAR, userAvatar)
|
||||
if (gameUid != -1 && Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||
try {
|
||||
sendBroadcastAsUser(intent, UserHandle.getUserHandleForUid(gameUid))
|
||||
} catch (e: Exception) {
|
||||
// 双开/分身游戏进行授权时,如果无 INTERACT_ACROSS_USERS 权限,则使用Activity传递授权结果
|
||||
authByActivity(intent)
|
||||
return
|
||||
}
|
||||
sendBroadcastAsUser(intent, UserHandle.getUserHandleForUid(gameUid))
|
||||
} else {
|
||||
sendBroadcast(intent)
|
||||
}
|
||||
logAuthResult(true)
|
||||
backToLaunchApp()
|
||||
finishAndRemoveTask()
|
||||
}
|
||||
|
||||
private fun authByActivity(intent: Intent) {
|
||||
intent.setClassName(mRemotePkgName!!, AUTHORIZATION_RESULT_ACTIVITY)
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
HaloApp.getInstance().registerActivityLifecycleCallbacks(object : ActivityLifecycleCallbacks {
|
||||
override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {}
|
||||
override fun onActivityStarted(activity: Activity) {}
|
||||
override fun onActivityResumed(activity: Activity) {}
|
||||
override fun onActivityPaused(activity: Activity) {}
|
||||
override fun onActivityStopped(activity: Activity) {
|
||||
if (activity == this@AuthorizationActivity) {
|
||||
HaloApp.getInstance().unregisterActivityLifecycleCallbacks(this)
|
||||
finishAndRemoveTask()
|
||||
}
|
||||
}
|
||||
override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) {}
|
||||
override fun onActivityDestroyed(activity: Activity) {
|
||||
if (activity == this@AuthorizationActivity) {
|
||||
HaloApp.getInstance().unregisterActivityLifecycleCallbacks(this)
|
||||
}
|
||||
}
|
||||
})
|
||||
startActivity(intent)
|
||||
logAuthResult(true)
|
||||
finish()
|
||||
}
|
||||
|
||||
private fun logAuthResult(isSuccess: Boolean) {
|
||||
@ -311,7 +277,7 @@ class AuthorizationActivity : ToolBarActivity() {
|
||||
}
|
||||
|
||||
override fun onBackPressed() {
|
||||
finishAndRemoveTask()
|
||||
super.onBackPressed()
|
||||
|
||||
backToLaunchApp(false)
|
||||
|
||||
@ -326,7 +292,6 @@ class AuthorizationActivity : ToolBarActivity() {
|
||||
private const val BUTTON_TYPE_CONFIRM = "确定"
|
||||
private const val BUTTON_TYPE_BACK = "返回"
|
||||
private const val TYPE_PLUGIN = "plugin"
|
||||
private const val AUTHORIZATION_RESULT_ACTIVITY = "com.gh.plugin.AuthorizationResultActivity"
|
||||
}
|
||||
|
||||
}
|
||||
@ -2,30 +2,17 @@ package com.gh.gamecenter.cloudarchive
|
||||
|
||||
import android.app.Application
|
||||
import com.gh.gamecenter.common.baselist.ListViewModel
|
||||
import com.gh.gamecenter.common.utils.toRequestBody
|
||||
import com.gh.gamecenter.entity.ArchiveEntity
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager
|
||||
import com.lightgame.utils.Utils
|
||||
import io.reactivex.Observable
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
import okhttp3.*
|
||||
import retrofit2.HttpException
|
||||
import java.io.IOException
|
||||
|
||||
open class BaseCloudArchiveViewModel(
|
||||
application: Application,
|
||||
private val mGameId: String,
|
||||
private var mConfigUrl: String
|
||||
) : ListViewModel<ArchiveEntity, ArchiveEntity>(application) {
|
||||
open class BaseCloudArchiveViewModel(application: Application, private val mConfigUrl: String): ListViewModel<ArchiveEntity, ArchiveEntity>(application) {
|
||||
private var mArchiveConfigStr = ""
|
||||
|
||||
init {
|
||||
if (mConfigUrl.isEmpty()) {
|
||||
getArchiveConfigUrl()
|
||||
} else {
|
||||
getArchiveConfigString()
|
||||
}
|
||||
getArchiveConfigString()
|
||||
}
|
||||
|
||||
// 通过url获取config字符串内容
|
||||
@ -54,27 +41,6 @@ open class BaseCloudArchiveViewModel(
|
||||
}
|
||||
}
|
||||
|
||||
// 获取游戏存档配置url
|
||||
private fun getArchiveConfigUrl() {
|
||||
val map = mapOf(
|
||||
"game_ids" to listOf(mGameId)
|
||||
)
|
||||
RetrofitManager.getInstance().newApi.getGamesArchiveConfigs(map.toRequestBody())
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(object : com.gh.gamecenter.common.retrofit.Response<List<ArchiveEntity>>() {
|
||||
override fun onResponse(response: List<ArchiveEntity>?) {
|
||||
mConfigUrl = response?.find { it.gameId == mGameId }?.configUrl ?: return
|
||||
getArchiveConfigString()
|
||||
}
|
||||
|
||||
override fun onFailure(e: HttpException?) {
|
||||
super.onFailure(e)
|
||||
Utils.toast(getApplication(), "获取存档配置失败")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
override fun provideDataObservable(page: Int): Observable<List<ArchiveEntity>>? = null
|
||||
|
||||
override fun mergeResultLiveData() {}
|
||||
|
||||
@ -216,7 +216,7 @@ class CloudArchiveManagerActivity : BaseActivity_TabLayout(), ArchiveLimitSelect
|
||||
|
||||
private fun initDownloadBtn() {
|
||||
mGameEntity?.let { gameEntity ->
|
||||
DownloadItemUtils.updateDownloadButton(this, mBinding.downloadBtn, gameEntity, listener = null)
|
||||
DownloadItemUtils.updateDownloadButton(this, mBinding.downloadBtn, gameEntity)
|
||||
DownloadItemUtils.setOnClickListener(this, mBinding.downloadBtn, gameEntity, 0, null, mEntrance, "")
|
||||
}
|
||||
}
|
||||
|
||||
@ -8,6 +8,7 @@ import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import com.gh.common.util.NewFlatLogUtils
|
||||
import com.gh.gamecenter.common.retrofit.BiResponse
|
||||
import com.gh.gamecenter.common.utils.toJson
|
||||
import com.gh.gamecenter.common.utils.toRequestBody
|
||||
import com.gh.gamecenter.core.utils.GsonUtils
|
||||
import com.gh.gamecenter.entity.ArchiveEntity
|
||||
@ -21,7 +22,7 @@ import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.disposables.CompositeDisposable
|
||||
import io.reactivex.disposables.Disposable
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
import okhttp3.ResponseBody
|
||||
import okhttp3.*
|
||||
import retrofit2.HttpException
|
||||
|
||||
class CloudArchiveManagerViewModel(
|
||||
@ -29,7 +30,7 @@ class CloudArchiveManagerViewModel(
|
||||
val gameId: String,
|
||||
val gameName: String,
|
||||
configUrl: String
|
||||
) : BaseCloudArchiveViewModel(application, gameId, configUrl) {
|
||||
) : BaseCloudArchiveViewModel(application, configUrl) {
|
||||
|
||||
companion object {
|
||||
private const val SORT_TYPE_CREATE = "time.create:-1"
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
package com.gh.gamecenter.entity
|
||||
|
||||
import com.gh.gamecenter.feature.entity.Count
|
||||
import com.gh.gamecenter.feature.entity.SimpleGame
|
||||
import com.gh.gamecenter.feature.entity.Count
|
||||
import com.google.gson.annotations.SerializedName
|
||||
|
||||
data class GameDetailRecommendGameCollectionEntity(
|
||||
data class GameDetailRecommendGameEntity(
|
||||
@SerializedName("_id")
|
||||
val id: String = "",
|
||||
val cover: String = "",
|
||||
@ -1,11 +0,0 @@
|
||||
package com.gh.gamecenter.entity
|
||||
|
||||
import androidx.room.Entity
|
||||
import androidx.room.PrimaryKey
|
||||
|
||||
@Entity
|
||||
data class HistoryGameDetailEntity(
|
||||
@PrimaryKey
|
||||
var id: String = "",
|
||||
var name: String? = "",
|
||||
)
|
||||
@ -1,5 +0,0 @@
|
||||
package com.gh.gamecenter.eventbus
|
||||
|
||||
import com.gh.gamecenter.feature.entity.AcctGameInfo
|
||||
|
||||
class EBStartupAcceleration(val acctGameInfo: AcctGameInfo)
|
||||
@ -8,6 +8,7 @@ import android.text.SpannableStringBuilder
|
||||
import android.view.View
|
||||
import com.facebook.drawee.view.SimpleDraweeView
|
||||
import com.gh.common.util.*
|
||||
import com.gh.common.util.DialogUtils
|
||||
import com.gh.common.util.LogUtils
|
||||
import com.gh.common.util.NewLogUtils
|
||||
import com.gh.common.view.ImageContainerView
|
||||
@ -16,18 +17,22 @@ import com.gh.gamecenter.ImageViewerActivity
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.base.activity.BaseActivity
|
||||
import com.gh.gamecenter.common.callback.ConfirmListener
|
||||
import com.gh.gamecenter.common.entity.AdditionalParamsEntity
|
||||
import com.gh.gamecenter.common.entity.CommunityEntity
|
||||
import com.gh.gamecenter.common.utils.*
|
||||
import com.gh.gamecenter.core.utils.MtaHelper
|
||||
import com.gh.gamecenter.core.utils.SpanBuilder
|
||||
import com.gh.gamecenter.core.utils.ToastUtils
|
||||
import com.gh.gamecenter.databinding.CommunityAnswerItemBinding
|
||||
import com.gh.gamecenter.feature.entity.ForumVideoEntity
|
||||
import com.gh.gamecenter.eventbus.EBUserFollow
|
||||
import com.gh.gamecenter.forum.detail.ForumDetailActivity
|
||||
import com.gh.gamecenter.login.user.UserManager
|
||||
import com.gh.gamecenter.qa.answer.BaseAnswerOrArticleItemViewHolder
|
||||
import com.gh.gamecenter.qa.article.detail.ArticleDetailActivity
|
||||
import com.gh.gamecenter.feature.entity.AnswerEntity
|
||||
import com.gh.gamecenter.feature.entity.ArticleEntity
|
||||
import com.gh.gamecenter.feature.entity.CommunityItemData
|
||||
import com.gh.gamecenter.feature.entity.ForumVideoEntity
|
||||
import com.gh.gamecenter.forum.detail.ForumDetailActivity
|
||||
import com.gh.gamecenter.forum.home.ArticleItemVideoView.Companion.toArticleVideoData
|
||||
import com.gh.gamecenter.forum.search.CommunitySearchEventListener
|
||||
import com.gh.gamecenter.forum.search.CommunitySearchEventListener.Companion.SEARCH_BUTTON_COMMENT
|
||||
@ -39,9 +44,6 @@ import com.gh.gamecenter.forum.search.CommunitySearchEventListener.Companion.SEA
|
||||
import com.gh.gamecenter.forum.search.CommunitySearchEventListener.Companion.SEARCH_BUTTON_VIEW_IMAGE
|
||||
import com.gh.gamecenter.forum.search.CommunitySearchEventListener.Companion.SEARCH_BUTTON_VIEW_USER_DETAIL
|
||||
import com.gh.gamecenter.forum.search.CommunitySearchEventListener.Companion.htmlToString
|
||||
import com.gh.gamecenter.login.user.UserManager
|
||||
import com.gh.gamecenter.qa.answer.BaseAnswerOrArticleItemViewHolder
|
||||
import com.gh.gamecenter.qa.article.detail.ArticleDetailActivity
|
||||
import com.gh.gamecenter.qa.entity.QuestionsDetailEntity
|
||||
import com.gh.gamecenter.qa.questions.invite.QuestionsInviteActivity
|
||||
import com.gh.gamecenter.qa.questions.newdetail.NewQuestionDetailActivity
|
||||
@ -346,8 +348,8 @@ class ForumArticleAskItemViewHolder(
|
||||
.setReleaseWhenLossAudio(true)
|
||||
.setLooping(false)
|
||||
.setShowFullAnimation(false)
|
||||
.setEnlargeImageRes(R.drawable.ic_video_enter_full_screen)
|
||||
.setShrinkImageRes(R.drawable.ic_video_exit_full_screen)
|
||||
.setEnlargeImageRes(R.drawable.ic_game_detail_enter_full_screen)
|
||||
.setShrinkImageRes(R.drawable.ic_game_detail_exit_full_screen)
|
||||
.setVideoAllCallBack(object : GSYSampleCallBack() {
|
||||
override fun onQuitFullscreen(url: String?, vararg objects: Any) {
|
||||
orientationUtils.backToProtVideo()
|
||||
|
||||
@ -3,29 +3,26 @@ package com.gh.gamecenter.game.horizontal
|
||||
import android.content.Context
|
||||
import android.view.ViewGroup
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.gh.common.util.DataCollectionUtils
|
||||
import com.gh.common.util.DownloadItemUtils
|
||||
import com.gh.common.util.*
|
||||
import com.gh.common.util.NewLogUtils
|
||||
import com.gh.gamecenter.GameDetailActivity
|
||||
import com.gh.gamecenter.adapter.viewholder.GameViewHolder
|
||||
import com.gh.gamecenter.common.base.GlobalActivityManager
|
||||
import com.gh.gamecenter.common.utils.*
|
||||
import com.gh.gamecenter.core.utils.StringUtils
|
||||
import com.gh.gamecenter.entity.SubjectEntity
|
||||
import com.gh.gamecenter.feature.entity.GameEntity
|
||||
import com.gh.gamecenter.feature.exposure.ExposureEvent
|
||||
import com.gh.gamecenter.feature.minigame.MiniGameItemHelper
|
||||
import com.gh.gamecenter.gamedetail.detail.viewholder.BaseGameDetailItemViewHolder
|
||||
import com.gh.gamecenter.home.custom.model.CustomPageItem.Companion.subjectTypeToComponentStyle
|
||||
import com.gh.gamecenter.feature.minigame.MiniGameItemHelper
|
||||
import com.lightgame.adapter.BaseRecyclerAdapter
|
||||
import com.lightgame.download.DownloadEntity
|
||||
|
||||
class GameHorizontalAdapter(
|
||||
context: Context,
|
||||
var subjectEntity: SubjectEntity,
|
||||
private var mSubjectEntity: SubjectEntity,
|
||||
private var type: GameHorizontalListType = GameHorizontalListType.SubjectHorizontalType,
|
||||
private val trackColumnClick: Boolean = true,
|
||||
private val gameDetailTrackData: BaseGameDetailItemViewHolder.GameDetailModuleTrackData? = null,
|
||||
private val getGameStatus: (() -> String)? = null
|
||||
private val trackColumnClick: Boolean = true
|
||||
) : BaseRecyclerAdapter<GameHorizontalItemViewHolder>(context) {
|
||||
|
||||
var gameName = ""
|
||||
@ -40,15 +37,15 @@ class GameHorizontalAdapter(
|
||||
|
||||
init {
|
||||
var dataIds = ""
|
||||
subjectEntity.data?.forEach {
|
||||
mSubjectEntity.data?.forEach {
|
||||
dataIds += it.id
|
||||
}
|
||||
if (dataIds.isNotEmpty()) countAndKey = Pair(subjectEntity.data?.size ?: 0, dataIds)
|
||||
if (dataIds.isNotEmpty()) countAndKey = Pair(mSubjectEntity.data?.size ?: 0, dataIds)
|
||||
}
|
||||
|
||||
fun getIndex(): Int {
|
||||
if (subjectEntity.data!!.isNotEmpty()) {
|
||||
return if (subjectEntity.data!![0].image.isNullOrEmpty()) 0 else 1
|
||||
if (mSubjectEntity.data!!.isNotEmpty()) {
|
||||
return if (mSubjectEntity.data!![0].image.isNullOrEmpty()) 0 else 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
@ -56,13 +53,13 @@ class GameHorizontalAdapter(
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = GameHorizontalItemViewHolder(parent.toBinding())
|
||||
|
||||
override fun getItemCount(): Int {
|
||||
val size = subjectEntity.data!!.size - getIndex()
|
||||
val size = mSubjectEntity.data!!.size - getIndex()
|
||||
return when (type) {
|
||||
GameHorizontalListType.GameDetailHorizontalType -> {
|
||||
size
|
||||
}
|
||||
GameHorizontalListType.MiniGameSubjectHorizontalType -> {
|
||||
subjectEntity.data!!.size
|
||||
mSubjectEntity.data!!.size
|
||||
}
|
||||
else -> when {
|
||||
size < 4 -> size
|
||||
@ -83,15 +80,14 @@ class GameHorizontalAdapter(
|
||||
}
|
||||
holder.binding.root.layoutParams = params
|
||||
|
||||
val gameEntity = subjectEntity.data!![position + getIndex()]
|
||||
val gameEntity = mSubjectEntity.data!![position + getIndex()]
|
||||
holder.binding.simpleGameContainer.run {
|
||||
gameIcon.displayGameIcon(gameEntity)
|
||||
GameHorizontalSimpleItemViewHolder.setHorizontalNameAndGravity(gameName, gameEntity.name)
|
||||
downloadBtn.goneIf(!subjectEntity.showDownload)
|
||||
gameName.setTextColor(com.gh.gamecenter.common.R.color.text_primary.toColor(mContext))
|
||||
gameName.maxLines = if (subjectEntity.showDownload) 1 else 2
|
||||
downloadBtn.goneIf(!mSubjectEntity.showDownload)
|
||||
gameName.maxLines = if (mSubjectEntity.showDownload) 1 else 2
|
||||
}
|
||||
holder.bindGameHorizontalItem(gameEntity, subjectEntity)
|
||||
holder.bindGameHorizontalItem(gameEntity, mSubjectEntity)
|
||||
val entranceResult: String
|
||||
val locationResult: String
|
||||
if (type == GameHorizontalListType.GameDetailHorizontalType) {
|
||||
@ -108,35 +104,37 @@ class GameHorizontalAdapter(
|
||||
locationResult = StringUtils.buildString("游戏详情-", gameName, "-${path}", ":", gameEntity.name)
|
||||
} else {
|
||||
entranceResult =
|
||||
StringUtils.buildString("(游戏-专题:", subjectEntity.name, "-列表[", (position + 1).toString(), "])")
|
||||
locationResult = StringUtils.buildString("游戏-专题-", subjectEntity.name, ":", gameEntity.name)
|
||||
StringUtils.buildString("(游戏-专题:", mSubjectEntity.name, "-列表[", (position + 1).toString(), "])")
|
||||
locationResult = StringUtils.buildString("游戏-专题-", mSubjectEntity.name, ":", gameEntity.name)
|
||||
}
|
||||
holder.itemView.setOnClickListener {
|
||||
if (type == GameHorizontalListType.GameDetailHorizontalType) {
|
||||
DataCollectionUtils.uploadClick(mContext, path, "游戏详情", gameEntity.name)
|
||||
NewLogUtils.logGameDetailPopularClick(gameName, gameId, "game", gameEntity.name ?: "")
|
||||
SensorsBridge.trackGameDetailModuleClick(
|
||||
gameDetailTrackData?.gameId,
|
||||
gameDetailTrackData?.gameName,
|
||||
gameDetailTrackData?.gameType,
|
||||
"组件内容",
|
||||
gameDetailTrackData?.moduleType,
|
||||
gameDetailTrackData?.moduleName,
|
||||
gameDetailTrackData?.sequence,
|
||||
linkType = "game",
|
||||
linkId = gameEntity.id,
|
||||
linkText = gameEntity.name ?: "",
|
||||
gameStatus = getGameStatus?.invoke()
|
||||
SensorsBridge.trackGameDetailPagePopularClick(
|
||||
gameId = gameId,
|
||||
gameName = gameName,
|
||||
pageName = GlobalActivityManager.getCurrentPageEntity().pageName,
|
||||
pageId = GlobalActivityManager.getCurrentPageEntity().pageId,
|
||||
pageBusinessId = GlobalActivityManager.getCurrentPageEntity().pageBusinessId,
|
||||
lastPageName = GlobalActivityManager.getLastPageEntity().pageName,
|
||||
lastPageId = GlobalActivityManager.getLastPageEntity().pageId,
|
||||
lastPageBusinessId = GlobalActivityManager.getLastPageEntity().pageBusinessId,
|
||||
downloadStatus = game?.downloadStatusChinese ?: "",
|
||||
gameType = game?.categoryChinese ?: "",
|
||||
clickGameType = gameEntity.categoryChinese,
|
||||
clickGameName = gameEntity.name ?: "",
|
||||
clickGameId = gameEntity.id
|
||||
)
|
||||
if (!gameEntity.isMiniGame() && trackColumnClick) {
|
||||
SensorsBridge.trackColumnClick(
|
||||
location = "游戏详情",
|
||||
gameName = gameName,
|
||||
gameId = gameId,
|
||||
gameColumnName = subjectEntity.name ?: "",
|
||||
gameColumnId = subjectEntity.id ?: "",
|
||||
gameColumnName = mSubjectEntity.name ?: "",
|
||||
gameColumnId = mSubjectEntity.id ?: "",
|
||||
text = "游戏",
|
||||
columnPattern = subjectTypeToComponentStyle[subjectEntity.type] ?: ""
|
||||
columnPattern = subjectTypeToComponentStyle[mSubjectEntity.type] ?: ""
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -153,7 +151,7 @@ class GameHorizontalAdapter(
|
||||
}
|
||||
}
|
||||
|
||||
if (subjectEntity.showDownload && type != GameHorizontalListType.GameDetailHorizontalType) {
|
||||
if (mSubjectEntity.showDownload && type != GameHorizontalListType.GameDetailHorizontalType) {
|
||||
DownloadItemUtils.setOnClickListener(
|
||||
mContext,
|
||||
holder.binding.simpleGameContainer.downloadBtn,
|
||||
@ -181,7 +179,7 @@ class GameHorizontalAdapter(
|
||||
if (downloadEntity == null) {
|
||||
notifyDataSetChanged()
|
||||
} else {
|
||||
subjectEntity.data?.forEachIndexed { position, gameEntity ->
|
||||
mSubjectEntity.data?.forEachIndexed { position, gameEntity ->
|
||||
if (downloadEntity.gameId == gameEntity.id) {
|
||||
notifyItemChanged(position - getIndex())
|
||||
return
|
||||
@ -191,7 +189,7 @@ class GameHorizontalAdapter(
|
||||
}
|
||||
|
||||
fun notifyChildItem(packageName: String) {
|
||||
subjectEntity.data?.forEachIndexed { position, gameEntity ->
|
||||
mSubjectEntity.data?.forEachIndexed { position, gameEntity ->
|
||||
gameEntity.getApk().forEach { apkEntity ->
|
||||
if (apkEntity.packageName == packageName) {
|
||||
notifyItemChanged(position - getIndex())
|
||||
@ -208,11 +206,11 @@ class GameHorizontalAdapter(
|
||||
dataIds += it.id
|
||||
}
|
||||
|
||||
this.subjectEntity = subjectEntity
|
||||
if (countAndKey?.first != subjectEntity.data?.size) { // 数量发生改变
|
||||
notifyDataSetChanged()
|
||||
} else {
|
||||
mSubjectEntity = subjectEntity
|
||||
if (countAndKey?.first == subjectEntity.data?.size && countAndKey?.second != dataIds) { // 数量不变,内容发生改变
|
||||
notifyItemRangeChanged(0, itemCount)
|
||||
} else if (countAndKey?.first != subjectEntity.data?.size) { // 数量发生改变
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
|
||||
// 重新刷新数据标识
|
||||
|
||||
@ -39,6 +39,7 @@ import com.gh.gamecenter.common.syncpage.SyncDataEntity
|
||||
import com.gh.gamecenter.common.syncpage.SyncFieldConstants
|
||||
import com.gh.gamecenter.common.syncpage.SyncPageRepository
|
||||
import com.gh.gamecenter.common.utils.*
|
||||
import com.gh.gamecenter.common.view.SegmentedFilterView
|
||||
import com.gh.gamecenter.core.iinterface.IScrollable
|
||||
import com.gh.gamecenter.core.utils.*
|
||||
import com.gh.gamecenter.databinding.FragmentGameCollectionDetailBinding
|
||||
@ -47,6 +48,7 @@ import com.gh.gamecenter.entity.GamesCollectionDetailEntity
|
||||
import com.gh.gamecenter.eventbus.EBDownloadStatus
|
||||
import com.gh.gamecenter.eventbus.EBPackage
|
||||
import com.gh.gamecenter.eventbus.EBUserFollow
|
||||
import com.gh.gamecenter.gamedetail.GameDetailFragment
|
||||
import com.gh.gamecenter.home.video.ScrollCalculatorHelper
|
||||
import com.gh.gamecenter.login.user.UserManager
|
||||
import com.gh.gamecenter.login.user.UserViewModel
|
||||
@ -185,10 +187,12 @@ class GameCollectionDetailFragment :
|
||||
root.layoutParams = this
|
||||
}
|
||||
orderSfv.setItemList(listOf("正序", "倒序"), 0)
|
||||
orderSfv.setOnCheckedCallback { position ->
|
||||
getFilterVH()?.binding?.orderSfv?.performClick(position)
|
||||
updateFilterView()
|
||||
}
|
||||
orderSfv.setOnCheckedCallback(object : SegmentedFilterView.OnCheckedCallback {
|
||||
override fun onItemCheck(position: Int) {
|
||||
getFilterVH()?.binding?.orderSfv?.performClick(position)
|
||||
updateFilterView()
|
||||
}
|
||||
})
|
||||
commentHintTv.text = "玩家评论"
|
||||
}
|
||||
}
|
||||
@ -737,7 +741,7 @@ class GameCollectionDetailFragment :
|
||||
if (activity != null && activity?.isFinishing != true) {
|
||||
startPlayLogic(isAutoPlay = true)
|
||||
}
|
||||
}, INITIAL_DELAY)
|
||||
}, GameDetailFragment.INITIAL_DELAY)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1206,8 +1210,4 @@ class GameCollectionDetailFragment :
|
||||
appbar.setExpanded(true)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val INITIAL_DELAY = 500L
|
||||
}
|
||||
}
|
||||
@ -13,15 +13,15 @@ import android.widget.TextView
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.FragmentManager
|
||||
import com.gh.common.util.NewLogUtils
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.observer.MuteCallback
|
||||
import com.gh.gamecenter.common.observer.VolumeObserver
|
||||
import com.gh.gamecenter.common.utils.ImageUtils
|
||||
import com.gh.gamecenter.common.utils.NetworkUtils
|
||||
import com.gh.gamecenter.core.runOnIoThread
|
||||
import com.gh.common.util.*
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.utils.debounceActionWithInterval
|
||||
import com.gh.gamecenter.common.utils.rxTimer
|
||||
import com.gh.gamecenter.core.runOnIoThread
|
||||
import com.gh.gamecenter.common.utils.ImageUtils
|
||||
import com.gh.gamecenter.common.utils.NetworkUtils
|
||||
import com.gh.gamecenter.core.utils.MD5Utils
|
||||
import com.gh.gamecenter.entity.GamesCollectionDetailEntity
|
||||
import com.gh.gamecenter.home.video.ScrollCalculatorHelper
|
||||
@ -180,7 +180,7 @@ class GameCollectionVideoView @JvmOverloads constructor(context: Context, attrs:
|
||||
|
||||
private fun mute(isManual: Boolean = false) {
|
||||
viewModel?.videoIsMuted = true
|
||||
volume.setImageResource(R.drawable.ic_video_volume_off)
|
||||
volume.setImageResource(R.drawable.ic_game_detail_volume_off)
|
||||
CustomManager.getCustomManager(getKey()).isNeedMute = true
|
||||
if (isManual) {
|
||||
Utils.toast(context, "当前处于静音状态")
|
||||
@ -190,7 +190,7 @@ class GameCollectionVideoView @JvmOverloads constructor(context: Context, attrs:
|
||||
|
||||
private fun unMute(isManual: Boolean = false) {
|
||||
viewModel?.videoIsMuted = false
|
||||
volume.setImageResource(R.drawable.ic_video_volume_on)
|
||||
volume.setImageResource(R.drawable.ic_game_detail_volume_on)
|
||||
CustomManager.getCustomManager(getKey()).isNeedMute = false
|
||||
if (isManual) {
|
||||
logVideoEvent("video_game_collect_detail_mute_cancel")
|
||||
@ -278,9 +278,9 @@ class GameCollectionVideoView @JvmOverloads constructor(context: Context, attrs:
|
||||
if (mStartButton is ImageView) {
|
||||
val imageView = mStartButton as ImageView
|
||||
when (mCurrentState) {
|
||||
GSYVideoView.CURRENT_STATE_PLAYING -> imageView.setImageResource(R.drawable.ic_video_pause)
|
||||
GSYVideoView.CURRENT_STATE_ERROR -> imageView.setImageResource(R.drawable.ic_video_play)
|
||||
else -> imageView.setImageResource(R.drawable.ic_video_play)
|
||||
GSYVideoView.CURRENT_STATE_PLAYING -> imageView.setImageResource(R.drawable.ic_game_detail_pause)
|
||||
GSYVideoView.CURRENT_STATE_ERROR -> imageView.setImageResource(R.drawable.ic_game_detail_play)
|
||||
else -> imageView.setImageResource(R.drawable.ic_game_detail_play)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -314,11 +314,11 @@ class GameCollectionVideoView @JvmOverloads constructor(context: Context, attrs:
|
||||
}
|
||||
|
||||
override fun getEnlargeImageRes(): Int {
|
||||
return R.drawable.ic_video_enter_full_screen
|
||||
return R.drawable.ic_game_detail_enter_full_screen
|
||||
}
|
||||
|
||||
override fun getShrinkImageRes(): Int {
|
||||
return R.drawable.ic_video_exit_full_screen
|
||||
return R.drawable.ic_game_detail_exit_full_screen
|
||||
}
|
||||
|
||||
override fun onInterceptTouchEvent(ev: MotionEvent): Boolean {
|
||||
|
||||
@ -73,7 +73,6 @@ class GameCollectionHotListAdapter(
|
||||
if (holder is GameCollectionPlayerCreationAdapter.GameCollectionPlayerCreationHeaderItemViewHolder) {
|
||||
holder.binding.run {
|
||||
root.setPadding(0, if (mIsFromDetail) 16F.dip2px() else 0, 0, 12F.dip2px())
|
||||
timeSfv.visibility = View.GONE
|
||||
tipsIv.visibility = View.GONE
|
||||
tipsTv.text = mGameCollectionListEntity?.explain
|
||||
tipsTv.setTextColor(com.gh.gamecenter.common.R.color.text_tertiary.toColor(mContext))
|
||||
|
||||
@ -617,7 +617,6 @@ class GameCollectionSquareFragment : LazyListFragment<GamesCollectionEntity, Gam
|
||||
mAlternativeBinding.listRv.addOnScrollListener(object : RecyclerView.OnScrollListener() {
|
||||
override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
|
||||
super.onScrollStateChanged(recyclerView, newState)
|
||||
if (!isSupportVisible) return
|
||||
if (newState == RecyclerView.SCROLL_STATE_DRAGGING) {
|
||||
setFabStatus(mPostFabView, View.GONE)
|
||||
setFabStatus(mRefreshFabView, View.GONE)
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
package com.gh.gamecenter.gamedetail
|
||||
|
||||
import androidx.lifecycle.ViewModel
|
||||
import com.halo.assistant.accelerator.AccelerationUseCase
|
||||
import com.halo.assistant.member.MemberUseCase
|
||||
|
||||
class AcceleratorZoneViewModel : ViewModel() {
|
||||
|
||||
val useCase = AccelerationUseCase()
|
||||
val useCase = MemberUseCase()
|
||||
|
||||
override fun onCleared() {
|
||||
useCase.onClear()
|
||||
|
||||
@ -0,0 +1,51 @@
|
||||
package com.gh.gamecenter.gamedetail
|
||||
|
||||
import android.content.Context
|
||||
import android.view.ViewGroup
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.gh.gamecenter.common.utils.safelyGetInRelease
|
||||
import com.gh.gamecenter.common.utils.toBinding
|
||||
import com.gh.gamecenter.common.utils.toColor
|
||||
import com.gh.gamecenter.core.utils.TimeUtils
|
||||
import com.gh.gamecenter.databinding.ItemGameDetailContentCardContentBinding
|
||||
import com.gh.gamecenter.gamedetail.entity.ContentCardEntity
|
||||
import com.lightgame.adapter.BaseRecyclerAdapter
|
||||
|
||||
class GameDetailContentCardContentAdapter(
|
||||
context: Context,
|
||||
private val linkEntity: ContentCardEntity,
|
||||
private val isHighlightBg: Boolean = false
|
||||
) : BaseRecyclerAdapter<RecyclerView.ViewHolder>(context) {
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder =
|
||||
GameDetailContentCardContentItemViewHolder(parent.toBinding())
|
||||
|
||||
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
|
||||
if (holder is GameDetailContentCardContentItemViewHolder) {
|
||||
holder.binding.root.setTextColor(
|
||||
if (isHighlightBg) com.gh.gamecenter.common.R.color.text_secondary.toColor(mContext) else com.gh.gamecenter.common.R.color.text_tertiary.toColor(
|
||||
mContext
|
||||
)
|
||||
)
|
||||
if (linkEntity.type == "func_server" && linkEntity.server != null && linkEntity.server?.calendar?.isNotEmpty() == true) {
|
||||
val calendarList = linkEntity.server!!.calendar
|
||||
val realPosition = position % calendarList.size
|
||||
calendarList.safelyGetInRelease(realPosition)?.let {
|
||||
val serverTime =
|
||||
if (TimeUtils.isToday(it.getTime()))
|
||||
it.getFormatTime("今天 HH:mm")
|
||||
else if (TimeUtils.isTomorrow(it.getTime()))
|
||||
it.getFormatTime("明天 HH:mm")
|
||||
else
|
||||
it.getFormatTime("MM-dd HH:mm")
|
||||
holder.binding.root.text = "$serverTime ${it.type}"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int = Int.MAX_VALUE
|
||||
|
||||
class GameDetailContentCardContentItemViewHolder(var binding: ItemGameDetailContentCardContentBinding) :
|
||||
RecyclerView.ViewHolder(binding.root)
|
||||
}
|
||||
2764
app/src/main/java/com/gh/gamecenter/gamedetail/GameDetailFragment.kt
Normal file
2764
app/src/main/java/com/gh/gamecenter/gamedetail/GameDetailFragment.kt
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,57 @@
|
||||
package com.gh.gamecenter.gamedetail
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import android.widget.TextView
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.base.fragment.BaseFragment
|
||||
import com.gh.gamecenter.common.utils.toDrawable
|
||||
import com.gh.gamecenter.feature.entity.LibaoEntity
|
||||
import com.gh.gamecenter.gamedetail.desc.GameLibaoAdapter
|
||||
|
||||
class LibaoListFragment : BaseFragment<Any>() {
|
||||
|
||||
override fun getLayoutId() = R.layout.fragment_libao_list
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
val recyclerView = view.findViewById<RecyclerView>(R.id.recyclerView)
|
||||
val toolbarTitleTv = view.findViewById<TextView>(R.id.normal_title)
|
||||
val toolbarBackContainer = view.findViewById<View>(com.gh.gamecenter.selector.R.id.backContainer)
|
||||
|
||||
toolbarTitleTv.setText("游戏礼包")
|
||||
toolbarBackContainer.setOnClickListener { requireActivity().onBackPressed() }
|
||||
|
||||
val gameId = arguments?.getString(ARG_GAME_ID) ?: ""
|
||||
val gameName = arguments?.getString(ARG_GAME_NAME) ?: ""
|
||||
val libaoList = arguments?.getParcelableArrayList<LibaoEntity>(ARG_LIBAO_LIST) ?: arrayListOf()
|
||||
|
||||
recyclerView?.apply {
|
||||
layoutManager = LinearLayoutManager(requireContext())
|
||||
adapter = adapter ?: GameLibaoAdapter(requireContext(), libaoList, gameName, gameId, false, true)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
private const val ARG_GAME_ID = "game_id"
|
||||
private const val ARG_GAME_NAME = "game_name"
|
||||
private const val ARG_LIBAO_LIST = "libao_list"
|
||||
|
||||
fun getBundle(gameId: String, gameName: String, libaoList: ArrayList<LibaoEntity>) = Bundle().apply {
|
||||
putString(ARG_GAME_ID, gameId)
|
||||
putString(ARG_GAME_NAME, gameName)
|
||||
putParcelableArrayList(ARG_LIBAO_LIST, libaoList)
|
||||
}
|
||||
|
||||
fun newInstance(bundle: Bundle?) = LibaoListFragment().apply {
|
||||
if (bundle != null) {
|
||||
arguments = bundle
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -5,21 +5,22 @@ 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.accelerator.AccelerationUseCase
|
||||
import com.halo.assistant.accelerator.repository.AcceleratorDataHolder
|
||||
import com.halo.assistant.member.MemberUseCase
|
||||
import com.therouter.TheRouter
|
||||
import io.reactivex.disposables.CompositeDisposable
|
||||
|
||||
class StartingAcceleratorViewModel : ViewModel() {
|
||||
|
||||
private val compositeDisposable = CompositeDisposable()
|
||||
|
||||
val useCase = AccelerationUseCase()
|
||||
val useCase = MemberUseCase()
|
||||
|
||||
private val _restartingAcceleratorAction = MutableLiveData<Event<Boolean>>()
|
||||
val restartingAcceleratorAction: LiveData<Event<Boolean>> = _restartingAcceleratorAction
|
||||
@ -42,15 +43,15 @@ class StartingAcceleratorViewModel : ViewModel() {
|
||||
override fun onSuccess(data: BaseEntity<TrialEntity>) {
|
||||
if (data.data?.result == true) {
|
||||
// 刷新vip状态
|
||||
// 这里先刷新内存数据
|
||||
AcceleratorDataHolder.instance.setVipEntity(
|
||||
// 这里先刷新内存数据,再去刷新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)
|
||||
@ -64,6 +65,10 @@ class StartingAcceleratorViewModel : ViewModel() {
|
||||
}).let(compositeDisposable::add)
|
||||
}
|
||||
|
||||
private fun refreshVipStatus(userId: String) {
|
||||
UserRepository.getInstance().refreshVipStatus(userId, true)
|
||||
}
|
||||
|
||||
override fun onCleared() {
|
||||
super.onCleared()
|
||||
compositeDisposable.clear()
|
||||
|
||||
@ -1,49 +0,0 @@
|
||||
package com.gh.gamecenter.gamedetail.accelerator
|
||||
|
||||
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.AcctRecord
|
||||
import io.reactivex.Observable
|
||||
import io.reactivex.Single
|
||||
|
||||
@Dao
|
||||
interface AccelerationDao {
|
||||
|
||||
@Upsert
|
||||
fun upsertAcctGameInfo(gameInfo: AcctGameInfo): Single<Long>
|
||||
|
||||
@Upsert
|
||||
fun upsertAcctRecord(record: AcctRecord): Single<Long>
|
||||
|
||||
/**
|
||||
* 为什么这里定义成 Observable<List<AcctGameInfo>> 而不是 Observable<AcctGameInfo>
|
||||
* 因为当返回值为 Observable<T> 时,当表中未查询到数据,则不会收到任何回调
|
||||
* 使用 Observable<List<AcctGameInfo>>时,为查询到数据时会返回空数组
|
||||
*/
|
||||
@Query("SELECT * FROM AcctGameInfo WHERE gameId = :gameId")
|
||||
fun getAcctGameInfoByGameIdObservable(gameId: String): Observable<List<AcctGameInfo>>
|
||||
|
||||
@Query("SELECT EXISTS(SELECT 1 FROM AcctGameInfo LIMIT 1)")
|
||||
fun hasAnyAcctGameInfo(): Single<Boolean>
|
||||
|
||||
@Query("SELECT * FROM AcctGameInfo WHERE gameId IN (:gameIds)")
|
||||
fun queryAcctGameInfoByGameId(gameIds: List<String>): List<AcctGameInfo>
|
||||
|
||||
@Query("SELECT * FROM AcctRecord ORDER BY createTime DESC LIMIT 20")
|
||||
fun loadAcctRecordsObservable(): Observable<List<AcctRecord>>
|
||||
|
||||
@Query("SELECT * FROM AcctRecord ORDER BY createTime DESC LIMIT 20")
|
||||
fun loadAcctRecords(): List<AcctRecord>
|
||||
|
||||
/**
|
||||
* 获取最新的记录(根据createTime排序)
|
||||
* @return 最新的AcctRecord记录
|
||||
*/
|
||||
@Query("SELECT * FROM AcctRecord ORDER BY createTime DESC LIMIT 1")
|
||||
fun loadLatestRecord(): Single<AcctRecord>
|
||||
|
||||
@Query("SELECT EXISTS(SELECT 1 FROM AcctRecord LIMIT 1)")
|
||||
fun getAnyAcctRecordObservable(): Observable<Boolean>
|
||||
}
|
||||
@ -5,16 +5,14 @@ import androidx.room.Database
|
||||
import androidx.room.Room
|
||||
import androidx.room.RoomDatabase
|
||||
import androidx.room.TypeConverters
|
||||
import androidx.room.migration.Migration
|
||||
import androidx.sqlite.db.SupportSQLiteDatabase
|
||||
import com.gh.gamecenter.feature.entity.AcctGameInfo
|
||||
import com.gh.gamecenter.feature.entity.AcctRecord
|
||||
import com.gh.gamecenter.feature.entity.AcctZoneListBean
|
||||
import com.gh.gamecenter.room.converter.AcctGameInfoConverter
|
||||
import com.halo.assistant.HaloApp
|
||||
|
||||
@Database(
|
||||
entities = [AcctGameInfo::class, AcctRecord::class],
|
||||
version = 2,
|
||||
entities = [AcctGameInfo::class, AcctZoneListBean::class],
|
||||
version = 1,
|
||||
exportSchema = false
|
||||
)
|
||||
@TypeConverters(
|
||||
@ -22,7 +20,7 @@ import com.halo.assistant.HaloApp
|
||||
)
|
||||
abstract class AccelerationDataBase : RoomDatabase() {
|
||||
|
||||
abstract fun accelerationDao(): AccelerationDao
|
||||
abstract fun accelerationDao(): AcceleratorDao
|
||||
|
||||
companion object {
|
||||
private const val DATABASE_NAME: String = "acceleration_db"
|
||||
@ -31,63 +29,7 @@ abstract class AccelerationDataBase : RoomDatabase() {
|
||||
|
||||
private fun buildDatabase(context: Context): AccelerationDataBase {
|
||||
return Room.databaseBuilder(context, AccelerationDataBase::class.java, DATABASE_NAME)
|
||||
.addMigrations(MIGRATION_1_2)
|
||||
.allowMainThreadQueries()
|
||||
.build()
|
||||
}
|
||||
|
||||
private val MIGRATION_1_2 = object : Migration(1, 2) {
|
||||
override fun migrate(db: SupportSQLiteDatabase) {
|
||||
// 删除表 AcctZoneListBean
|
||||
db.execSQL("DROP TABLE IF EXISTS AcctZoneListBean")
|
||||
// 创建新表的SQL ,游戏加速成功记录
|
||||
createAcctRecordTab(db)
|
||||
|
||||
renamePrimaryKeyWithAcctGameInfoTab(db)
|
||||
|
||||
}
|
||||
|
||||
private fun createAcctRecordTab(db: SupportSQLiteDatabase) {
|
||||
db.execSQL(
|
||||
"""
|
||||
CREATE TABLE IF NOT EXISTS AcctRecord (
|
||||
gameId TEXT PRIMARY KEY NOT NULL,
|
||||
game TEXT NOT NULL,
|
||||
zoneInfo TEXT NOT NULL,
|
||||
hasMultiZone INTEGER NOT NULL,
|
||||
createTime INTEGER NOT NULL
|
||||
)
|
||||
"""
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* 重命名表 AcctGameInfo 主键
|
||||
* 游戏旧表中没有 gameId 字段,这里将旧表数据直接清空
|
||||
*/
|
||||
private fun renamePrimaryKeyWithAcctGameInfoTab(db: SupportSQLiteDatabase) {
|
||||
// 1. 创建临时表(包含新的结构)
|
||||
db.execSQL(
|
||||
"""
|
||||
CREATE TABLE IF NOT EXISTS AcctGameInfo_temp (
|
||||
gameId TEXT PRIMARY KEY NOT NULL,
|
||||
accGamePkgName TEXT NOT NULL,
|
||||
zoneInfo TEXT NOT NULL,
|
||||
notifyGameName TEXT,
|
||||
notifyGameTxtTitle TEXT,
|
||||
notifyGameSmallLogo INTEGER,
|
||||
notifyGameLargeLogo INTEGER,
|
||||
notifyClickParam TEXT
|
||||
)
|
||||
"""
|
||||
)
|
||||
|
||||
// 2. 删除旧表
|
||||
db.execSQL("DROP TABLE AcctGameInfo")
|
||||
|
||||
// 3. 重命名新表
|
||||
db.execSQL("ALTER TABLE AcctGameInfo_temp RENAME TO AcctGameInfo")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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?>
|
||||
}
|
||||
@ -12,17 +12,16 @@ 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.feature.entity.VipEntity
|
||||
import com.gh.gamecenter.gamedetail.accelerator.chain.AcceleratorClient
|
||||
import com.gh.gamecenter.gamedetail.accelerator.chain.AcceleratorValidator
|
||||
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.accelerator.repository.AcceleratorDataHolder
|
||||
import com.halo.assistant.member.MemberRepository
|
||||
import com.therouter.TheRouter
|
||||
|
||||
class GameDetailAcceleratorUiHelper(private val binding: DetailDownloadItemBinding) {
|
||||
@ -31,41 +30,54 @@ class GameDetailAcceleratorUiHelper(private val binding: DetailDownloadItemBindi
|
||||
|
||||
private var guideView: AcceleratorGuideView? = null
|
||||
|
||||
private lateinit var game: GameEntity
|
||||
val isGuideLayerShowing: Boolean
|
||||
get() = guideView?.isShowing ?: false
|
||||
|
||||
private var isGuideLayerShowing = false
|
||||
private val zoneList = arrayListOf<AcctGameInfo>()
|
||||
private var hasZoneListLoaded = false
|
||||
|
||||
private var _last: AcctGameInfo? = null
|
||||
private val last: AcctGameInfo?
|
||||
val last: AcctGameInfo?
|
||||
get() = _last
|
||||
|
||||
private val hasMultiZone: Boolean
|
||||
get() = game.serviceArea.size > 1
|
||||
get() = zoneList.size > 1
|
||||
|
||||
private val hasZone: Boolean
|
||||
get() = zoneList.isNotEmpty()
|
||||
|
||||
private val isVip: Boolean
|
||||
get() = AcceleratorDataHolder.instance.isVip
|
||||
get() = iAcceleratorProvider?.isVip() ?: false
|
||||
|
||||
val isNewUser: Boolean
|
||||
get() = AcceleratorDataHolder.instance.isNewUser
|
||||
get() = iAcceleratorProvider?.isNewUser() ?: false
|
||||
|
||||
private val isInit: Boolean
|
||||
get() = ::game.isInitialized
|
||||
private var canSpeed = false
|
||||
|
||||
val context: Context
|
||||
get() = binding.root.context
|
||||
var showSpeedUi = false
|
||||
|
||||
private var hasAnyAcctRecord = 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 -> {
|
||||
updateSpeedUi()
|
||||
|
||||
_game?.let {
|
||||
val acctGameInfo = state.acctGameInfo
|
||||
if (acctGameInfo is AcctGameInfo) {
|
||||
setCurrentAcctGameInfo(acctGameInfo)
|
||||
}
|
||||
updateSpeedUi()
|
||||
}
|
||||
}
|
||||
|
||||
is AccelerateState.Normal -> {
|
||||
updateSpeedUi()
|
||||
if (!state.isTokenExpired) {
|
||||
updateSpeedUi()
|
||||
}
|
||||
}
|
||||
|
||||
else -> Unit
|
||||
@ -74,78 +86,94 @@ class GameDetailAcceleratorUiHelper(private val binding: DetailDownloadItemBindi
|
||||
|
||||
override fun onProgress(progress: Int, curGamePkgName: String?, curGameZoneFlag: String?) = Unit
|
||||
|
||||
}
|
||||
|
||||
private val onDataHolderListener = object : AcceleratorDataHolder.OnDataHolderListener {
|
||||
override fun onVipStateChanged(vip: VipEntity) {
|
||||
showFreeTag()
|
||||
override fun onVipStatusChanged(isNewUser: Boolean, isVip: Boolean) {
|
||||
binding.ivFreeVipTag.visibleIf(
|
||||
showSpeedUi &&
|
||||
CheckLoginUtils.isLogin() &&
|
||||
isNewUser &&
|
||||
!isGuideLayerShowing
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fun initUi(game: GameEntity, context: Context) {
|
||||
this.game = game
|
||||
iAcceleratorProvider?.bindAccRelatedListener(game.getUniquePackageName() ?: "", accelerationListener)
|
||||
AcceleratorDataHolder.instance.addListener(onDataHolderListener)
|
||||
fun initSpeedUi(context: Context) {
|
||||
canSpeed = true
|
||||
|
||||
_game?.let {
|
||||
iAcceleratorProvider?.bindAccRelatedListener(it.getUniquePackageName() ?: "", accelerationListener)
|
||||
}
|
||||
|
||||
binding.vSpeedContent.setOnClickListener {
|
||||
startAccelerating(context, game, false)
|
||||
_game?.let { game ->
|
||||
checkDataReady {
|
||||
startAccelerating(context, game, false)
|
||||
}
|
||||
}
|
||||
}
|
||||
binding.vMoreZone.setOnClickListener {
|
||||
showZoneList(context, game)
|
||||
_game?.let { game ->
|
||||
checkDataReady {
|
||||
showZoneList(context, game)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
binding.tvStopSpeed.setOnClickListener {
|
||||
SensorsBridge.trackNetworkAccelerationOtherButtonClick(
|
||||
game.getUniquePackageName() ?: "",
|
||||
game.id,
|
||||
game.name ?: "",
|
||||
AcceleratorDataHolder.instance.memberType,
|
||||
BUTTON_NAME_STOP_ACCELERATOR,
|
||||
SOURCE_ENTRANCE_GAME_DETAIL
|
||||
)
|
||||
_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
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
AcceleratorDialogFragment.show(
|
||||
SPEED_STOP, game.getUniquePackageName() ?: "", game.id, game.name ?: "",
|
||||
SOURCE_ENTRANCE_GAME_DETAIL, context
|
||||
)
|
||||
}
|
||||
|
||||
binding.tvEnterGame.setOnClickListener {
|
||||
SensorsBridge.trackNetworkAccelerationOtherButtonClick(
|
||||
game.getUniquePackageName() ?: "",
|
||||
game.id,
|
||||
game.name ?: "",
|
||||
AcceleratorDataHolder.instance.memberType,
|
||||
BUTTON_NAME_ENTER_GAME,
|
||||
SOURCE_ENTRANCE_GAME_DETAIL
|
||||
)
|
||||
PackageLauncher.launchApp(context, game, game.getUniquePackageName())
|
||||
_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 (!isInit || !showSpeedUi) {
|
||||
if (!showSpeedUi) {
|
||||
return
|
||||
}
|
||||
|
||||
val isCurrentGameAccelerating = AcceleratorDataHolder.instance.isCurrentGameAccelerating(game.id)
|
||||
|
||||
when {
|
||||
isCurrentGameAccelerating -> {// 如果当前游戏正处于加速状态,则需要隐藏当前下载按钮
|
||||
binding.detailProgressbar.goneIf(true)
|
||||
}
|
||||
|
||||
binding.detailProgressbar.text == "更新" -> { // 游戏没有处于加速状态,如果 下载按钮为 “更新” 状态,则需要显示出来
|
||||
binding.detailProgressbar.goneIf(false)
|
||||
}
|
||||
}
|
||||
|
||||
binding.clSpeed.goneIf(isCurrentGameAccelerating)
|
||||
binding.gAccelerating.goneIf(!isCurrentGameAccelerating)
|
||||
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)
|
||||
showFreeTag()
|
||||
binding.ivFreeVipTag.visibleIf(
|
||||
showSpeedUi &&
|
||||
CheckLoginUtils.isLogin() &&
|
||||
isNewUser &&
|
||||
!isGuideLayerShowing
|
||||
)
|
||||
binding.tvSpeed.text = if (hasMultiZone) {
|
||||
last?.zoneName
|
||||
} else {
|
||||
@ -153,81 +181,67 @@ class GameDetailAcceleratorUiHelper(private val binding: DetailDownloadItemBindi
|
||||
} ?: R.string.network_acceleration.toResString()
|
||||
}
|
||||
|
||||
fun checkIfShowSpeedUi(show: Boolean) {
|
||||
if (!isInit) {
|
||||
return
|
||||
}
|
||||
showSpeedUi = show
|
||||
/**
|
||||
* 在这个方法里确定是否需要展示 加速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))
|
||||
// 是否需要展示弹窗
|
||||
showGuideLayerIfNeed()
|
||||
updateSpeedUi()
|
||||
}
|
||||
}
|
||||
|
||||
private fun showFreeTag() {
|
||||
binding.ivFreeVipTag.visibleIf(
|
||||
showSpeedUi && last == null && !isGuideLayerShowing &&
|
||||
(!CheckLoginUtils.isLogin() || isNewUser)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* 需要同时满足这四个条件,才需要判断是否需要展示弹窗
|
||||
*/
|
||||
var isButtonSizeDetermined = false // 底部下载按钮尺寸是否已确定
|
||||
private var isLastLoaded = false // 本地存在区服记录(用户点击过选择区服/启动加速)
|
||||
private var hasAnyAcctRecordLoaded = false // 已获取:是否存在加速成功的游戏记录
|
||||
private var showSpeedUi = false // 显示加速器ui
|
||||
fun showGuideLayerIfNeed() {
|
||||
if (isButtonSizeDetermined && hasAnyAcctRecordLoaded && isLastLoaded && showSpeedUi) {
|
||||
if (shouldShowGuideLayer()) {
|
||||
isGuideLayerShowing = true
|
||||
if (CheckLoginUtils.isLogin()) {
|
||||
if (!hasShow()) {
|
||||
// 优先显示弹窗
|
||||
binding.ivFreeVipTag.visibleIf(false)
|
||||
showGuideLayer(context)
|
||||
}
|
||||
} else {
|
||||
// 未登录
|
||||
binding.ivFreeVipTag.visibleIf(false)
|
||||
showGuideLayer(context)
|
||||
}
|
||||
showFreeTag()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private fun shouldShowGuideLayer() =
|
||||
!SPUtils.getBoolean(Constants.SP_HAS_SHOW_ACCELERATION_GUIDE_LAYER) &&
|
||||
!hasAnyAcctRecord &&
|
||||
last == null &&
|
||||
!isGuideLayerShowing
|
||||
|
||||
private fun showGuideLayer(context: Context) {
|
||||
binding.root.post {
|
||||
val uiListener = object : OnAcceleratorListener {
|
||||
override fun onStartAccelerator() {
|
||||
startAccelerating(context, game, true)
|
||||
}
|
||||
if (!hasShow()) {
|
||||
binding.root.post {
|
||||
val uiListener = object : OnAcceleratorListener {
|
||||
override fun onStartAccelerator() {
|
||||
_game?.let {
|
||||
startAccelerating(context, it, true)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onGuideLayerDismiss() {
|
||||
isGuideLayerShowing = false
|
||||
showFreeTag()
|
||||
}
|
||||
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) {
|
||||
SensorsBridge.trackNetworkAccelerationGuidanceDiagramShow(
|
||||
game.getUniquePackageName() ?: "",
|
||||
game.id,
|
||||
game.name ?: ""
|
||||
)
|
||||
guideView?.show(binding.clSpeedContainer, context, uiListener::onStartAccelerator)
|
||||
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 {
|
||||
@ -240,13 +254,21 @@ class GameDetailAcceleratorUiHelper(private val binding: DetailDownloadItemBindi
|
||||
}
|
||||
}
|
||||
|
||||
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()) {
|
||||
if (isInvalidClick() || !hasZone) {
|
||||
return
|
||||
}
|
||||
val lastAcctGameInfo = last
|
||||
|
||||
val memberType = AcceleratorDataHolder.instance.memberType
|
||||
val memberType = if (CheckLoginUtils.isLogin()) {
|
||||
iAcceleratorProvider?.getMemberType() ?: ""
|
||||
} else {
|
||||
MEMBER_TYPE_NOT_LOGIN
|
||||
}
|
||||
val districtServer = when {
|
||||
hasMultiZone && lastAcctGameInfo != null -> lastAcctGameInfo.zoneName
|
||||
hasMultiZone -> DISTRICT_SERVER_EMPTY
|
||||
@ -264,44 +286,34 @@ class GameDetailAcceleratorUiHelper(private val binding: DetailDownloadItemBindi
|
||||
|
||||
when {
|
||||
lastAcctGameInfo != null ->
|
||||
doStartAccelerating(context, game, lastAcctGameInfo.zoneInfo)
|
||||
|
||||
hasMultiZone -> context.ifLogin("[网络加速]") {
|
||||
AcceleratorZoneDialogFragment.show(
|
||||
context, last?.zoneInfo?.id, game.serviceArea, game,
|
||||
SOURCE_ENTRANCE_GAME_DETAIL
|
||||
)
|
||||
}
|
||||
doStartAccelerating(context, game, lastAcctGameInfo)
|
||||
|
||||
hasMultiZone -> AcceleratorZoneDialogFragment.show(context, zoneList, game)
|
||||
else -> {
|
||||
val gameInfo = game.serviceArea.firstOrNull() ?: AcctGameInfo.ZoneInfo(0)
|
||||
val gameInfo = zoneList.firstOrNull() ?: AcctGameInfo("", AcctGameInfo.ZoneInfo(0))
|
||||
doStartAccelerating(context, game, gameInfo)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun showZoneList(context: Context, game: GameEntity) {
|
||||
if (isInvalidClick()) {
|
||||
if (isInvalidClick() || !hasZone) {
|
||||
return
|
||||
}
|
||||
context.ifLogin("[网络加速]") {
|
||||
AcceleratorZoneDialogFragment.show(
|
||||
context, last?.zoneInfo?.id, game.serviceArea, game,
|
||||
SOURCE_ENTRANCE_GAME_DETAIL
|
||||
)
|
||||
}
|
||||
AcceleratorZoneDialogFragment.show(context, zoneList, game)
|
||||
|
||||
}
|
||||
|
||||
private var clickTime = 0L
|
||||
|
||||
private fun doStartAccelerating(context: Context, game: GameEntity, zoneInfo: AcctGameInfo.ZoneInfo) {
|
||||
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, zoneInfo, game, true, hasMultiZone,
|
||||
context, acctGameInfo, game, true, hasMultiZone,
|
||||
SOURCE_ENTRANCE_GAME_DETAIL,
|
||||
)
|
||||
}
|
||||
@ -309,18 +321,27 @@ class GameDetailAcceleratorUiHelper(private val binding: DetailDownloadItemBindi
|
||||
}
|
||||
|
||||
fun setCurrentAcctGameInfo(acctGameInfo: AcctGameInfo?) {
|
||||
isLastLoaded = true
|
||||
if (last?.zoneInfo?.id != acctGameInfo?.zoneInfo?.id) {
|
||||
_last = acctGameInfo
|
||||
_last = acctGameInfo
|
||||
if (hasZoneListLoaded) {
|
||||
updateSpeedUi()
|
||||
}
|
||||
showGuideLayerIfNeed()
|
||||
|
||||
}
|
||||
|
||||
fun setHasAnyAcctRecord(hasAnyAcctRecord: Boolean) {
|
||||
hasAnyAcctRecordLoaded = true
|
||||
this.hasAnyAcctRecord = hasAnyAcctRecord
|
||||
showGuideLayerIfNeed()
|
||||
/**
|
||||
* 第一次调用 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 {
|
||||
@ -334,26 +355,38 @@ class GameDetailAcceleratorUiHelper(private val binding: DetailDownloadItemBindi
|
||||
return false
|
||||
}
|
||||
|
||||
fun clear() {
|
||||
iAcceleratorProvider?.unBindAccRelatedListener(accelerationListener)
|
||||
AcceleratorDataHolder.instance.removeListener(onDataHolderListener)
|
||||
guideView?.dismiss()
|
||||
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 = "未登录"
|
||||
|
||||
|
||||
const val DISTRICT_SERVER_EMPTY = "空"
|
||||
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 SOURCE_ENTRANCE_SEARCH = "搜索页"
|
||||
const val SOURCE_ENTRANCE_RECENTLY_PLAYED = "最近在玩"
|
||||
const val BUTTON_NAME_ENTER_GAME = "进入游戏"
|
||||
const val BUTTON_NAME_STOP_ACCELERATOR = "停止加速"
|
||||
|
||||
|
||||
@ -2,10 +2,7 @@ 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.AcceleratorDialogFragment
|
||||
import com.gh.gamecenter.gamedetail.accelerator.dialog.AcceleratorDialogFragment.Companion.SPEED_CURRENT_ACCELERATING
|
||||
import com.gh.gamecenter.gamedetail.accelerator.dialog.AcceleratorReplaceDialogFragment
|
||||
import com.halo.assistant.accelerator.repository.AcceleratorDataHolder
|
||||
import com.therouter.TheRouter
|
||||
|
||||
class AcceleratorStateInterceptor : AcceleratorValidator.Interceptor {
|
||||
@ -19,30 +16,18 @@ class AcceleratorStateInterceptor : AcceleratorValidator.Interceptor {
|
||||
val isAccelerating = iAcceleratorProvider?.isCurAccSuccess() ?: false
|
||||
if (isAccelerating) {
|
||||
val game = request.game
|
||||
val isCurrentAccelerating = AcceleratorDataHolder.instance.isCurrentGameAccelerating(game.id)
|
||||
if (isCurrentAccelerating) {
|
||||
AcceleratorDialogFragment.show(
|
||||
SPEED_CURRENT_ACCELERATING,
|
||||
game.getUniquePackageName() ?: "",
|
||||
game.id,
|
||||
game.name ?: "",
|
||||
request.sourceEntrance,
|
||||
context
|
||||
)
|
||||
} else {
|
||||
AcceleratorReplaceDialogFragment.show(
|
||||
context,
|
||||
game.getUniquePackageName() ?: "",
|
||||
game.id,
|
||||
game.name ?: "",
|
||||
request.sourceEntrance
|
||||
) {
|
||||
if (chain.isValidContext(context)) {
|
||||
listener?.finished(context)
|
||||
}
|
||||
AcceleratorReplaceDialogFragment.show(
|
||||
context,
|
||||
game.getUniquePackageName() ?: "",
|
||||
game.id,
|
||||
game.name ?: "",
|
||||
request.sourceEntrance
|
||||
) {
|
||||
if (chain.isValidContext(context)) {
|
||||
listener?.finished(context)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
} else {
|
||||
chain.proceed(context, request, listener)
|
||||
}
|
||||
|
||||
@ -10,6 +10,7 @@ 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
|
||||
@ -55,11 +56,6 @@ class AcceleratorDialogFragment : BaseDialogFragment() {
|
||||
|
||||
SPEED_STOP -> StopSpeedUi()
|
||||
SPEED_NOT_INSTALLED -> NotInstalledUi()
|
||||
SPEED_CURRENT_ACCELERATING -> {
|
||||
SensorsBridge.trackStopAcceleratingDialogShow(gameId, gameName, pkgName)
|
||||
CurrentAcceleratingUi()
|
||||
}
|
||||
|
||||
else -> throw IllegalArgumentException("请传递正确的参数 SpeedType !")
|
||||
}
|
||||
}
|
||||
@ -106,7 +102,8 @@ class AcceleratorDialogFragment : BaseDialogFragment() {
|
||||
sourceEntrance
|
||||
)
|
||||
SensorsBridge.trackMyAssetsPageShow(pkgName, gameId, gameName, sourceEntrance)
|
||||
DirectUtils.navigateToMyAssetsPage(requireContext(), sourceEntrance)
|
||||
val intent = WebActivity.getMyAssetsIntent(requireContext())
|
||||
startActivity(intent)
|
||||
}
|
||||
|
||||
is SpeedFailureUi -> {
|
||||
@ -116,7 +113,7 @@ class AcceleratorDialogFragment : BaseDialogFragment() {
|
||||
}
|
||||
}
|
||||
|
||||
is StopSpeedUi, is CurrentAcceleratingUi -> {
|
||||
is StopSpeedUi -> {
|
||||
TheRouter.get(IAcceleratorProvider::class.java)?.stopQyGameAccelerate()
|
||||
}
|
||||
|
||||
@ -137,7 +134,6 @@ class AcceleratorDialogFragment : BaseDialogFragment() {
|
||||
const val SPEED_START_FAILURE = 2
|
||||
const val SPEED_STOP = 3
|
||||
const val SPEED_NOT_INSTALLED = 4
|
||||
const val SPEED_CURRENT_ACCELERATING = 5
|
||||
|
||||
fun show(
|
||||
@SpeedType type: Int,
|
||||
@ -167,7 +163,7 @@ class AcceleratorDialogFragment : BaseDialogFragment() {
|
||||
}
|
||||
}
|
||||
|
||||
@IntDef(SPEED_ENABLE_VIP, SPEED_START_FAILURE, SPEED_STOP, SPEED_NOT_INSTALLED, SPEED_CURRENT_ACCELERATING)
|
||||
@IntDef(SPEED_ENABLE_VIP, SPEED_START_FAILURE, SPEED_STOP, SPEED_NOT_INSTALLED)
|
||||
@Retention(AnnotationRetention.SOURCE)
|
||||
annotation class SpeedType
|
||||
|
||||
@ -242,19 +238,4 @@ class AcceleratorDialogFragment : BaseDialogFragment() {
|
||||
override val submitResId: Int
|
||||
get() = R.string.dialog_hint_confirm
|
||||
}
|
||||
|
||||
class CurrentAcceleratingUi : SpeedDialogUiHelper() {
|
||||
override val contentResId: Int
|
||||
get() = R.string.speed_current_game_accelerating
|
||||
|
||||
override val isShowCancelButton: Boolean
|
||||
get() = true
|
||||
|
||||
override val submitResId: Int
|
||||
get() = R.string.stop_speed
|
||||
|
||||
override val cancelResId: Int
|
||||
get() = R.string.cancel
|
||||
|
||||
}
|
||||
}
|
||||
@ -13,20 +13,26 @@ 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.constant.EntranceConsts
|
||||
import com.gh.gamecenter.common.utils.*
|
||||
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.AcceleratorZoneViewModel
|
||||
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.halo.assistant.accelerator.repository.AcceleratorDataHolder
|
||||
import com.therouter.TheRouter
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
class AcceleratorZoneDialogFragment : BaseBottomDialogFragment<DialogFragmentAcceleratorZoneBinding>() {
|
||||
@ -35,31 +41,21 @@ class AcceleratorZoneDialogFragment : BaseBottomDialogFragment<DialogFragmentAcc
|
||||
|
||||
private lateinit var adapter: ZoneAdapter
|
||||
|
||||
private var sourceEntrance = ""
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
sourceEntrance = arguments?.getString(EntranceConsts.KEY_SOURCE_ENTRANCE) ?: ""
|
||||
}
|
||||
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
val data =
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||
arguments?.getParcelableArrayList(EntranceConsts.KEY_DATA, AcctGameInfo.ZoneInfo::class.java)
|
||||
arguments?.getParcelableArrayList(KEY_DATA, AcctGameInfo::class.java)
|
||||
} else {
|
||||
arguments?.getParcelableArrayList(EntranceConsts.KEY_DATA)
|
||||
} ?: listOf<AcctGameInfo.ZoneInfo>()
|
||||
arguments?.getParcelableArrayList(KEY_DATA)
|
||||
} ?: listOf<AcctGameInfo>()
|
||||
|
||||
val game = arguments?.getParcelable<GameEntity>(EntranceConsts.KEY_GAME)!!
|
||||
val selectedId = arguments?.getInt(KEY_SELECTED_ID) ?: -1
|
||||
val game = arguments?.getParcelable<GameEntity>(KEY_GAME)!!
|
||||
|
||||
mBinding.titleView.setOnRightClickListener {
|
||||
dismiss()
|
||||
}
|
||||
|
||||
adapter = ZoneAdapter {
|
||||
startAccelerating(game, it)
|
||||
dismiss()
|
||||
@ -67,38 +63,39 @@ class AcceleratorZoneDialogFragment : BaseBottomDialogFragment<DialogFragmentAcc
|
||||
mBinding.recyclerZone.layoutManager = GridLayoutManager(requireContext(), 3)
|
||||
mBinding.recyclerZone.addItemDecoration(MyDecorationItem())
|
||||
mBinding.recyclerZone.adapter = adapter
|
||||
adapter.setData(selectedId, data)
|
||||
adapter.submitList(data)
|
||||
}
|
||||
|
||||
private fun startAccelerating(game: GameEntity, zoneInfo: AcctGameInfo.ZoneInfo) {
|
||||
private fun startAccelerating(game: GameEntity, acctGameInfo: AcctGameInfo) {
|
||||
context?.let {
|
||||
viewModel.useCase.insertAcctGameInfo(AcctGameInfo(game.id, game.getUniquePackageName() ?: "", zoneInfo))
|
||||
val acceleratorDataHolder = AcceleratorDataHolder.instance
|
||||
val memberType = acceleratorDataHolder.memberType
|
||||
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,
|
||||
zoneInfo.cnName ?: "",
|
||||
acctGameInfo.zoneInfo.cnName ?: "",
|
||||
SCENE_TYPE_NO_GUIDE_LAYER,
|
||||
sourceEntrance
|
||||
SOURCE_ENTRANCE_GAME_DETAIL
|
||||
)
|
||||
|
||||
val isVip = acceleratorDataHolder.isVip
|
||||
val isNewUser = acceleratorDataHolder.isNewUser
|
||||
val request = AcceleratorValidator.Request(isVip, isNewUser, game, sourceEntrance)
|
||||
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,
|
||||
zoneInfo,
|
||||
game,
|
||||
isNeedRecord = false,
|
||||
hasMultiZone = true,
|
||||
sourceEntrance = sourceEntrance
|
||||
context, acctGameInfo, game, isNeedRecord = true, hasMultiZone = true,
|
||||
sourceEntrance = SOURCE_ENTRANCE_GAME_DETAIL
|
||||
)
|
||||
}
|
||||
|
||||
@ -108,14 +105,9 @@ class AcceleratorZoneDialogFragment : BaseBottomDialogFragment<DialogFragmentAcc
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val KEY_SELECTED_ID = "key_selected_id"
|
||||
fun show(
|
||||
context: Context,
|
||||
selectedId: Int? = null,
|
||||
data: List<AcctGameInfo.ZoneInfo>,
|
||||
game: GameEntity,
|
||||
sourceEntrance: String
|
||||
) {
|
||||
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 {
|
||||
@ -123,10 +115,8 @@ class AcceleratorZoneDialogFragment : BaseBottomDialogFragment<DialogFragmentAcc
|
||||
}?.let {
|
||||
val fragment = AcceleratorZoneDialogFragment().apply {
|
||||
arguments = Bundle().apply {
|
||||
putParcelableArrayList(EntranceConsts.KEY_DATA, data.toArrayList())
|
||||
putParcelable(EntranceConsts.KEY_GAME, game)
|
||||
putInt(KEY_SELECTED_ID, selectedId ?: -1)
|
||||
putString(EntranceConsts.KEY_SOURCE_ENTRANCE, sourceEntrance)
|
||||
putParcelableArrayList(KEY_DATA, data)
|
||||
putParcelable(KEY_GAME, game)
|
||||
}
|
||||
}
|
||||
fragment.show(it, fragment::class.java.simpleName)
|
||||
@ -150,15 +140,10 @@ class AcceleratorZoneDialogFragment : BaseBottomDialogFragment<DialogFragmentAcc
|
||||
}
|
||||
}
|
||||
|
||||
class ZoneAdapter(private val click: (AcctGameInfo.ZoneInfo) -> Unit) :
|
||||
ListAdapter<AcctGameInfo.ZoneInfo, ZoneAdapter.ZoneViewHolder>(diffCallback) {
|
||||
class ZoneAdapter(private val click: (AcctGameInfo) -> Unit) :
|
||||
ListAdapter<AcctGameInfo, ZoneAdapter.ZoneViewHolder>(diffCallback) {
|
||||
|
||||
private var selectedId = -1
|
||||
|
||||
fun setData(selectedId: Int, data: List<AcctGameInfo.ZoneInfo>) {
|
||||
this.selectedId = selectedId
|
||||
submitList(data)
|
||||
}
|
||||
private var selectedPosition = -1
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ZoneViewHolder {
|
||||
return ZoneViewHolder(parent.toBinding())
|
||||
@ -174,15 +159,15 @@ class AcceleratorZoneDialogFragment : BaseBottomDialogFragment<DialogFragmentAcc
|
||||
|
||||
override fun onBindViewHolder(holder: ZoneViewHolder, position: Int) {
|
||||
val item = getItem(position) ?: return
|
||||
updateSelectedState(holder, item.id)
|
||||
holder.binding.tvName.text = item.cnName
|
||||
updateSelectedState(holder, position)
|
||||
holder.binding.tvName.text = item.zoneName
|
||||
holder.itemView.setOnClickListener {
|
||||
click(item)
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateSelectedState(holder: ZoneViewHolder, zoneId: Int) {
|
||||
val (textColorResId, backgroundResId) = if (selectedId == zoneId) {
|
||||
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
|
||||
@ -193,15 +178,14 @@ class AcceleratorZoneDialogFragment : BaseBottomDialogFragment<DialogFragmentAcc
|
||||
|
||||
companion object {
|
||||
|
||||
private val diffCallback = object : DiffUtil.ItemCallback<AcctGameInfo.ZoneInfo>() {
|
||||
override fun areItemsTheSame(oldItem: AcctGameInfo.ZoneInfo, newItem: AcctGameInfo.ZoneInfo): Boolean {
|
||||
return oldItem.id == newItem.id
|
||||
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.ZoneInfo,
|
||||
newItem: AcctGameInfo.ZoneInfo
|
||||
): Boolean {
|
||||
override fun areContentsTheSame(oldItem: AcctGameInfo, newItem: AcctGameInfo): Boolean {
|
||||
return oldItem == newItem
|
||||
}
|
||||
|
||||
|
||||
@ -22,17 +22,12 @@ 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.AcctRecord
|
||||
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_ENABLE_VIP
|
||||
import com.gh.gamecenter.gamedetail.accelerator.dialog.AcceleratorDialogFragment.Companion.SPEED_START_FAILURE
|
||||
import com.gh.gamecenter.livedata.EventObserver
|
||||
import com.gh.gamecenter.login.user.UserManager
|
||||
import com.gh.gamecenter.login.user.UserRepository
|
||||
import com.halo.assistant.accelerator.repository.AcceleratorDataHolder
|
||||
import com.therouter.TheRouter
|
||||
import io.reactivex.disposables.CompositeDisposable
|
||||
import kotlin.math.max
|
||||
@ -43,7 +38,7 @@ class StartingAcceleratorDialogFragment : BaseDialogFragment() {
|
||||
|
||||
private lateinit var binding: DialogFragmentStartingAcceleratorBinding
|
||||
|
||||
private lateinit var zoneInfo: AcctGameInfo.ZoneInfo
|
||||
private lateinit var acctGameInfo: AcctGameInfo
|
||||
private lateinit var game: GameEntity
|
||||
private var isNeedRecord: Boolean = false
|
||||
private var iAcceleratorProvider: IAcceleratorProvider? = null
|
||||
@ -56,8 +51,6 @@ class StartingAcceleratorDialogFragment : BaseDialogFragment() {
|
||||
|
||||
private var refreshTokenCount = 0
|
||||
|
||||
private val acceleratorDataHolder = AcceleratorDataHolder.instance
|
||||
|
||||
private val accelerationListener = object : OnAccelerateListener {
|
||||
override fun onStateChanged(state: AccelerateState) {
|
||||
// 如果状态能成功回,则移除计时
|
||||
@ -67,8 +60,10 @@ class StartingAcceleratorDialogFragment : BaseDialogFragment() {
|
||||
ToastUtils.showToast("加速成功")
|
||||
// 加速成功,启动游戏
|
||||
PackageLauncher.launchApp(requireContext(), game, game.getUniquePackageName())
|
||||
// 记录加速成功的游戏
|
||||
viewModel.useCase.recordAcctGameInfo(game, zoneInfo, hasMultiZone)
|
||||
// 记录加速记录
|
||||
if (isNeedRecord) {
|
||||
viewModel.useCase.recordAcctGameInfo(game.id, acctGameInfo, hasMultiZone)
|
||||
}
|
||||
|
||||
trackNetworkAccelerationStartupResult("成功")
|
||||
dismissAllowingStateLoss()
|
||||
@ -89,26 +84,14 @@ class StartingAcceleratorDialogFragment : BaseDialogFragment() {
|
||||
sourceEntrance,
|
||||
it
|
||||
)
|
||||
// 加速失败,上传奇游加速器log
|
||||
unloadAcceleratorErrorLog(game)
|
||||
}
|
||||
}
|
||||
|
||||
if (state.isPermissionExpired) {
|
||||
// 加速会员过期,刷新本地vip状态
|
||||
val userId = UserManager.getInstance().userId
|
||||
UserRepository.getInstance().refreshVipStatus(userId, true)
|
||||
// 加速失败,上传奇游加速器log
|
||||
unloadAcceleratorErrorLog(game)
|
||||
}
|
||||
|
||||
dismissAllowingStateLoss()
|
||||
trackNetworkAccelerationStartupResult("失败(${state.code})")
|
||||
}
|
||||
}
|
||||
|
||||
is AccelerateState.Normal -> {
|
||||
|
||||
if (state.isTokenExpired || state.isTokenEmpty) {
|
||||
// token过期/登录时token设置失败,在此获取token并重新启动加速(最多重试三次)
|
||||
if (refreshTokenCount < REFRESH_TOKEN_MAX_COUNT) {
|
||||
@ -127,10 +110,8 @@ class StartingAcceleratorDialogFragment : BaseDialogFragment() {
|
||||
binding.tvProgress.text = getString(R.string.accelerating_with_progress, "$progress")
|
||||
}
|
||||
|
||||
}
|
||||
override fun onVipStatusChanged(isNewUser: Boolean, isVip: Boolean) = Unit
|
||||
|
||||
private fun unloadAcceleratorErrorLog(game: GameEntity) {
|
||||
viewModel.useCase.unloadAcceleratorErrorLog(game)
|
||||
}
|
||||
|
||||
private fun trackNetworkAccelerationStartupResult(result: String) {
|
||||
@ -138,8 +119,8 @@ class StartingAcceleratorDialogFragment : BaseDialogFragment() {
|
||||
game.getUniquePackageName() ?: "",
|
||||
game.id,
|
||||
game.name ?: "",
|
||||
acceleratorDataHolder.memberType,
|
||||
if (hasMultiZone) zoneInfo.cnName ?: "" else DISTRICT_SERVER_HAVA,
|
||||
iAcceleratorProvider?.getMemberType() ?: "",
|
||||
if (hasMultiZone) acctGameInfo.zoneInfo.cnName ?: "" else DISTRICT_SERVER_HAVA,
|
||||
result,
|
||||
sourceEntrance
|
||||
)
|
||||
@ -156,7 +137,7 @@ class StartingAcceleratorDialogFragment : BaseDialogFragment() {
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
iAcceleratorProvider = TheRouter.get(IAcceleratorProvider::class.java)
|
||||
zoneInfo = arguments?.getParcelable(EntranceConsts.KEY_ACCT_ZONE_INFO)!!
|
||||
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
|
||||
@ -179,8 +160,8 @@ class StartingAcceleratorDialogFragment : BaseDialogFragment() {
|
||||
|
||||
binding.tvProgress.text = getString(R.string.accelerating_with_progress, "0")
|
||||
iAcceleratorProvider?.bindAccRelatedListener("", accelerationListener)
|
||||
val isVip = acceleratorDataHolder.isVip
|
||||
val isNewUser = acceleratorDataHolder.isNewUser
|
||||
val isVip = iAcceleratorProvider?.isVip() ?: false
|
||||
val isNewUser = iAcceleratorProvider?.isNewUser() ?: false
|
||||
if (isNewUser && !isVip) {
|
||||
// 新用户,并且还不是vip
|
||||
viewModel.rechargeTrial()
|
||||
@ -218,21 +199,18 @@ class StartingAcceleratorDialogFragment : BaseDialogFragment() {
|
||||
// 15s以后,不管成功还是失败,都要关闭当前页面
|
||||
dismissAllowingStateLoss()
|
||||
}, TIME_OUT)
|
||||
AcceleratorDataHolder.instance.acctGameRecord = AcctRecord(game.id, game, zoneInfo, hasMultiZone, 0)
|
||||
iAcceleratorProvider?.startQyGameAccelerate(game.id, game.getUniquePackageName() ?: "", zoneInfo)
|
||||
viewModel.useCase.setLastAcctGameRecord(game)
|
||||
iAcceleratorProvider?.startQyGameAccelerate(acctGameInfo)
|
||||
if (isNeedRecord) {
|
||||
viewModel.useCase.insertAcctGameInfo(
|
||||
AcctGameInfo(game.id, game.getUniquePackageName() ?: "", zoneInfo)
|
||||
)
|
||||
viewModel.useCase.insertAcctGameInfo(acctGameInfo)
|
||||
}
|
||||
if (refreshTokenCount == 0) {
|
||||
|
||||
SensorsBridge.trackNetworkAccelerationStartup(
|
||||
game.getUniquePackageName() ?: "",
|
||||
game.id,
|
||||
game.name ?: "",
|
||||
acceleratorDataHolder.memberType,
|
||||
if (hasMultiZone) zoneInfo.cnName ?: "" else DISTRICT_SERVER_HAVA,
|
||||
iAcceleratorProvider?.getMemberType() ?: "",
|
||||
if (hasMultiZone) acctGameInfo.zoneInfo.cnName ?: "" else DISTRICT_SERVER_HAVA,
|
||||
sourceEntrance
|
||||
)
|
||||
}
|
||||
@ -253,7 +231,7 @@ class StartingAcceleratorDialogFragment : BaseDialogFragment() {
|
||||
|
||||
fun show(
|
||||
context: Context,
|
||||
zoneInfo: AcctGameInfo.ZoneInfo,
|
||||
acctGameInfo: AcctGameInfo,
|
||||
game: GameEntity,
|
||||
isNeedRecord: Boolean,
|
||||
hasMultiZone: Boolean,
|
||||
@ -266,7 +244,7 @@ class StartingAcceleratorDialogFragment : BaseDialogFragment() {
|
||||
}?.let {
|
||||
val fragment = StartingAcceleratorDialogFragment().apply {
|
||||
arguments = Bundle().apply {
|
||||
putParcelable(EntranceConsts.KEY_ACCT_ZONE_INFO, zoneInfo)
|
||||
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)
|
||||
|
||||
@ -1,125 +1,81 @@
|
||||
package com.gh.gamecenter.gamedetail.cloudarchive
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import android.view.inputmethod.EditorInfo
|
||||
import androidx.core.os.bundleOf
|
||||
import com.gh.common.util.NewFlatLogUtils
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.catalog.SpecialCatalogFragment
|
||||
import com.gh.gamecenter.cloudarchive.CloudArchiveManagerActivity
|
||||
import com.gh.gamecenter.common.base.GlobalActivityManager
|
||||
import com.gh.gamecenter.common.base.fragment.LazyFragment
|
||||
import com.gh.gamecenter.common.constant.EntranceConsts
|
||||
import com.gh.gamecenter.common.json.json
|
||||
import com.gh.gamecenter.common.utils.*
|
||||
import com.gh.gamecenter.databinding.FragmentCloudArchiveAlBinding
|
||||
import com.gh.gamecenter.common.utils.goneIf
|
||||
import com.gh.gamecenter.common.utils.toResString
|
||||
import com.gh.gamecenter.databinding.FragmentCloudArchiveBinding
|
||||
import com.gh.gamecenter.feature.entity.GameEntity
|
||||
|
||||
class CloudArchiveFragment : LazyFragment() {
|
||||
|
||||
private var mUseAlternativeLayout = false
|
||||
private var mGameEntity: GameEntity? = null
|
||||
private var mBinding: FragmentCloudArchiveBinding? = null
|
||||
private var mAlternativeBinding: FragmentCloudArchiveAlBinding? = null
|
||||
private var mSearchFragment: CloudArchiveListFragment? = null
|
||||
private var mNormalFragment: CloudArchiveListFragment? = null
|
||||
private var mIsSearch = false
|
||||
private var mOrderList =
|
||||
listOf(CloudArchiveListViewModel.SortType.NEWEST, CloudArchiveListViewModel.SortType.HOTTEST)
|
||||
|
||||
private val searchBarBinding
|
||||
get() = if (mUseAlternativeLayout) mAlternativeBinding?.searchBar else mBinding?.searchBar
|
||||
|
||||
private val orderSfv
|
||||
get() = if (mUseAlternativeLayout) mAlternativeBinding?.orderSfv else mBinding?.orderSfv
|
||||
|
||||
private val archiveManageTv
|
||||
get() = if (mUseAlternativeLayout) mAlternativeBinding?.archiveManageTv else mBinding?.archiveManageTv
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
mUseAlternativeLayout = arguments?.getBoolean(EntranceConsts.KEY_USE_ALTERNATIVE_LAYOUT) ?: false
|
||||
super.onCreate(savedInstanceState)
|
||||
}
|
||||
|
||||
override fun getRealLayoutId() =
|
||||
if (mUseAlternativeLayout) R.layout.fragment_cloud_archive_al else R.layout.fragment_cloud_archive
|
||||
override fun getRealLayoutId() = R.layout.fragment_cloud_archive
|
||||
|
||||
override fun onRealLayoutInflated(inflatedView: View) {
|
||||
if (mUseAlternativeLayout) {
|
||||
mAlternativeBinding = FragmentCloudArchiveAlBinding.bind(inflatedView)
|
||||
} else {
|
||||
mBinding = FragmentCloudArchiveBinding.bind(inflatedView)
|
||||
}
|
||||
mBinding = FragmentCloudArchiveBinding.bind(inflatedView)
|
||||
}
|
||||
|
||||
override fun onFragmentFirstVisible() {
|
||||
mGameEntity = arguments?.getParcelable(EntranceConsts.KEY_GAME_ENTITY)
|
||||
mGameEntity = arguments?.getParcelable(EntranceConsts.KEY_GAME)
|
||||
super.onFragmentFirstVisible()
|
||||
if (mUseAlternativeLayout) {
|
||||
requireActivity().updateStatusBarColor(com.gh.gamecenter.common.R.color.ui_surface, com.gh.gamecenter.common.R.color.ui_surface)
|
||||
}
|
||||
changeContentFragment()
|
||||
|
||||
SensorsBridge.trackEvent("CloudSavePageView", json {
|
||||
"game_id" to mGameEntity?.id
|
||||
"game_name" to mGameEntity?.name
|
||||
"last_page_name" to GlobalActivityManager.getLastPageEntity().pageName
|
||||
"last_page_id" to GlobalActivityManager.getLastPageEntity().pageId
|
||||
})
|
||||
}
|
||||
|
||||
override fun inflateRealView() {
|
||||
super.inflateRealView()
|
||||
mAlternativeBinding?.run {
|
||||
reuseToolbar.backBtn.setOnClickListener {
|
||||
requireActivity().onBackPressed()
|
||||
}
|
||||
reuseToolbar.normalTitle.run {
|
||||
text = "${mGameEntity?.name}-云存档"
|
||||
marqueeOnce()
|
||||
}
|
||||
}
|
||||
orderSfv?.run {
|
||||
setItemList(mOrderList.map { it.value }, 1)
|
||||
setOnCheckedCallback {
|
||||
mBinding?.run {
|
||||
searchBar.etSearch.hint = R.string.game_detail_cloud_archive_search_hint.toResString()
|
||||
orderSfv.setItemList(mOrderList.map { it.value }, 1)
|
||||
orderSfv.setOnCheckedCallback {
|
||||
if (mIsSearch) {
|
||||
mSearchFragment?.updateSortType(mOrderList[it])
|
||||
} else {
|
||||
mNormalFragment?.updateSortType(mOrderList[it])
|
||||
}
|
||||
}
|
||||
}
|
||||
searchBarBinding?.run {
|
||||
etSearch.hint = R.string.game_detail_cloud_archive_search_hint.toResString()
|
||||
tvBack.setOnClickListener {
|
||||
changeSearchStatus(false)
|
||||
etSearch.setText("")
|
||||
}
|
||||
etSearch.setOnEditorActionListener { _, actionId, _ ->
|
||||
searchBar.etSearch.setOnEditorActionListener { _, actionId, _ ->
|
||||
if (actionId == EditorInfo.IME_ACTION_SEARCH) {
|
||||
tvSearch.performClick()
|
||||
searchBar.tvSearch.performClick()
|
||||
}
|
||||
false
|
||||
}
|
||||
tvSearch.setOnClickListener {
|
||||
val keyWord = etSearch.text.toString().trim { it <= ' ' }
|
||||
searchBar.tvSearch.setOnClickListener {
|
||||
val keyWord = searchBar.etSearch.text.toString().trim { it <= ' ' }
|
||||
if (keyWord.isBlank()) {
|
||||
toast(R.string.search_hint)
|
||||
} else {
|
||||
changeSearchStatus(true)
|
||||
}
|
||||
}
|
||||
}
|
||||
archiveManageTv?.setOnClickListener {
|
||||
startActivity(
|
||||
CloudArchiveManagerActivity.getIntent(
|
||||
requireContext(),
|
||||
mGameEntity ?: GameEntity(),
|
||||
arguments?.getString(EntranceConsts.KEY_ARCHIVE_CONFIG_URL) ?: "",
|
||||
"游戏详情页"
|
||||
searchBar.tvBack.setOnClickListener {
|
||||
changeSearchStatus(false)
|
||||
searchBar.etSearch.setText("")
|
||||
}
|
||||
archiveManageTv.setOnClickListener {
|
||||
startActivity(
|
||||
CloudArchiveManagerActivity.getIntent(
|
||||
requireContext(),
|
||||
mGameEntity ?: GameEntity(),
|
||||
arguments?.getString(EntranceConsts.KEY_ARCHIVE_CONFIG_URL) ?: "",
|
||||
"游戏详情页"
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -143,7 +99,7 @@ class CloudArchiveFragment : LazyFragment() {
|
||||
EntranceConsts.KEY_ARCHIVE_CONFIG_URL to arguments?.getString(EntranceConsts.KEY_ARCHIVE_CONFIG_URL, "")
|
||||
)
|
||||
if (mIsSearch) {
|
||||
val keyWord = searchBarBinding?.etSearch?.text?.toString()?.trim { it <= ' ' }
|
||||
val keyWord = mBinding?.searchBar?.etSearch?.text?.toString()?.trim { it <= ' ' }
|
||||
bundle.putString(EntranceConsts.KEY_SEARCHKEY, keyWord)
|
||||
NewFlatLogUtils.logCloudArchiveSearchKeyUpload(
|
||||
mGameEntity?.id ?: "",
|
||||
@ -157,7 +113,7 @@ class CloudArchiveFragment : LazyFragment() {
|
||||
.replace(
|
||||
R.id.contentFragment,
|
||||
fragment,
|
||||
CloudArchiveListFragment::class.java.name
|
||||
SpecialCatalogFragment::class.java.name
|
||||
)
|
||||
.commitAllowingStateLoss()
|
||||
}
|
||||
@ -166,36 +122,14 @@ class CloudArchiveFragment : LazyFragment() {
|
||||
when {
|
||||
mIsSearch != isSearch -> {
|
||||
mIsSearch = isSearch
|
||||
searchBarBinding?.tvBack?.goneIf(!mIsSearch)
|
||||
mBinding?.searchBar?.tvBack?.goneIf(!mIsSearch)
|
||||
changeContentFragment()
|
||||
}
|
||||
|
||||
mIsSearch -> {
|
||||
val keyWord = searchBarBinding?.etSearch?.text?.toString()?.trim { it <= ' ' } ?: ""
|
||||
val keyWord = mBinding?.searchBar?.etSearch?.text?.toString()?.trim { it <= ' ' } ?: ""
|
||||
NewFlatLogUtils.logCloudArchiveSearchKeyUpload(mGameEntity?.id ?: "", mGameEntity?.name ?: "", keyWord)
|
||||
mSearchFragment?.updateSearchKeyWord(keyWord)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDarkModeChanged() {
|
||||
super.onDarkModeChanged()
|
||||
if (mUseAlternativeLayout) {
|
||||
requireActivity().updateStatusBarColor(com.gh.gamecenter.common.R.color.ui_surface, com.gh.gamecenter.common.R.color.ui_surface)
|
||||
}
|
||||
mAlternativeBinding?.reuseToolbar?.run {
|
||||
normalToolbar.setBackgroundColor(
|
||||
com.gh.gamecenter.common.R.color.ui_surface.toColor(requireContext()))
|
||||
backBtn.setImageResource(com.gh.gamecenter.common.R.drawable.ic_bar_back)
|
||||
normalTitle.setTextColor(com.gh.gamecenter.common.R.color.text_primary.toColor(requireContext()))
|
||||
}
|
||||
orderSfv?.run {
|
||||
setContainerBackground(com.gh.gamecenter.common.R.drawable.button_round_f5f5f5.toDrawable(requireContext()))
|
||||
setIndicatorBackground(R.drawable.bg_game_collection_sfv_indicator.toDrawable(requireContext()))
|
||||
setTextColor(
|
||||
com.gh.gamecenter.common.R.color.text_secondary.toColor(requireContext()),
|
||||
com.gh.gamecenter.common.R.color.text_tertiary.toColor(requireContext())
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -15,7 +15,7 @@ class CloudArchiveListViewModel(
|
||||
private val mGameId: String,
|
||||
private var mKeyWord: String,
|
||||
configUrl: String
|
||||
) : BaseCloudArchiveViewModel(application, mGameId, configUrl) {
|
||||
) : BaseCloudArchiveViewModel(application, configUrl) {
|
||||
|
||||
val refresh = MutableLiveData<Boolean>()
|
||||
private var mSortType = SortType.HOTTEST
|
||||
|
||||
1296
app/src/main/java/com/gh/gamecenter/gamedetail/desc/DescAdapter.kt
Normal file
1296
app/src/main/java/com/gh/gamecenter/gamedetail/desc/DescAdapter.kt
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,337 @@
|
||||
package com.gh.gamecenter.gamedetail.desc
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.drawable.ColorDrawable
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.PopupWindow
|
||||
import android.widget.TextView
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.gh.common.util.*
|
||||
import com.gh.common.util.DialogUtils
|
||||
import com.gh.common.util.NewLogUtils
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.base.activity.BaseActivity
|
||||
import com.gh.gamecenter.common.baselist.ListAdapter
|
||||
import com.gh.gamecenter.common.callback.ConfirmListener
|
||||
import com.gh.gamecenter.common.constant.Constants
|
||||
import com.gh.gamecenter.common.constant.ItemViewType
|
||||
import com.gh.gamecenter.common.eventbus.EBReuse
|
||||
import com.gh.gamecenter.common.utils.*
|
||||
import com.gh.gamecenter.core.utils.MtaHelper
|
||||
import com.gh.gamecenter.core.utils.SpanBuilder
|
||||
import com.gh.gamecenter.databinding.ItemGameDetailRatingCommentBinding
|
||||
import com.gh.gamecenter.entity.RatingComment
|
||||
import com.gh.gamecenter.common.exposure.ExposureSource
|
||||
import com.gh.gamecenter.gamedetail.GameDetailFragment
|
||||
import com.gh.gamecenter.gamedetail.rating.RatingReplyActivity
|
||||
import com.gh.gamecenter.gamedetail.rating.edit.RatingEditActivity
|
||||
import com.gh.gamecenter.gamedetail.rating.logs.CommentLogsActivity
|
||||
import com.gh.gamecenter.login.user.UserManager
|
||||
import org.greenrobot.eventbus.EventBus
|
||||
import java.util.regex.Pattern
|
||||
|
||||
class DescCommentsAdapter(
|
||||
context: Context,
|
||||
var mViewModel: DescViewModel,
|
||||
private var mEntrance: String,
|
||||
private var gameName: String?
|
||||
) : ListAdapter<RatingComment>(context) {
|
||||
|
||||
var comments = ArrayList<RatingComment>()
|
||||
val path = "游戏详情:介绍"
|
||||
|
||||
override fun getItemViewType(position: Int): Int {
|
||||
return if (position == comments.size) {
|
||||
ItemViewType.ITEM_FOOTER
|
||||
} else {
|
||||
ItemViewType.ITEM_BODY
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
|
||||
return if (viewType == ItemViewType.ITEM_BODY) {
|
||||
GameDetailRatingCommentViewHolder(parent.toBinding())
|
||||
} else {
|
||||
MoreViewHolder(LayoutInflater.from(mContext).inflate(R.layout.item_game_detail_comment_more, parent, false))
|
||||
}
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int {
|
||||
return comments.size + 1
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
|
||||
if (holder is GameDetailRatingCommentViewHolder) {
|
||||
val commentData = comments[position]
|
||||
var isChildLongClick = false
|
||||
holder.binding.run {
|
||||
ImageUtils.display(userIcon, commentData.user.icon)
|
||||
ImageUtils.display(userBadge, commentData.user.auth?.icon)
|
||||
userName.text = commentData.user.name
|
||||
ratingStart.rating = commentData.star.toFloat()
|
||||
val p = Pattern.compile(RatingEditActivity.LABEL_REGEX)
|
||||
val m = p.matcher(commentData.content)
|
||||
if (m.find()) {
|
||||
val contents =
|
||||
TextHelper.getCommentLabelSpannableStringBuilder(commentData.content, com.gh.gamecenter.common.R.color.text_theme)
|
||||
content.setTextWithHighlightedTextWrappedInsideWrapper(
|
||||
text = contents,
|
||||
highlightedTextClickListener = TextHelper.DirectToWebViewHighlightedTextClick(mContext, path)
|
||||
)
|
||||
} else {
|
||||
content.setTextWithHighlightedTextWrappedInsideWrapper(
|
||||
text = commentData.content,
|
||||
highlightedTextClickListener = TextHelper.DirectToWebViewHighlightedTextClick(mContext, path)
|
||||
)
|
||||
}
|
||||
if (commentData.user.badge != null) {
|
||||
sdvUserBadge.visibility = View.VISIBLE
|
||||
tvBadgeName.visibility = View.VISIBLE
|
||||
ImageUtils.display(sdvUserBadge, commentData.user.badge?.icon)
|
||||
tvBadgeName.text = commentData.user.badge?.name
|
||||
} else {
|
||||
sdvUserBadge.visibility = View.GONE
|
||||
tvBadgeName.visibility = View.GONE
|
||||
}
|
||||
|
||||
ipRegionTv.goneIf(!(commentData.source != null && commentData.source.region.isNotEmpty()))
|
||||
ipRegionTv.text = " · ${commentData.source?.region}"
|
||||
when {
|
||||
commentData.isEditContent == null -> {
|
||||
time.setTextColor(ContextCompat.getColor(mContext, com.gh.gamecenter.common.R.color.text_tertiary))
|
||||
time.text = if (commentData.ignore) {
|
||||
val s = "${NewsUtils.getFormattedTime(commentData.time)} 保护期评论不计入总分"
|
||||
SpanBuilder(s).image(s.length - 12, s.length - 11, R.drawable.ic_ignore_rating_tips)
|
||||
.color(mContext, s.length - 10, s.length, com.gh.gamecenter.common.R.color.text_secondary).build()
|
||||
} else {
|
||||
NewsUtils.getFormattedTime(commentData.time)
|
||||
}
|
||||
}
|
||||
|
||||
commentData.isEditContent!! -> {
|
||||
time.setTextColor(ContextCompat.getColor(mContext, com.gh.gamecenter.common.R.color.text_F56614))
|
||||
time.text = if (commentData.ignore) {
|
||||
"${NewsUtils.getFormattedTime(commentData.time)} 保护期间修改评论 >"
|
||||
} else {
|
||||
"${NewsUtils.getFormattedTime(commentData.time)} 已修改 >"
|
||||
}
|
||||
}
|
||||
|
||||
else -> {
|
||||
time.setTextColor(ContextCompat.getColor(mContext, com.gh.gamecenter.common.R.color.text_F56614))
|
||||
time.text = if (commentData.ignore) {
|
||||
"${NewsUtils.getFormattedTime(commentData.time)} 保护期间修改评论"
|
||||
} else {
|
||||
"${NewsUtils.getFormattedTime(commentData.time)} 已修改"
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
sdvUserBadge.setOnClickListener {
|
||||
DialogUtils.showViewBadgeDialog(mContext, commentData.user.badge, object : ConfirmListener {
|
||||
override fun onConfirm() {
|
||||
MtaHelper.onEvent(
|
||||
"进入徽章墙_用户记录",
|
||||
"游戏详情-玩家评论",
|
||||
"${commentData.user.name}(${commentData.user.id})"
|
||||
)
|
||||
MtaHelper.onEvent("徽章中心", "进入徽章中心", "游戏详情-玩家评论")
|
||||
DirectUtils.directToBadgeWall(
|
||||
mContext,
|
||||
commentData.user.id,
|
||||
commentData.user.name,
|
||||
commentData.user.icon
|
||||
)
|
||||
}
|
||||
})
|
||||
}
|
||||
userIcon.setOnClickListener {
|
||||
DirectUtils.directToHomeActivity(mContext, commentData.user.id, mEntrance, "游戏详情-玩家评论")
|
||||
MtaHelper.onEvent("游戏详情_新", "玩家评论_点击用户头像", mViewModel.game?.name)
|
||||
NewLogUtils.logGameDetailCommentClick(
|
||||
mViewModel.game?.name ?: "",
|
||||
mViewModel.game?.id ?: "",
|
||||
"个人主页"
|
||||
)
|
||||
}
|
||||
userName.setOnClickListener {
|
||||
userIcon.performClick()
|
||||
MtaHelper.onEvent("游戏详情_新", "玩家评论_点击用户名字", mViewModel.game?.name)
|
||||
}
|
||||
|
||||
tvBadgeName.setOnClickListener { sdvUserBadge.performClick() }
|
||||
|
||||
commentItem.setOnClickListener {
|
||||
if (isChildLongClick) {
|
||||
isChildLongClick = false
|
||||
return@setOnClickListener
|
||||
}
|
||||
val exposureSource = arrayListOf(
|
||||
ExposureSource("游戏详情"),
|
||||
ExposureSource("详情tab"),
|
||||
ExposureSource("玩家评价"),
|
||||
).toJson()
|
||||
val intent = RatingReplyActivity.getIntent(
|
||||
context = mContext,
|
||||
gameId = mViewModel.game?.id ?: "",
|
||||
commentId = commentData.id,
|
||||
exposureSource = exposureSource,
|
||||
entrance = mEntrance,
|
||||
path = path
|
||||
)
|
||||
SyncDataBetweenPageHelper.startActivityForResult(mContext, intent, RATING_REPLY_REQUEST, position)
|
||||
MtaHelper.onEvent("游戏详情_新", "玩家评论_点击评论", mViewModel.game?.name)
|
||||
NewLogUtils.logGameDetailCommentClick(
|
||||
mViewModel.game?.name ?: "",
|
||||
mViewModel.game?.id ?: "",
|
||||
"评论内容"
|
||||
)
|
||||
}
|
||||
content.setExpandCallback {
|
||||
MtaHelper.onEvent("游戏详情_新", "玩家评论_点击全文", mViewModel.game?.name)
|
||||
}
|
||||
|
||||
content.setOnLongClickListener(View.OnLongClickListener {
|
||||
isChildLongClick = true
|
||||
commentData.content.replace(RatingEditActivity.LABEL_REPLACE_REGEX.toRegex(), "").copyTextAndToast()
|
||||
return@OnLongClickListener true
|
||||
})
|
||||
more.setOnClickListener {
|
||||
showMorePopWindow(it, commentData.user.id == UserManager.getInstance().userId) { text ->
|
||||
when (text) {
|
||||
"复制" -> {
|
||||
commentData.content.replace(RatingEditActivity.LABEL_REPLACE_REGEX.toRegex(), "")
|
||||
.copyTextAndToast()
|
||||
MtaHelper.onEvent("游戏详情_新", "玩家评论_复制", mViewModel.game?.name)
|
||||
}
|
||||
|
||||
"修改" -> {
|
||||
MtaHelper.onEvent("游戏详情_新", "玩家评论_修改", mViewModel.game?.name)
|
||||
val intent = RatingEditActivity.getPatchIntent(mContext, mViewModel.game!!, commentData)
|
||||
SyncDataBetweenPageHelper.startActivityForResult(
|
||||
mContext,
|
||||
intent,
|
||||
RATING_PATCH_REQUEST,
|
||||
position
|
||||
)
|
||||
}
|
||||
|
||||
"投诉" -> {
|
||||
MtaHelper.onEvent("游戏详情_新", "玩家评论_投诉", mViewModel.game?.name)
|
||||
mContext.ifLogin(BaseActivity.mergeEntranceAndPath(mEntrance, path)) {
|
||||
DialogUtils.showReportReasonDialog(
|
||||
mContext,
|
||||
Constants.REPORT_LIST.toList() as java.util.ArrayList<String>
|
||||
) { reason, desc ->
|
||||
SimpleRequestHelper.reportGameComment(
|
||||
mViewModel.game?.id ?: "",
|
||||
commentData.id,
|
||||
if (reason != "其他原因") reason else desc
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
"删除" -> {
|
||||
DialogHelper.showDeleteGameCommentDialog(
|
||||
mContext,
|
||||
R.string.delete_game_comment.toResString()
|
||||
) {
|
||||
SimpleRequestHelper.deleteGameComment(
|
||||
mViewModel.game?.id ?: "",
|
||||
commentData.id
|
||||
) {
|
||||
// 删除列表中的评论(如果当前列表有的话)
|
||||
val index = comments.indexOfFirst { item ->
|
||||
item.id == commentData.id
|
||||
}
|
||||
if (index != -1) {
|
||||
comments.removeAt(index)
|
||||
notifyItemRemoved(index)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
time.setOnClickListener {
|
||||
if (commentData.isEditContent == null && commentData.ignore) {
|
||||
MtaHelper.onEvent("游戏详情_新", "玩家评论-评论说明", mViewModel.game?.name)
|
||||
DialogUtils.showStopServerExplanationDialog(
|
||||
mContext,
|
||||
if (mViewModel.game?.commentDescription?.isNotEmpty() == true)
|
||||
mViewModel.game?.commentDescription else mContext.getString(R.string.rating_protection),
|
||||
mViewModel.game?.name
|
||||
?: ""
|
||||
)
|
||||
} else if (commentData.isEditContent == true) {
|
||||
MtaHelper.onEvent("游戏详情_新", "玩家评论-点击时间", mViewModel.game?.name)
|
||||
val intent = CommentLogsActivity.getIntent(mContext, mViewModel.game!!.id, commentData.id)
|
||||
mContext.startActivity(intent)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (holder is MoreViewHolder) {
|
||||
holder.itemView.setOnClickListener {
|
||||
EventBus.getDefault().post(EBReuse(GameDetailFragment.SKIP_RATING))
|
||||
MtaHelper.onEvent("游戏详情_新", "玩家评论_查看全部评论", gameName)
|
||||
NewLogUtils.logGameDetailCommentClick(
|
||||
mViewModel.game?.name ?: "",
|
||||
mViewModel.game?.id ?: "",
|
||||
"查看全部评论"
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun showMorePopWindow(v: View, isMyRating: Boolean, clickListener: (String) -> Unit) {
|
||||
val contentList = if (isMyRating) arrayListOf("复制", "修改", "删除")
|
||||
else arrayListOf("复制", "投诉")
|
||||
|
||||
val inflater = LayoutInflater.from(v.context)
|
||||
val layout = inflater.inflate(com.gh.gamecenter.common.R.layout.layout_popup_container, null)
|
||||
val popupWindow = PopupWindow(
|
||||
layout,
|
||||
LinearLayout.LayoutParams.WRAP_CONTENT,
|
||||
LinearLayout.LayoutParams.WRAP_CONTENT
|
||||
)
|
||||
popupWindow.apply {
|
||||
setBackgroundDrawable(ColorDrawable(0))
|
||||
isTouchable = true
|
||||
isFocusable = true
|
||||
isOutsideTouchable = true
|
||||
}
|
||||
|
||||
val container = layout.findViewById<LinearLayout>(R.id.container)
|
||||
for (text in contentList) {
|
||||
val item = inflater.inflate(R.layout.layout_popup_option_item, container, false)
|
||||
container.addView(item)
|
||||
|
||||
val hitText = item.findViewById<TextView>(R.id.hint_text)
|
||||
hitText.text = text
|
||||
|
||||
item.setOnClickListener {
|
||||
clickListener.invoke(text)
|
||||
popupWindow.dismiss()
|
||||
}
|
||||
}
|
||||
|
||||
popupWindow.showAutoOrientation(v)
|
||||
}
|
||||
|
||||
class MoreViewHolder(var view: View) : RecyclerView.ViewHolder(view)
|
||||
|
||||
class GameDetailRatingCommentViewHolder(var binding: ItemGameDetailRatingCommentBinding) :
|
||||
RecyclerView.ViewHolder(binding.root)
|
||||
|
||||
companion object {
|
||||
const val RATING_REPLY_REQUEST = 233
|
||||
const val RATING_PATCH_REQUEST = 234
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,322 @@
|
||||
package com.gh.gamecenter.gamedetail.desc
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Intent
|
||||
import android.graphics.Rect
|
||||
import android.view.View
|
||||
import androidx.recyclerview.widget.DefaultItemAnimator
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.therouter.TheRouter
|
||||
import com.gh.common.util.DirectUtils
|
||||
import com.gh.common.util.OnSyncCallBack
|
||||
import com.gh.common.util.SyncDataBetweenPageHelper
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.base.fragment.LazyFragment
|
||||
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.eventbus.EBReuse
|
||||
import com.gh.gamecenter.common.utils.observeNonNull
|
||||
import com.gh.gamecenter.common.utils.toColor
|
||||
import com.gh.gamecenter.common.utils.viewModelProvider
|
||||
import com.gh.gamecenter.common.utils.viewModelProviderFromParent
|
||||
import com.gh.gamecenter.core.iinterface.IScrollable
|
||||
import com.gh.gamecenter.core.provider.IFloatingWindowProvider
|
||||
import com.gh.gamecenter.core.utils.SPUtils
|
||||
import com.gh.gamecenter.databinding.FragmentDescBinding
|
||||
import com.gh.gamecenter.entity.RatingComment
|
||||
import com.gh.gamecenter.eventbus.EBScroll
|
||||
import com.gh.gamecenter.eventbus.EBTypeChange
|
||||
import com.gh.gamecenter.feature.entity.GameEntity
|
||||
import com.gh.gamecenter.feature.entity.WelcomeDialogEntity
|
||||
import com.gh.gamecenter.gamedetail.GameDetailFragment
|
||||
import com.gh.gamecenter.gamedetail.GameDetailFragment.Companion.SKIP_DESC
|
||||
import com.gh.gamecenter.gamedetail.GameDetailViewModel
|
||||
import com.gh.gamecenter.gamedetail.entity.DetailEntity
|
||||
import com.gh.gamecenter.gamedetail.entity.NewGameDetailEntity
|
||||
import com.gh.gamecenter.gamedetail.rating.RatingFragment
|
||||
import com.gh.gamecenter.video.detail.VideoDetailActivity
|
||||
import com.halo.assistant.HaloApp
|
||||
import io.reactivex.disposables.CompositeDisposable
|
||||
import org.greenrobot.eventbus.EventBus
|
||||
import org.greenrobot.eventbus.Subscribe
|
||||
import org.greenrobot.eventbus.ThreadMode
|
||||
|
||||
// TODO 处理页面重建时会生成额外 Fragment 的问题
|
||||
class DescFragment: LazyFragment(), IScrollable {
|
||||
|
||||
private var mAdapter: DescAdapter ? = null
|
||||
private var mLayoutManager: LinearLayoutManager? = null
|
||||
private var mGameEntity: GameEntity? = null
|
||||
|
||||
private var mNewDetailEntity: NewGameDetailEntity? = null
|
||||
|
||||
private lateinit var mViewModel: DescViewModel
|
||||
private lateinit var mBinding: FragmentDescBinding
|
||||
|
||||
private var mCompositeDisposable = CompositeDisposable()
|
||||
|
||||
var openVideoStreaming = false // 是否自动打开视频流
|
||||
|
||||
private var mScrollToLibao = false
|
||||
private var mScrollToServer = false
|
||||
|
||||
override fun getRealLayoutId() = R.layout.fragment_desc
|
||||
|
||||
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||
super.onActivityResult(requestCode, resultCode, data)
|
||||
|
||||
val adapter = mAdapter ?: return
|
||||
|
||||
if (resultCode == Activity.RESULT_OK) {
|
||||
if (DescCommentsAdapter.RATING_REPLY_REQUEST == requestCode || DescCommentsAdapter.RATING_PATCH_REQUEST == requestCode) {
|
||||
var commentPosition = 0
|
||||
SyncDataBetweenPageHelper.resultHandle(data, object : OnSyncCallBack<RatingComment> {
|
||||
override fun onData(dataPosition: Int): RatingComment? {
|
||||
val descItemList = adapter.descItemList
|
||||
for (i in 0 until descItemList.size) {
|
||||
val comments = descItemList[i].comment
|
||||
if (comments != null) {
|
||||
commentPosition = i
|
||||
val ratingComment = comments[dataPosition]
|
||||
if (DescCommentsAdapter.RATING_PATCH_REQUEST == requestCode) {
|
||||
ratingComment.ignore = mGameEntity?.ignoreComment ?: false
|
||||
}
|
||||
return ratingComment
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
override fun onNotify(dataPosition: Int) {
|
||||
adapter.notifyItemChanged(commentPosition)
|
||||
}
|
||||
})
|
||||
} else if (requestCode == 100) {
|
||||
val position = adapter.descItemList.indexOfFirst { it.type == DetailEntity.Type.LIBAO.value }
|
||||
adapter.notifyItemChanged(position)
|
||||
}
|
||||
} else if (requestCode == DescCommentsAdapter.RATING_REPLY_REQUEST && resultCode == RatingFragment.RATING_DELETE_RESULT) {
|
||||
data?.getParcelableExtra<RatingComment>(RatingComment::class.java.simpleName)?.run {
|
||||
val descItemList = adapter.descItemList
|
||||
var commentPosition = 0
|
||||
for (i in 0 until descItemList.size) {
|
||||
val comments = descItemList[i].comment
|
||||
if (comments != null) {
|
||||
commentPosition = i
|
||||
val deleteCommentPosition = comments.indexOfFirst { it.id == id }
|
||||
if (deleteCommentPosition != -1) comments.removeAt(deleteCommentPosition)
|
||||
break
|
||||
}
|
||||
}
|
||||
adapter.notifyItemChanged(commentPosition)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onFragmentFirstVisible() {
|
||||
mGameEntity = arguments?.getParcelable(EntranceConsts.KEY_GAME_ENTITY)
|
||||
openVideoStreaming = arguments?.getBoolean(EntranceConsts.KEY_OPEN_VIDEO_STREAMING, false) ?: false
|
||||
mScrollToLibao = arguments?.getBoolean(EntranceConsts.KEY_SCROLL_TO_LIBAO, false) ?: false
|
||||
mScrollToServer = arguments?.getBoolean(EntranceConsts.KEY_SCROLL_TO_SERVER, false) ?: false
|
||||
|
||||
val gameDetailFactory =
|
||||
GameDetailViewModel.Factory(HaloApp.getInstance().application, mGameEntity?.id, mGameEntity)
|
||||
val gameDetailViewModel: GameDetailViewModel = viewModelProviderFromParent(gameDetailFactory, mGameEntity?.id ?: "")
|
||||
mNewDetailEntity = gameDetailViewModel.gameDetailLiveData.value?.data
|
||||
|
||||
val factory = DescViewModel.Factory(HaloApp.getInstance().application, mGameEntity)
|
||||
mViewModel = viewModelProvider(factory)
|
||||
|
||||
super.onFragmentFirstVisible()
|
||||
|
||||
gameDetailViewModel.gameDetailLiveData.observeNonNull(this) { gameDetail ->
|
||||
if (gameDetail.data == null) return@observeNonNull
|
||||
|
||||
mAdapter?.updateDescItemList(mViewModel.decorateList(gameDetail.data!!.detailEntity))
|
||||
// 非镜像游戏获取大家都在玩 (数据来源看具体方法内容) 数据
|
||||
if (mGameEntity?.shouldUseMirrorInfo() == false) {
|
||||
mViewModel.generateRecommendedGamesItem(gameDetail.data!!.detailEntity)
|
||||
}
|
||||
if (openVideoStreaming) {
|
||||
gameDetail.data!!.detailEntity.forEach { entity ->
|
||||
if (entity.video != null && activity !is VideoDetailActivity) {
|
||||
DirectUtils.directToVideoDetail(
|
||||
requireContext(), entity.video?.firstOrNull()?.videoId ?: "", entity.video?.firstOrNull()?.videoId, path = "游戏详情-介绍视频"
|
||||
)
|
||||
return@forEach
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
gameDetailViewModel.unifiedGameDetailWithUserRelatedInfoForChildLiveData.observeNonNull(this) {
|
||||
mAdapter?.updateDescItemList(mViewModel.decorateList(it.detailEntity))
|
||||
}
|
||||
mViewModel.list.observe(this) {
|
||||
mAdapter?.updateDescItemList(it)
|
||||
if (mScrollToLibao && mViewModel.getLibaoIndexPosition() != -1) {
|
||||
mScrollToLibao = false
|
||||
mLayoutManager?.scrollToPositionWithOffset(mViewModel.getLibaoIndexPosition(), 0)
|
||||
}
|
||||
if (mScrollToServer && mViewModel.getServerIndexPosition() != -1) {
|
||||
mScrollToServer = false
|
||||
mLayoutManager?.scrollToPositionWithOffset(mViewModel.getServerIndexPosition(), 0)
|
||||
}
|
||||
}
|
||||
|
||||
mViewModel.changeColumnGameLiveData.observe(this) {
|
||||
val viewHolder =
|
||||
mBinding.recyclerview.findViewHolderForAdapterPosition(mViewModel.getColumnRecommendPosition()) as? DescAdapter.ColumnRecommendViewHolder
|
||||
viewHolder?.binding?.run {
|
||||
headPb.visibility = View.GONE
|
||||
moreTv.isEnabled = true
|
||||
}
|
||||
if (it) {
|
||||
mAdapter?.notifyItemChanged(mViewModel.getColumnRecommendPosition())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onRealLayoutInflated(inflatedView: View) {
|
||||
super.onRealLayoutInflated(inflatedView)
|
||||
|
||||
mBinding = FragmentDescBinding.bind(inflatedView)
|
||||
|
||||
showFloatingWindowIfNeeded()
|
||||
mBinding.reuseLoading.root.visibility = View.GONE
|
||||
|
||||
mAdapter = DescAdapter(requireContext(), mEntrance, mViewModel, mNewDetailEntity)
|
||||
(mBinding.recyclerview.itemAnimator as DefaultItemAnimator).supportsChangeAnimations = false
|
||||
mLayoutManager = LinearLayoutManager(context)
|
||||
mBinding.recyclerview.layoutManager = mLayoutManager
|
||||
mBinding.recyclerview.adapter = mAdapter
|
||||
|
||||
mBinding.recyclerview.addOnScrollListener(object : RecyclerView.OnScrollListener() {
|
||||
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
|
||||
super.onScrolled(recyclerView, dx, dy)
|
||||
val firstCompletelyVisibleItemPosition = mLayoutManager!!.findFirstCompletelyVisibleItemPosition()
|
||||
val lastCompletelyVisibleItemPosition = mLayoutManager!!.findLastCompletelyVisibleItemPosition()
|
||||
|
||||
for (i in firstCompletelyVisibleItemPosition..lastCompletelyVisibleItemPosition) {
|
||||
if (i < 0) continue
|
||||
|
||||
if (mAdapter?.getItemViewType(i) == DescAdapter.CUSTOM_COLUMN
|
||||
&& mAdapter!!.descItemList[i].customColumn?.showExpandTagsHint == true
|
||||
) {
|
||||
SPUtils.setBoolean(Constants.SP_HAS_SHOWN_EXPANDED_GAME_DETAIL_TAGS_HINT, true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
|
||||
super.onScrollStateChanged(recyclerView, newState)
|
||||
if (newState == RecyclerView.SCROLL_STATE_DRAGGING) {
|
||||
EventBus.getDefault().post(EBTypeChange(GameDetailFragment.EB_SCROLLING, 0))
|
||||
}
|
||||
|
||||
exposureScroll(newState)
|
||||
}
|
||||
})
|
||||
exposureScroll(RecyclerView.SCROLL_STATE_IDLE)
|
||||
}
|
||||
|
||||
private fun exposureScroll(newState: Int) {
|
||||
if (newState == RecyclerView.SCROLL_STATE_IDLE) {
|
||||
val layoutManager = mBinding.recyclerview.layoutManager as? LinearLayoutManager
|
||||
val firstVisibleItem = layoutManager?.findFirstCompletelyVisibleItemPosition() ?: -1
|
||||
val lastVisibleItem = layoutManager?.findLastCompletelyVisibleItemPosition() ?: -1
|
||||
val childCount = mBinding.recyclerview.adapter?.itemCount ?: 0
|
||||
if (firstVisibleItem == -1 || lastVisibleItem == -1) return
|
||||
for (i in 0 until childCount) {
|
||||
val viewHolder = mBinding.recyclerview.findViewHolderForAdapterPosition(i)
|
||||
if (viewHolder != null && viewHolder is ExposureViewHolder) {
|
||||
if (i in firstVisibleItem..lastVisibleItem) {
|
||||
val rect = Rect()
|
||||
viewHolder.itemView.getLocalVisibleRect(rect)
|
||||
if (rect.top == 0 && rect.bottom == viewHolder.itemView.height) {
|
||||
viewHolder.startDelayLogRunnable()
|
||||
}
|
||||
} else {
|
||||
viewHolder.removeLogRunnable()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onFragmentPause() {
|
||||
super.onFragmentPause()
|
||||
|
||||
val childCount = mBinding.recyclerview.adapter?.itemCount ?: 0
|
||||
for (i in 0 until childCount) {
|
||||
val viewHolder = mBinding.recyclerview.findViewHolderForAdapterPosition(i)
|
||||
if (viewHolder is ExposureViewHolder) {
|
||||
viewHolder.removeLogRunnable()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
mCompositeDisposable.dispose()
|
||||
mAdapter?.stopHandlerThread()
|
||||
}
|
||||
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
fun onEventMainThread(reuse: EBReuse) {
|
||||
if (SKIP_DESC == reuse.type) {
|
||||
mAdapter?.notifyDataSetChanged()
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
fun onEventMainThread(bean: EBScroll) {
|
||||
if (mGameEntity?.id == bean.id) {
|
||||
val position = mViewModel.getGameInfoPosition()
|
||||
(mBinding.recyclerview.layoutManager as LinearLayoutManager).scrollToPositionWithOffset(position, 0)
|
||||
}
|
||||
}
|
||||
|
||||
override fun scrollToTop() {
|
||||
if (::mBinding.isInitialized) {
|
||||
mBinding.recyclerview.scrollToPosition(0)
|
||||
}
|
||||
}
|
||||
|
||||
fun scrollToRelatedVersion() {
|
||||
if (mViewModel.getRelatedVersionPosition() != -1) {
|
||||
mLayoutManager?.scrollToPositionWithOffset(mViewModel.getRelatedVersionPosition(), 0)
|
||||
}
|
||||
}
|
||||
|
||||
fun scrollToLibao() {
|
||||
if (mViewModel.getDetailLibaoPosition() != -1) {
|
||||
mLayoutManager?.scrollToPositionWithOffset(mViewModel.getDetailLibaoPosition(), 0)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDarkModeChanged() {
|
||||
super.onDarkModeChanged()
|
||||
if (!::mBinding.isInitialized) return
|
||||
|
||||
mBinding.recyclerview.setBackgroundColor(com.gh.gamecenter.common.R.color.ui_background.toColor(requireContext()))
|
||||
mBinding.recyclerview.recycledViewPool.clear()
|
||||
mAdapter?.let { it.notifyItemRangeChanged(0, it.itemCount) }
|
||||
}
|
||||
|
||||
private fun showFloatingWindowIfNeeded() {
|
||||
val floatingWindowProvider = TheRouter.get(IFloatingWindowProvider::class.java)
|
||||
|
||||
floatingWindowProvider?.getAndShowFloatingWindow(
|
||||
mGameEntity?.id ?: "",
|
||||
mGameEntity?.name ?: "",
|
||||
"游戏详情",
|
||||
this,
|
||||
mBinding.recyclerview
|
||||
)?.let {
|
||||
mCompositeDisposable.add(it)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,460 @@
|
||||
package com.gh.gamecenter.gamedetail.desc
|
||||
|
||||
import android.app.Application
|
||||
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 com.facebook.common.util.UriUtil
|
||||
import com.gh.common.util.PackageUtils
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.constant.Constants
|
||||
import com.gh.gamecenter.common.exposure.meta.MetaUtil
|
||||
import com.gh.gamecenter.common.retrofit.Response
|
||||
import com.gh.gamecenter.common.utils.*
|
||||
import com.gh.gamecenter.core.utils.*
|
||||
import com.gh.gamecenter.entity.SubjectEntity
|
||||
import com.gh.gamecenter.feature.entity.GameEntity
|
||||
import com.gh.gamecenter.feature.entity.GameInfo
|
||||
import com.gh.gamecenter.gamedetail.entity.CustomColumn
|
||||
import com.gh.gamecenter.gamedetail.entity.DetailEntity
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager
|
||||
import com.google.gson.JsonArray
|
||||
import com.google.gson.reflect.TypeToken
|
||||
import com.halo.assistant.HaloApp
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
import okhttp3.ResponseBody
|
||||
import org.json.JSONObject
|
||||
import retrofit2.HttpException
|
||||
|
||||
class DescViewModel(
|
||||
application: Application,
|
||||
var game: GameEntity?
|
||||
) : AndroidViewModel(application) {
|
||||
|
||||
private var mDataList = arrayListOf<DetailEntity>()
|
||||
private var mRelatedGameList = arrayListOf<GameEntity>()
|
||||
|
||||
private var mGameInfoPosition = 0
|
||||
private var mLibaoPosition = -1
|
||||
private var mServerPosition = -1
|
||||
private var mDetailLibaoPosition = -1
|
||||
private var mRelatedVersionPosition = -1
|
||||
private var mColumnRecommendPosition = -1
|
||||
private var mGameInfo: GameInfo? = null
|
||||
private val mIdMaps = hashMapOf<String, String>()
|
||||
private var mSubjectPage = 1
|
||||
var list = MutableLiveData<ArrayList<DetailEntity>>()
|
||||
var changeColumnGameLiveData = MutableLiveData<Boolean>()
|
||||
var gameId = game?.id
|
||||
|
||||
/**
|
||||
* 构建大家都在玩的item
|
||||
*/
|
||||
fun generateRecommendedGamesItem(mDataList: ArrayList<DetailEntity>) {
|
||||
this.mDataList = mDataList
|
||||
mIdMaps.clear()
|
||||
val detailEntity = mDataList.find { it.type == DetailEntity.Type.RECOMMENDED_GAMES.value } ?: return
|
||||
val relatedGames = detailEntity.relatedGames
|
||||
val installGames = detailEntity.installGames
|
||||
val downloadGames = detailEntity.downloadGames
|
||||
|
||||
if (relatedGames.isNullOrEmpty()
|
||||
&& installGames.isNullOrEmpty()
|
||||
&& downloadGames.isNullOrEmpty()
|
||||
) {
|
||||
assembleListWithRecommendedGames()
|
||||
return
|
||||
}
|
||||
|
||||
val labelGames = arrayListOf<String>()
|
||||
for (relatedGame in relatedGames ?: listOf()) {
|
||||
relatedGame.game?.let {
|
||||
labelGames.addAll(it)
|
||||
}
|
||||
}
|
||||
|
||||
if (labelGames.isNotEmpty()) {
|
||||
val gameIds = labelGames.take(4)
|
||||
gameIds.forEach {
|
||||
mIdMaps[it] = "标签推荐"
|
||||
}
|
||||
}
|
||||
val labelGameCount = mIdMaps.size
|
||||
|
||||
if (installGames != null) {
|
||||
val gameIds = installGames.take(4)
|
||||
gameIds.forEach {
|
||||
mIdMaps[it] = "安装推荐"
|
||||
}
|
||||
}
|
||||
|
||||
if (downloadGames != null) {
|
||||
val gameIds = downloadGames.take(4)
|
||||
gameIds.forEach {
|
||||
mIdMaps[it] = "下载推荐"
|
||||
}
|
||||
}
|
||||
|
||||
if (mIdMaps.size < 6 && labelGames.size > labelGameCount) {
|
||||
for (i in labelGameCount until labelGames.size) {
|
||||
mIdMaps[labelGames[i]] = "标签推荐"
|
||||
if (mIdMaps.size >= 6) break
|
||||
}
|
||||
}
|
||||
|
||||
if (mIdMaps.size < 6) {
|
||||
val entity = mDataList.find { it.type == DetailEntity.Type.RECOMMENDED_GAMES.value }
|
||||
mDataList.remove(entity)
|
||||
assembleListWithRecommendedGames()
|
||||
return
|
||||
}
|
||||
|
||||
getGamesDigestByIds {
|
||||
mRelatedGameList.clear()
|
||||
mRelatedGameList.addAll(it)
|
||||
assembleListWithRecommendedGames()
|
||||
}
|
||||
}
|
||||
|
||||
private fun getGamesDigestByIds(callback: (List<GameEntity>) -> Unit) {
|
||||
val ids = mIdMaps.map { it.key }.toList().joinToString("-")
|
||||
val filterQuery = UrlFilterUtils.getFilterQuery("game_ids", ids)
|
||||
RetrofitManager.getInstance().api.getGamesDigestByIds(filterQuery)
|
||||
.compose(observableToMain())
|
||||
.subscribe(object : Response<List<GameEntity>>() {
|
||||
override fun onResponse(response: List<GameEntity>?) {
|
||||
super.onResponse(response)
|
||||
response?.forEach { it.recommendType = mIdMaps[it.id] ?: "" }
|
||||
response?.let(callback) ?: callback.invoke(listOf())
|
||||
}
|
||||
|
||||
override fun onFailure(e: HttpException?) {
|
||||
super.onFailure(e)
|
||||
callback.invoke(listOf())
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private fun assembleListWithRecommendedGames() {
|
||||
for ((index, data) in mDataList.withIndex()) {
|
||||
if (data.info != null) {
|
||||
mGameInfoPosition = index
|
||||
mGameInfo = data.info!!
|
||||
}
|
||||
|
||||
if (data.server != null) {
|
||||
mServerPosition = index
|
||||
}
|
||||
|
||||
if (data.libao != null) {
|
||||
mLibaoPosition = index
|
||||
}
|
||||
|
||||
if (data.columnGames != null) {
|
||||
mColumnRecommendPosition = index
|
||||
}
|
||||
|
||||
if (data.relatedGames != null) {
|
||||
mRelatedGameList.shuffle()
|
||||
val recommendedGames = SubjectEntity().apply {
|
||||
this.data = mRelatedGameList
|
||||
}
|
||||
data.recommendedGames = recommendedGames
|
||||
}
|
||||
}
|
||||
list.postValue(mDataList)
|
||||
}
|
||||
|
||||
fun changeSubjectGame(subjectId: String, gameCount: Int) {
|
||||
RetrofitManager.getInstance().api
|
||||
.getSubjectGame(subjectId, mSubjectPage)
|
||||
.compose(observableToMain())
|
||||
.subscribe(object : Response<retrofit2.Response<JsonArray>>() {
|
||||
override fun onResponse(response: retrofit2.Response<JsonArray>?) {
|
||||
super.onResponse(response)
|
||||
if (response == null) return
|
||||
val total = response.headers().get("total")?.toInt() ?: 0
|
||||
val isHasNextPage = (total - mSubjectPage * 20) > 0
|
||||
val type = object : TypeToken<ArrayList<GameEntity>>() {}.type
|
||||
val games = GsonUtils.gson.fromJson<ArrayList<GameEntity>>(response.body()?.toJson() ?: "", type)
|
||||
val detailEntity =
|
||||
mDataList.find { data -> data.type == DetailEntity.Type.COLUMN_RECOMMEND.value } ?: return
|
||||
val randomArray = RandomUtils.getRandomArray(gameCount, games.size)
|
||||
detailEntity.columnGames?.run {
|
||||
clear()
|
||||
for (i in randomArray) {
|
||||
add(games[i])
|
||||
}
|
||||
}
|
||||
changeColumnGameLiveData.postValue(true)
|
||||
mSubjectPage = if (isHasNextPage) mSubjectPage + 1 else 1
|
||||
}
|
||||
|
||||
override fun onFailure(e: HttpException?) {
|
||||
super.onFailure(e)
|
||||
changeColumnGameLiveData.postValue(false)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fun sendSuggestion() {
|
||||
val params = hashMapOf<String, String>()
|
||||
params["from"] = ""
|
||||
params["ghversion"] = PackageUtils.getGhVersionName()
|
||||
params["channel"] = HaloApp.getInstance().channel
|
||||
params["type"] = Build.MODEL
|
||||
params["sdk"] = Build.VERSION.SDK_INT.toString()
|
||||
params["version"] = Build.VERSION.RELEASE
|
||||
params["source"] = HaloApp.getInstance().application.getString(R.string.app_name)
|
||||
params["jnfj"] = MetaUtil.getBase64EncodedIMEI()
|
||||
params["manufacturer"] = Build.MANUFACTURER
|
||||
params["rom"] = MetaUtil.getRom().name + " " + MetaUtil.getRom().versionName
|
||||
|
||||
params["suggestion_type"] = "游戏求更新"
|
||||
params["game_id"] = game?.id ?: ""
|
||||
params["message"] =
|
||||
"求更新:${game?.name}(${game?.getApk()?.firstOrNull()?.packageName}, ${game?.getApk()?.firstOrNull()?.version})"
|
||||
val requestBody = params.createRequestBody()
|
||||
RetrofitManager.getInstance().api.postSuggestion(requestBody)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(object : Response<ResponseBody?>() {
|
||||
override fun onResponse(response: ResponseBody?) {
|
||||
super.onResponse(response)
|
||||
ToastUtils.showToast("感谢您的反馈信息,我们将尽快处理~")
|
||||
}
|
||||
|
||||
override fun onFailure(e: HttpException?) {
|
||||
super.onFailure(e)
|
||||
e?.response()?.errorBody()?.let {
|
||||
val content = JSONObject(it.string())
|
||||
if (content.getInt("code") == 403208) {
|
||||
ToastUtils.showToast("您已经提交过反馈信息,我们将尽快处理~")
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// TODO 装饰操作放到子线程去做
|
||||
// 装饰列表数据
|
||||
fun decorateList(detailEntityList: ArrayList<DetailEntity>): ArrayList<DetailEntity> {
|
||||
val specialPadding = DisplayUtils.dip2px(12F)
|
||||
val defaultPadding = DisplayUtils.dip2px(15F)
|
||||
|
||||
var containsFirstTimeExpandCustomColumnTags = false
|
||||
var hasShownCustomColumnTagsExpandHint =
|
||||
SPUtils.getBoolean(Constants.SP_HAS_SHOWN_EXPANDED_GAME_DETAIL_TAGS_HINT)
|
||||
|
||||
// A 确定每个 item 的上下内边距
|
||||
for ((index, rawItem) in detailEntityList.withIndex()) {
|
||||
rawItem.paddingTop = defaultPadding
|
||||
rawItem.paddingBottom = defaultPadding
|
||||
|
||||
if (index == 0) {
|
||||
rawItem.paddingTop = specialPadding
|
||||
}
|
||||
}
|
||||
|
||||
// B 将游戏介绍转为简单的自定义栏目
|
||||
for (rawItem in detailEntityList) {
|
||||
if (rawItem.type == DetailEntity.Type.DES.value) {
|
||||
rawItem.type = DetailEntity.Type.CUSTOM_COLUMN.value
|
||||
rawItem.customColumn = CustomColumn(
|
||||
name = "游戏简介",
|
||||
order = 1,
|
||||
nameIcon = UriUtil.getUriForResourceId(R.drawable.ic_game_desc).toString(),
|
||||
des = rawItem.des,
|
||||
isHtmlDes = false,
|
||||
showDesRowNum = 3
|
||||
)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// C 标记"公告"、"自定义栏目"、"详细信息" 的UI样式是否合并在一起,处理置顶文章的内容
|
||||
for ((index, rawItem) in detailEntityList.withIndex()) {
|
||||
if (rawItem.type == DetailEntity.Type.NOTICE.value
|
||||
|| rawItem.type == DetailEntity.Type.CUSTOM_COLUMN.value
|
||||
|| rawItem.type == DetailEntity.Type.GAME_INFO.value
|
||||
) {
|
||||
if (index + 1 != detailEntityList.size) {
|
||||
val nextRawItem = detailEntityList[index + 1]
|
||||
if (nextRawItem.type == DetailEntity.Type.CUSTOM_COLUMN.value
|
||||
|| nextRawItem.type == DetailEntity.Type.NOTICE.value
|
||||
|| nextRawItem.type == DetailEntity.Type.GAME_INFO.value
|
||||
) {
|
||||
// 默认情况下 UI 与前后相连
|
||||
rawItem.shouldBoundWithNextItem = true
|
||||
nextRawItem.shouldBoundWithPreviousItem = true
|
||||
|
||||
// 特殊情况下,如果自定义栏目类型为按钮,且后续的项不是按钮就独立显示,后续的项也为按钮时合并显示 (仅按钮类型的自定义栏目合并)
|
||||
if (rawItem.type == DetailEntity.Type.CUSTOM_COLUMN.value
|
||||
&& rawItem.customColumn?.link?.style == "button"
|
||||
) {
|
||||
val nextItemIsButtonStyleCustomColumn =
|
||||
(nextRawItem.type == DetailEntity.Type.CUSTOM_COLUMN.value && nextRawItem.customColumn?.link?.style == "button")
|
||||
|
||||
rawItem.paddingBottom = 0
|
||||
rawItem.shouldBoundWithNextItem = nextItemIsButtonStyleCustomColumn
|
||||
nextRawItem.shouldBoundWithPreviousItem = nextItemIsButtonStyleCustomColumn
|
||||
|
||||
rawItem.paddingTop = specialPadding
|
||||
nextRawItem.paddingTop = specialPadding
|
||||
}
|
||||
|
||||
// 若当前项不是自定义栏目按钮类型的项,并且下个项是自定义栏目的项,不合并相关 UI
|
||||
if (nextRawItem.type == DetailEntity.Type.CUSTOM_COLUMN.value
|
||||
&& nextRawItem.customColumn?.link?.style == "button"
|
||||
&& (rawItem.type != DetailEntity.Type.CUSTOM_COLUMN.value
|
||||
|| rawItem.customColumn?.link?.style != "button")
|
||||
) {
|
||||
nextRawItem.shouldBoundWithPreviousItem = false
|
||||
nextRawItem.paddingBottom = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 处理置顶文章
|
||||
if (rawItem.type == "article") {
|
||||
if (rawItem.articleTop != null && rawItem.articleTop?.size != 0) {
|
||||
for ((i, article) in rawItem.articleTop!!.withIndex()) {
|
||||
article.priority = Int.MAX_VALUE
|
||||
rawItem.article?.add(i, article)
|
||||
}
|
||||
rawItem.articleTop?.clear()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// D 处理自定义栏目相关的东西
|
||||
for (rawItem in detailEntityList) {
|
||||
if (rawItem.type == DetailEntity.Type.CUSTOM_COLUMN.value) {
|
||||
// 判断自定义栏目的标签是否需要进入就自动展开
|
||||
if (rawItem.customColumn?.showInfoTagDesType == "first_expand"
|
||||
&& !SPUtils.getBoolean(Constants.SP_HAS_EXPANDED_GAME_DETAIL_TAGS)
|
||||
) {
|
||||
containsFirstTimeExpandCustomColumnTags = true
|
||||
rawItem.customColumn?.showInfoTagDesType = "expand"
|
||||
}
|
||||
|
||||
// 正文内容为空,但是后台配置了标签展开的默认展开
|
||||
if (rawItem.customColumn?.showInfoTag == true
|
||||
&& TextUtils.isEmpty(rawItem.customColumn?.des)
|
||||
) {
|
||||
rawItem.customColumn?.showInfoTagDesType = "expand"
|
||||
}
|
||||
|
||||
// 判断是否显示标签展开提示
|
||||
if (rawItem.customColumn?.showInfoTagDes == true
|
||||
&& rawItem.customColumn?.infoTag?.size != 0
|
||||
&& rawItem.customColumn?.showInfoTagDesType != "expand"
|
||||
&& !hasShownCustomColumnTagsExpandHint
|
||||
) {
|
||||
rawItem.customColumn?.showExpandTagsHint = true
|
||||
// 内存置为 true 避免出现多个提示
|
||||
hasShownCustomColumnTagsExpandHint = true
|
||||
}
|
||||
|
||||
// 不存在缩起正文的自定义栏目默认全显示
|
||||
if (TextUtils.isEmpty(rawItem.customColumn?.desBrief) && rawItem.customColumn?.name != "游戏简介") {
|
||||
rawItem.customColumn?.showDesType = "all"
|
||||
}
|
||||
|
||||
// 将自定义栏目正文内容里低版本 android 系统不支持的 HTML Tag 转为手动处理
|
||||
if (!TextUtils.isEmpty(rawItem.customColumn?.desBrief)) {
|
||||
rawItem.customColumn?.desFull = rawItem.customColumn?.desFull?.replaceUnsupportedHtmlTag()
|
||||
rawItem.customColumn?.desBrief = rawItem.customColumn?.desBrief?.replaceUnsupportedHtmlTag()
|
||||
}
|
||||
|
||||
rawItem.customColumn?.des = rawItem.customColumn?.desFull
|
||||
?: rawItem.customColumn?.des
|
||||
}
|
||||
}
|
||||
|
||||
for ((index, entity) in detailEntityList.withIndex()) {
|
||||
if (entity.libao != null) {
|
||||
mDetailLibaoPosition = index
|
||||
}
|
||||
if (entity.relatedVersion != null) {
|
||||
mRelatedVersionPosition = index
|
||||
}
|
||||
}
|
||||
|
||||
if (containsFirstTimeExpandCustomColumnTags) {
|
||||
SPUtils.setBoolean(Constants.SP_HAS_EXPANDED_GAME_DETAIL_TAGS, true)
|
||||
}
|
||||
|
||||
loadCustomColumnImageInAdvance(detailEntityList)
|
||||
|
||||
return detailEntityList
|
||||
}
|
||||
|
||||
fun getServerIndexPosition() = mServerPosition
|
||||
|
||||
fun getLibaoIndexPosition() = mLibaoPosition
|
||||
|
||||
fun getGameInfoPosition() = mGameInfoPosition
|
||||
|
||||
fun getDetailLibaoPosition() = mDetailLibaoPosition
|
||||
|
||||
fun getRelatedVersionPosition() = mRelatedVersionPosition
|
||||
|
||||
fun getColumnRecommendPosition() = mColumnRecommendPosition
|
||||
|
||||
fun getGameInfo() = mGameInfo
|
||||
|
||||
/**
|
||||
* 预加载自定义栏目的标签小图标
|
||||
*/
|
||||
private fun loadCustomColumnImageInAdvance(detailEntityList: ArrayList<DetailEntity>) {
|
||||
for (item in detailEntityList) {
|
||||
if (item.type == DetailEntity.Type.CUSTOM_COLUMN.value) {
|
||||
item.customColumn?.infoTag?.let {
|
||||
for (tag in it) {
|
||||
tryWithDefaultCatch {
|
||||
ImageUtils.picasso.load(tag.icon).fetch()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun postRequestSpeed() {
|
||||
RetrofitManager.getInstance().newApi.postRequestSpeed(com.gh.gamecenter.login.user.UserManager.getInstance().userId, gameId)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(object : Response<ResponseBody>() {
|
||||
override fun onResponse(response: ResponseBody?) {
|
||||
super.onResponse(response)
|
||||
ToastUtils.showToast("感谢您的反馈信息,我们将尽快处理~")
|
||||
}
|
||||
|
||||
override fun onFailure(e: HttpException?) {
|
||||
super.onFailure(e)
|
||||
e?.response()?.errorBody()?.let {
|
||||
val content = JSONObject(it.string())
|
||||
if (content.getInt("code") == 403208) {
|
||||
ToastUtils.showToast("您已经提交过反馈信息,我们将尽快处理~")
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
class Factory(
|
||||
private val mApplication: Application,
|
||||
private val game: GameEntity?
|
||||
) : ViewModelProvider.NewInstanceFactory() {
|
||||
override fun <T : ViewModel> create(modelClass: Class<T>): T {
|
||||
return DescViewModel(mApplication, game) as T
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,30 @@
|
||||
package com.gh.gamecenter.gamedetail.desc
|
||||
|
||||
import android.os.Handler
|
||||
import android.view.View
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
|
||||
open class ExposureViewHolder(view: View, val handler: Handler) : RecyclerView.ViewHolder(view) {
|
||||
|
||||
private var mLogRunnable: Runnable? = null
|
||||
|
||||
fun startDelayLogRunnable() {
|
||||
if (mLogRunnable == null) {
|
||||
mLogRunnable = Runnable {
|
||||
exposureLog()
|
||||
}
|
||||
handler.postDelayed(mLogRunnable!!, 3000)
|
||||
}
|
||||
}
|
||||
|
||||
open fun exposureLog() {
|
||||
|
||||
}
|
||||
|
||||
fun removeLogRunnable() {
|
||||
if (mLogRunnable != null) {
|
||||
handler.removeCallbacks(mLogRunnable!!)
|
||||
mLogRunnable = null
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,4 +1,4 @@
|
||||
package com.gh.gamecenter.gamedetail.detail.adapter
|
||||
package com.gh.gamecenter.gamedetail.desc
|
||||
|
||||
import android.view.ViewGroup
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
@ -6,26 +6,23 @@ import com.gh.common.exposure.ExposureManager
|
||||
import com.gh.common.filter.RegionSettingHelper
|
||||
import com.gh.common.util.DirectUtils
|
||||
import com.gh.gamecenter.GameDetailActivity
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.base.GlobalActivityManager
|
||||
import com.gh.gamecenter.common.base.activity.BaseActivity
|
||||
import com.gh.gamecenter.common.exposure.ExposureSource
|
||||
import com.gh.gamecenter.common.utils.*
|
||||
import com.gh.gamecenter.databinding.GamedetailItemGameCollectionBinding
|
||||
import com.gh.gamecenter.entity.GameDetailRecommendGameCollectionEntity
|
||||
import com.gh.gamecenter.entity.GameDetailRecommendGameEntity
|
||||
import com.gh.gamecenter.feature.entity.GameEntity
|
||||
import com.gh.gamecenter.feature.exposure.ExposureEvent
|
||||
import com.gh.gamecenter.gamedetail.detail.viewholder.BaseGameDetailItemViewHolder
|
||||
|
||||
class GameCollectionAdapter(
|
||||
private val mRecommendGameList: ArrayList<GameDetailRecommendGameCollectionEntity>,
|
||||
private val mRecommendGameList: ArrayList<GameDetailRecommendGameEntity>,
|
||||
private val mGameId: String,
|
||||
private val mGameName: String,
|
||||
private val mGame: GameEntity?,
|
||||
private val mEntrance: String,
|
||||
private val mPath: String,
|
||||
private val mBasicExposureSource: List<ExposureSource>,
|
||||
private val trackData: BaseGameDetailItemViewHolder.GameDetailModuleTrackData,
|
||||
private val getGameStatus: () -> String
|
||||
private val mBasicExposureSource: List<ExposureSource>
|
||||
) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
|
||||
|
||||
private val mDefaultHorizontalPadding by lazy { com.gh.gamecenter.common.R.dimen.game_detail_item_horizontal_padding.toPx() }
|
||||
@ -42,7 +39,7 @@ class GameCollectionAdapter(
|
||||
if (holder is GameCollectionItemViewHolder) {
|
||||
val entity = mRecommendGameList[position]
|
||||
holder.binding.run {
|
||||
root.background = R.drawable.bg_shape_space_radius_5.toDrawable(root.context)
|
||||
root.background = com.gh.gamecenter.common.R.drawable.background_shape_white_radius_5.toDrawable(root.context)
|
||||
titleTv.setTextColor(com.gh.gamecenter.common.R.color.text_primary.toColor(root.context))
|
||||
titleTv.text = entity.title
|
||||
ImageUtils.display(coverImage, entity.cover)
|
||||
@ -75,20 +72,20 @@ class GameCollectionAdapter(
|
||||
}
|
||||
gameCountTv.text = "+${entity.count.game - games.size}"
|
||||
root.setOnClickListener {
|
||||
SensorsBridge.trackGameDetailModuleClick(
|
||||
trackData.gameId,
|
||||
trackData.gameName,
|
||||
trackData.gameType,
|
||||
"组件内容",
|
||||
trackData.moduleType,
|
||||
trackData.moduleName,
|
||||
trackData.sequence,
|
||||
entity.title,
|
||||
position + 1,
|
||||
"game_list_detail",
|
||||
entity.id,
|
||||
entity.title,
|
||||
getGameStatus()
|
||||
SensorsBridge.trackGameDetailPageGameCollectRecommendClick(
|
||||
gameId = mGameId,
|
||||
gameName = mGameName,
|
||||
pageName = GlobalActivityManager.getCurrentPageEntity().pageName,
|
||||
pageId = GlobalActivityManager.getCurrentPageEntity().pageId,
|
||||
pageBusinessId = GlobalActivityManager.getCurrentPageEntity().pageBusinessId,
|
||||
lastPageId = GlobalActivityManager.getCurrentPageEntity().pageId,
|
||||
lastPageName = GlobalActivityManager.getCurrentPageEntity().pageName,
|
||||
lastPageBusinessId = GlobalActivityManager.getCurrentPageEntity().pageBusinessId,
|
||||
downloadStatus = mGame?.downloadStatusChinese ?: "",
|
||||
gameType = mGame?.categoryChinese ?: "",
|
||||
text = "游戏单",
|
||||
gameCollectId = entity.id,
|
||||
gameCollectTitle = entity.title
|
||||
)
|
||||
DirectUtils.directToGameCollectionDetail(
|
||||
it.context,
|
||||
@ -0,0 +1,84 @@
|
||||
package com.gh.gamecenter.gamedetail.desc
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.drawable.BitmapDrawable
|
||||
import android.net.Uri
|
||||
import android.text.Spanned
|
||||
import android.view.ViewGroup
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.gh.gamecenter.common.base.BaseRecyclerViewHolder
|
||||
import com.gh.gamecenter.common.utils.ImageUtils
|
||||
import com.gh.gamecenter.common.view.CustomLinkMovementMethod
|
||||
import com.gh.gamecenter.common.utils.dip2px
|
||||
import com.gh.gamecenter.common.utils.toBinding
|
||||
import com.gh.gamecenter.common.utils.tryWithDefaultCatch
|
||||
import com.gh.gamecenter.core.utils.*
|
||||
import com.gh.gamecenter.databinding.GamedetailItemCustomColumnItemBinding
|
||||
import com.gh.gamecenter.entity.TagEntity
|
||||
import com.lightgame.adapter.BaseRecyclerAdapter
|
||||
import com.squareup.picasso.Picasso
|
||||
import io.reactivex.Single
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
|
||||
class GameDetailCustomColumnAdapter(context: Context) : BaseRecyclerAdapter<RecyclerView.ViewHolder>(context) {
|
||||
|
||||
private var mTags: ArrayList<TagEntity> = arrayListOf()
|
||||
private var mShowTagDes: Boolean = false
|
||||
|
||||
fun updateData(tags: ArrayList<TagEntity>, showTagDes: Boolean) {
|
||||
this.mTags = tags
|
||||
this.mShowTagDes = showTagDes
|
||||
}
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
|
||||
return GameDetailCustomViewHolderViewHolder(parent.toBinding())
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(viewHolder: RecyclerView.ViewHolder, position: Int) {
|
||||
if (viewHolder is GameDetailCustomViewHolderViewHolder) {
|
||||
val (_, name, icon, des, color) = mTags[position]
|
||||
|
||||
val marginBetweenIconAndName = " "
|
||||
val content = if (mShowTagDes) "$marginBetweenIconAndName$name $des" else "$marginBetweenIconAndName$name"
|
||||
|
||||
val spannable = SpanBuilder(content)
|
||||
.color(
|
||||
marginBetweenIconAndName.length,
|
||||
name?.length?.plus(marginBetweenIconAndName.length) ?: 1,
|
||||
color ?: "#000000"
|
||||
)
|
||||
.build()
|
||||
|
||||
tryWithDefaultCatch {
|
||||
Single.just(icon)
|
||||
.map {
|
||||
ImageUtils.picasso.load(Uri.parse(it)).priority(Picasso.Priority.HIGH).get()
|
||||
}.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe({
|
||||
val bitmapDrawable = BitmapDrawable(mContext.resources, it)
|
||||
bitmapDrawable.setBounds(0, 0, 16F.dip2px(), 16F.dip2px())
|
||||
spannable.setSpan(CenterImageSpan(bitmapDrawable), 0, 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
|
||||
viewHolder.binding.contentTv.run {
|
||||
movementMethod = CustomLinkMovementMethod.getInstance()
|
||||
text = spannable
|
||||
}
|
||||
}, {
|
||||
it.printStackTrace()
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun getItemViewType(position: Int): Int {
|
||||
return position
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int {
|
||||
return mTags.size
|
||||
}
|
||||
|
||||
class GameDetailCustomViewHolderViewHolder(val binding: GamedetailItemCustomColumnItemBinding) :
|
||||
BaseRecyclerViewHolder<Any>(binding.root)
|
||||
}
|
||||
@ -0,0 +1,217 @@
|
||||
package com.gh.gamecenter.gamedetail.desc
|
||||
|
||||
import android.content.Context
|
||||
import android.view.ViewGroup
|
||||
import android.view.ViewGroup.MarginLayoutParams
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.gh.common.DefaultUrlHandler
|
||||
import com.gh.common.util.DirectUtils
|
||||
import com.gh.common.util.NewFlatLogUtils
|
||||
import com.gh.gamecenter.WebActivity
|
||||
import com.gh.gamecenter.common.utils.*
|
||||
import com.gh.gamecenter.core.utils.MtaHelper
|
||||
import com.gh.gamecenter.core.utils.TimeUtils
|
||||
import com.gh.gamecenter.databinding.ItemGameInfoBinding
|
||||
import com.gh.gamecenter.feature.entity.GameInfo
|
||||
import com.gh.gamecenter.gamedetail.dialog.GamePermissionDialogFragment
|
||||
import com.gh.gamecenter.gamedetail.entity.GameInfoItemData
|
||||
|
||||
class GameDetailInfoItemAdapter(
|
||||
val context: Context,
|
||||
val gameInfo: GameInfo,
|
||||
private val mViewModel: DescViewModel,
|
||||
val gameName: String
|
||||
) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
|
||||
var datas = ArrayList<GameInfoItemData>()
|
||||
|
||||
init {
|
||||
if (gameInfo.manufacturer.isNotEmpty()) {
|
||||
when (gameInfo.manufacturerType) {
|
||||
"manufacturer" -> {
|
||||
datas.add(GameInfoItemData(title = "厂商", info = gameInfo.manufacturer))
|
||||
}
|
||||
"publisher" -> {
|
||||
if (gameInfo.developer.isNotEmpty()) {
|
||||
datas.add(GameInfoItemData(title = "开发商", info = gameInfo.developer))
|
||||
}
|
||||
datas.add(GameInfoItemData(title = "发行商", info = gameInfo.manufacturer))
|
||||
}
|
||||
"developer" -> {
|
||||
datas.add(GameInfoItemData(title = "开发商", info = gameInfo.manufacturer))
|
||||
if (gameInfo.publisher.isNotEmpty()) {
|
||||
datas.add(GameInfoItemData(title = "发行商", info = gameInfo.publisher))
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
//do nothing
|
||||
}
|
||||
}
|
||||
}
|
||||
if (gameInfo.supplier.isNotEmpty()) {
|
||||
datas.add(GameInfoItemData(title = "供应商", info = gameInfo.supplier))
|
||||
}
|
||||
if (gameInfo.creditCode.isNotEmpty()) {
|
||||
datas.add(GameInfoItemData(title = "统一社会信用代码", info = gameInfo.creditCode))
|
||||
}
|
||||
if (gameInfo.contact != null) {
|
||||
datas.add(
|
||||
GameInfoItemData(
|
||||
title = gameInfo.contact!!.hint,
|
||||
info = gameInfo.contact!!.qq,
|
||||
actionStr = if (gameInfo.contact!!.type == "qq") "咨询" else if (gameInfo.contact?.key.isNullOrEmpty()) "复制" else "加入",
|
||||
key = gameInfo.contact!!.key
|
||||
)
|
||||
)
|
||||
}
|
||||
if (gameInfo.version.isNotEmpty()) {
|
||||
datas.add(
|
||||
GameInfoItemData(
|
||||
title = "当前版本",
|
||||
info = gameInfo.version,
|
||||
actionStr = "",
|
||||
action2Str = if (gameInfo.requestUpdateStatus == "on" && mViewModel.game?.getApk()
|
||||
?.isNotEmpty() == true
|
||||
) "求更新" else ""
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
if (gameInfo.requestSpeedStatus == "on") {
|
||||
datas.add(
|
||||
GameInfoItemData(
|
||||
title = "游戏加速",
|
||||
info = "",
|
||||
actionStr = "求加速",
|
||||
action2Str = ""
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
if (gameInfo.size.isNotEmpty()) {
|
||||
datas.add(GameInfoItemData(title = "游戏大小", info = gameInfo.size))
|
||||
}
|
||||
if (gameInfo.updateTime != 0L) {
|
||||
datas.add(GameInfoItemData(title = "更新时间", info = TimeUtils.getFormatTime(gameInfo.updateTime)))
|
||||
}
|
||||
if (gameInfo.recommendAge.isNotEmpty()) {
|
||||
datas.add(GameInfoItemData(title = "适龄等级", info = gameInfo.recommendAge))
|
||||
}
|
||||
|
||||
if (!gameInfo.internetApp.isNullOrEmpty()) {
|
||||
datas.add(GameInfoItemData(title = "联网APP", info = if (gameInfo.internetApp == "yes") "是" else "否"))
|
||||
}
|
||||
|
||||
if (gameInfo.icp != null) {
|
||||
datas.add(GameInfoItemData(title = "ICP备案号", info = gameInfo.icp?.number ?: ""))
|
||||
}
|
||||
if (!gameInfo.permissions.isNullOrEmpty()) {
|
||||
datas.add(GameInfoItemData(title = "权限及用途", info = "查看"))
|
||||
}
|
||||
if (!gameInfo.privacyPolicyUrl.isNullOrEmpty()) {
|
||||
datas.add(GameInfoItemData(title = "隐私政策", info = "查看"))
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
|
||||
return GameDetailInfoItemViewHolder(parent.toBinding())
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int = datas.size
|
||||
|
||||
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
|
||||
val gameInfoItemData = datas[position]
|
||||
if (holder is GameDetailInfoItemViewHolder) {
|
||||
holder.binding.divider.setBackgroundColor(com.gh.gamecenter.common.R.color.ui_divider.toColor(holder.binding.divider.context))
|
||||
holder.binding.infoTv.isSelected = true
|
||||
holder.binding.infoTv.text = gameInfoItemData.info
|
||||
holder.binding.titleTv.text = gameInfoItemData.title
|
||||
holder.binding.infoTv.setTextColor(com.gh.gamecenter.common.R.color.text_primary.toColor(holder.binding.infoTv.context))
|
||||
holder.binding.titleTv.setTextColor(com.gh.gamecenter.common.R.color.text_primary.toColor(holder.binding.infoTv.context))
|
||||
holder.binding.actionTv.goneIf(gameInfoItemData.actionStr.isEmpty()) {
|
||||
holder.binding.actionTv.text = gameInfoItemData.actionStr
|
||||
holder.binding.actionTv.setTextColor(com.gh.gamecenter.common.R.color.text_theme.toColor(holder.binding.infoTv.context))
|
||||
}
|
||||
holder.binding.action2Tv.goneIf(gameInfoItemData.action2Str.isEmpty()) {
|
||||
holder.binding.action2Tv.text = gameInfoItemData.action2Str
|
||||
holder.binding.action2Tv.setTextColor(com.gh.gamecenter.common.R.color.text_theme.toColor(holder.binding.infoTv.context))
|
||||
}
|
||||
holder.binding.infoTv.layoutParams = (holder.binding.infoTv.layoutParams as MarginLayoutParams).apply {
|
||||
rightMargin = if (!holder.binding.actionTv.isVisible && !holder.binding.action2Tv.isVisible) 0 else 8F.dip2px()
|
||||
}
|
||||
if (gameInfoItemData.title == "权限及用途"
|
||||
|| gameInfoItemData.title == "隐私政策"
|
||||
|| gameInfoItemData.title == "ICP备案号") {
|
||||
holder.binding.infoTv.setTextColor(ContextCompat.getColor(context, com.gh.gamecenter.common.R.color.text_theme))
|
||||
}
|
||||
holder.binding.root.setOnClickListener {
|
||||
when (gameInfoItemData.title) {
|
||||
"ICP备案号" -> {
|
||||
DirectUtils.directToExternalBrowser(context, context.getString(com.gh.gamecenter.common.R.string.icp_url))
|
||||
}
|
||||
"权限及用途" -> {
|
||||
GamePermissionDialogFragment.show(context as AppCompatActivity, mViewModel.game, gameInfo)
|
||||
}
|
||||
"隐私政策" -> {
|
||||
gameInfo.privacyPolicyUrl?.let {
|
||||
if (!DefaultUrlHandler.transformNormalScheme(holder.binding.root.context, it, "隐私政策", "")) {
|
||||
val intent =
|
||||
WebActivity.getIntent(holder.binding.root.context, it, "隐私政策", false, false)
|
||||
holder.binding.root.context.startActivity(intent)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
listOf(holder.binding.actionTv, holder.binding.action2Tv).forEach {
|
||||
it.setOnClickListener { _ ->
|
||||
when (if (it == holder.binding.actionTv) gameInfoItemData.actionStr else gameInfoItemData.action2Str) {
|
||||
"求加速" -> {
|
||||
it.context.ifLogin("游戏详情-求加速") {
|
||||
NewFlatLogUtils.logGameDetailClickForAccelerate(mViewModel.gameId ?: "", gameName)
|
||||
DialogHelper.showDialog(
|
||||
context, "版本求加速", "如果游戏需要加速版本,您可以提交申请,让小助手尽快研究给您喔!",
|
||||
"提交申请", "取消", {
|
||||
mViewModel.postRequestSpeed()
|
||||
}, extraConfig = DialogHelper.Config(centerTitle = true, centerContent = true)
|
||||
)
|
||||
}
|
||||
}
|
||||
"求更新" -> {
|
||||
MtaHelper.onEvent("游戏详情_新", "详细信息_我要求更新", gameName)
|
||||
DialogHelper.showDialog(
|
||||
context, "版本求更新", "如果游戏上线了新版本,您可以提交申请,让小助手尽快更新版本喔!",
|
||||
"提交申请", "取消", {
|
||||
mViewModel.sendSuggestion()
|
||||
}, extraConfig = DialogHelper.Config(centerTitle = true, centerContent = true)
|
||||
)
|
||||
}
|
||||
"咨询" -> {
|
||||
MtaHelper.onEvent("游戏详情_新", "详细信息_咨询", gameName)
|
||||
if (ShareUtils.isQQClientAvailable(context)) {
|
||||
DirectUtils.directToQqConversation(context, gameInfoItemData.info)
|
||||
} else {
|
||||
gameInfoItemData.info.copyTextAndToast("已复制")
|
||||
}
|
||||
}
|
||||
"加入" -> {
|
||||
MtaHelper.onEvent("游戏详情_新", "详细信息_加入", gameName)
|
||||
if (ShareUtils.isQQClientAvailable(context)) {
|
||||
DirectUtils.directToQqGroup(context, gameInfoItemData.key)
|
||||
} else {
|
||||
gameInfoItemData.info.copyTextAndToast("已复制")
|
||||
}
|
||||
}
|
||||
"复制" -> {
|
||||
gameInfoItemData.info.copyTextAndToast()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class GameDetailInfoItemViewHolder(var binding: ItemGameInfoBinding) : RecyclerView.ViewHolder(binding.root)
|
||||
}
|
||||
@ -0,0 +1,141 @@
|
||||
package com.gh.gamecenter.gamedetail.desc
|
||||
|
||||
import android.content.Context
|
||||
import android.util.SparseArray
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.core.util.forEach
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.facebook.drawee.view.SimpleDraweeView
|
||||
import com.gh.common.util.DataCollectionUtils
|
||||
import com.gh.common.util.DirectUtils
|
||||
import com.gh.common.util.NewFlatLogUtils
|
||||
import com.gh.gamecenter.ImageViewerActivity
|
||||
import com.gh.gamecenter.common.base.BaseRecyclerViewHolder
|
||||
import com.gh.gamecenter.common.utils.*
|
||||
import com.gh.gamecenter.common.view.WrapContentDraweeView
|
||||
import com.gh.gamecenter.core.utils.MtaHelper
|
||||
import com.gh.gamecenter.databinding.GalleryVideoItemBinding
|
||||
import com.gh.gamecenter.databinding.GamedetailScreenshotItemBinding
|
||||
import com.gh.gamecenter.feature.entity.GameEntity
|
||||
import com.gh.gamecenter.gamedetail.entity.Video
|
||||
import com.gh.gamecenter.video.detail.VideoDetailContainerViewModel
|
||||
|
||||
class GameGalleryAdapter(
|
||||
var context: Context,
|
||||
private val mVideo: ArrayList<Video>? = null,
|
||||
private val mGallery: ArrayList<String>? = null,
|
||||
val mGame: GameEntity,
|
||||
private val mEntrance: String
|
||||
) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
|
||||
|
||||
private val mImageViewArray = SparseArray<SimpleDraweeView>()
|
||||
private val mDefaultHorizontalPadding by lazy { com.gh.gamecenter.common.R.dimen.game_detail_item_horizontal_padding.toPx() }
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
|
||||
return when (viewType) {
|
||||
VIDEO -> {
|
||||
VideoViewHolder(parent.toBinding())
|
||||
}
|
||||
IMAGE -> {
|
||||
GameGalleryViewHolder(parent.toBinding())
|
||||
}
|
||||
else -> throw NullPointerException()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
|
||||
when (holder) {
|
||||
is GameGalleryViewHolder -> {
|
||||
holder.binding.screenshotItemIv.setTag(ImageUtils.TAG_TARGET_WIDTH, 260F.dip2px())
|
||||
ImageUtils.display(holder.binding.screenshotItemIv, mGallery?.get(position))
|
||||
holder.binding.screenshotItemIv.registerLoadingCallback(object : WrapContentDraweeView.LoadingCallback {
|
||||
override fun loaded() {
|
||||
holder.binding.screenshotItemIv.post {
|
||||
holder.binding.screenshotItemIv.layoutParams.apply {
|
||||
height = holder.binding.screenshotItemIv.height
|
||||
width =
|
||||
(holder.binding.screenshotItemIv.height * holder.binding.screenshotItemIv.aspectRatio).toInt()
|
||||
holder.binding.screenshotItemIv.layoutParams = this
|
||||
}
|
||||
|
||||
holder.itemView.requestLayout()
|
||||
}
|
||||
}
|
||||
})
|
||||
holder.itemView.setDebouncedClickListener {
|
||||
DataCollectionUtils.uploadClick(context, "游戏介绍", "游戏详情")
|
||||
MtaHelper.onEvent("游戏详情_新", "点击游戏截图", mGame.name)
|
||||
|
||||
val imageViewList = ArrayList<View>()
|
||||
mImageViewArray.forEach { _, value ->
|
||||
imageViewList.add(value)
|
||||
}
|
||||
|
||||
val intent = ImageViewerActivity.getIntent(
|
||||
context,
|
||||
mGallery ?: arrayListOf(),
|
||||
holder.adapterPosition,
|
||||
imageViewList,
|
||||
mEntrance
|
||||
)
|
||||
context.startActivity(intent)
|
||||
}
|
||||
mImageViewArray.put(position, holder.binding.screenshotItemIv)
|
||||
}
|
||||
is VideoViewHolder -> {
|
||||
val video = mVideo?.get(position)
|
||||
ImageUtils.display(holder.binding.screenshotItemIv, mVideo?.get(position)!!.poster)
|
||||
holder.binding.videoTitleTv.setTextColor(com.gh.gamecenter.common.R.color.text_primary.toColor(holder.binding.videoTitleTv.context))
|
||||
holder.binding.usernameTv.text = video?.user?.name
|
||||
holder.binding.videoTitleTv.text = video?.title
|
||||
holder.binding.voteCountTv.text = video?.vote.toString()
|
||||
holder.binding.screenshotItemIv.setOnClickListener {
|
||||
MtaHelper.onEvent("游戏详情_新", "点击视频", "${mGame.name}+${video?.title}")
|
||||
NewFlatLogUtils.logClickGameDetailVideoCategory(
|
||||
"video",
|
||||
video?.videoId ?: "",
|
||||
video?.user?.id ?: ""
|
||||
)
|
||||
DirectUtils.directToVideoDetail(
|
||||
context, video?.videoId
|
||||
?: "", VideoDetailContainerViewModel.Location.GAME_DETAIL.value,
|
||||
false, mGame.id, mEntrance, "游戏详情"
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
val params = holder.itemView.layoutParams as RecyclerView.LayoutParams
|
||||
|
||||
params.leftMargin = if (position == 0) mDefaultHorizontalPadding else 8F.dip2px()
|
||||
params.rightMargin = if (position == itemCount - 1) mDefaultHorizontalPadding else 0F.dip2px()
|
||||
holder.itemView.layoutParams = params
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int {
|
||||
return when {
|
||||
mVideo != null -> mVideo.size
|
||||
mGallery != null -> mGallery.size
|
||||
else -> 0
|
||||
}
|
||||
}
|
||||
|
||||
override fun getItemViewType(position: Int): Int {
|
||||
return when {
|
||||
mVideo != null -> VIDEO
|
||||
mGallery != null -> IMAGE
|
||||
else -> 0
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val IMAGE = 223
|
||||
const val VIDEO = 224
|
||||
}
|
||||
|
||||
class GameGalleryViewHolder(val binding: GamedetailScreenshotItemBinding) :
|
||||
BaseRecyclerViewHolder<Any>(binding.root)
|
||||
|
||||
class VideoViewHolder(var binding: GalleryVideoItemBinding) : RecyclerView.ViewHolder(binding.root)
|
||||
|
||||
}
|
||||
@ -1,4 +1,4 @@
|
||||
package com.gh.gamecenter.gamedetail.detail.adapter
|
||||
package com.gh.gamecenter.gamedetail.desc
|
||||
|
||||
import android.content.Context
|
||||
import android.view.Gravity
|
||||
@ -8,9 +8,9 @@ import android.view.ViewGroup
|
||||
import android.view.ViewTreeObserver
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.gh.common.util.NewLogUtils
|
||||
import com.gh.gamecenter.core.utils.TimeUtils
|
||||
import com.gh.gamecenter.common.utils.safelyGetInRelease
|
||||
import com.gh.gamecenter.common.utils.toBinding
|
||||
import com.gh.gamecenter.core.utils.TimeUtils
|
||||
import com.gh.gamecenter.databinding.ItemGameDetailLatestServiceBinding
|
||||
import com.gh.gamecenter.databinding.ItemGameDetailMoreBinding
|
||||
import com.gh.gamecenter.feature.entity.GameEntity
|
||||
@ -0,0 +1,244 @@
|
||||
package com.gh.gamecenter.gamedetail.desc
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.gh.common.util.LibaoUtils
|
||||
import com.gh.common.util.NewLogUtils
|
||||
import com.gh.gamecenter.common.utils.copyTextAndToast
|
||||
import com.gh.gamecenter.common.utils.fromHtml
|
||||
import com.gh.gamecenter.common.utils.toBinding
|
||||
import com.gh.gamecenter.core.utils.MtaHelper
|
||||
import com.gh.gamecenter.core.utils.SpanBuilder
|
||||
import com.gh.gamecenter.databinding.ItemGameDetailMoreBinding
|
||||
import com.gh.gamecenter.databinding.ItemGameLibaoBinding
|
||||
import com.gh.gamecenter.feature.entity.LibaoEntity
|
||||
import com.gh.gamecenter.libao.LibaoDetailActivity
|
||||
import com.gh.gamecenter.login.user.UserManager
|
||||
|
||||
class GameLibaoAdapter(
|
||||
val context: Context,
|
||||
val libaos: ArrayList<LibaoEntity>,
|
||||
val gameName: String,
|
||||
val gameId: String,
|
||||
val showExpandIcon: Boolean = true,
|
||||
val standaloneStyle: Boolean = false,
|
||||
) :
|
||||
RecyclerView.Adapter<RecyclerView.ViewHolder>() {
|
||||
|
||||
private var mIsExpand = false
|
||||
private val mShowItemCount: Int = if (showExpandIcon) 3 else Int.MAX_VALUE // 最多展示多少个礼包
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
|
||||
return if (viewType == LIBAO_ITEM) {
|
||||
LibaoViewHolder(parent.toBinding())
|
||||
} else {
|
||||
MoreViewHolder(ItemGameDetailMoreBinding.inflate(LayoutInflater.from(context), parent, false))
|
||||
}
|
||||
}
|
||||
|
||||
override fun getItemViewType(position: Int): Int {
|
||||
return if (libaos.size > mShowItemCount) {
|
||||
if (!mIsExpand) {
|
||||
if (position == mShowItemCount) MORE else LIBAO_ITEM
|
||||
} else {
|
||||
if (position == libaos.size) MORE else LIBAO_ITEM
|
||||
}
|
||||
} else {
|
||||
LIBAO_ITEM
|
||||
}
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int {
|
||||
return if (libaos.size > mShowItemCount) {
|
||||
if (mIsExpand) libaos.size + 1 else mShowItemCount + 1
|
||||
} else libaos.size
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
|
||||
when (holder) {
|
||||
is LibaoViewHolder -> {
|
||||
if (standaloneStyle) {
|
||||
if (position == 0) {
|
||||
holder.binding.root.setBackgroundResource(com.gh.gamecenter.common.R.drawable.background_shape_white_radius_5_top_only)
|
||||
} else if (position == itemCount - 1) {
|
||||
holder.binding.root.setBackgroundResource(com.gh.gamecenter.common.R.drawable.background_shape_white_radius_5_bottm_only)
|
||||
} else {
|
||||
holder.binding.root.setBackgroundResource(com.gh.gamecenter.common.R.color.ui_surface)
|
||||
}
|
||||
}
|
||||
|
||||
val libaoEntity = libaos[position]
|
||||
|
||||
holder.binding.libaoNameTv.text = libaoEntity.name
|
||||
holder.binding.contentTv.text = libaoEntity.content?.fromHtml()
|
||||
|
||||
val isTypeCopy = libaoEntity.receiveMethod == "copy"
|
||||
if (isTypeCopy) {
|
||||
// 类型为复制,不需要登录也能直接领取
|
||||
holder.binding.libaoSchedulePb.visibility = View.GONE
|
||||
holder.binding.remainingTv.visibility = View.GONE
|
||||
holder.binding.libaoCodeTv.visibility = View.VISIBLE
|
||||
|
||||
val text = "兑换码:${libaoEntity.code}"
|
||||
holder.binding.libaoCodeTv.text = SpanBuilder(text).color(
|
||||
holder.binding.root.context,
|
||||
4,
|
||||
text.length,
|
||||
com.gh.gamecenter.common.R.color.text_theme
|
||||
).build()
|
||||
holder.binding.copyLibaoCodeIv.visibility = View.VISIBLE
|
||||
holder.binding.copyLibaoCodeIv.setOnClickListener {
|
||||
holder.binding.receiveTv.performClick()
|
||||
}
|
||||
} else if (libaoEntity.universal || libaoEntity.status == "check") {
|
||||
//通用码礼包/或者还未添加礼包码时,不显示进度条,显示礼包码
|
||||
holder.binding.libaoSchedulePb.visibility = View.GONE
|
||||
holder.binding.remainingTv.visibility = View.GONE
|
||||
holder.binding.libaoCodeTv.visibility = View.VISIBLE
|
||||
holder.binding.copyLibaoCodeIv.visibility = View.GONE
|
||||
|
||||
if (!UserManager.getInstance().isLoggedIn) {
|
||||
holder.binding.libaoCodeTv.text = "礼包码:-"
|
||||
} else {
|
||||
when (libaoEntity.status) {
|
||||
"linged", "repeatLing", "repeatLinged", "taoed", "repeatTao", "repeatTaoed" -> {
|
||||
val size = libaoEntity.me?.userDataLibaoList?.size ?: 0
|
||||
val code = libaoEntity.me?.userDataLibaoList?.get(size - 1)?.code ?: ""
|
||||
val text = "礼包码:$code"
|
||||
holder.binding.libaoCodeTv.text = SpanBuilder(text).color(
|
||||
holder.binding.root.context,
|
||||
4,
|
||||
text.length,
|
||||
com.gh.gamecenter.common.R.color.text_theme
|
||||
).build()
|
||||
holder.binding.copyLibaoCodeIv.visibility = View.VISIBLE
|
||||
holder.binding.copyLibaoCodeIv.setOnClickListener {
|
||||
code.copyTextAndToast("$code 复制成功")
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
holder.binding.libaoCodeTv.text = "礼包码:-"
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (!UserManager.getInstance().isLoggedIn) {
|
||||
holder.binding.libaoSchedulePb.visibility = View.VISIBLE
|
||||
holder.binding.remainingTv.visibility = View.VISIBLE
|
||||
holder.binding.libaoCodeTv.visibility = View.GONE
|
||||
holder.binding.copyLibaoCodeIv.visibility = View.GONE
|
||||
|
||||
initProgressUI(libaoEntity, holder)
|
||||
} else {
|
||||
when (libaoEntity.status) {
|
||||
"linged", "repeatLing", "repeatLinged", "taoed", "repeatTao", "repeatTaoed" -> {
|
||||
holder.binding.libaoSchedulePb.visibility = View.GONE
|
||||
holder.binding.remainingTv.visibility = View.GONE
|
||||
holder.binding.libaoCodeTv.visibility = View.VISIBLE
|
||||
|
||||
val size = libaoEntity.me?.userDataLibaoList?.size ?: 0
|
||||
val code = libaoEntity.me?.userDataLibaoList?.get(size - 1)?.code ?: ""
|
||||
val text = "礼包码:$code"
|
||||
holder.binding.libaoCodeTv.text = SpanBuilder(text).color(
|
||||
holder.binding.root.context,
|
||||
4,
|
||||
text.length,
|
||||
com.gh.gamecenter.common.R.color.text_theme
|
||||
).build()
|
||||
holder.binding.copyLibaoCodeIv.visibility = View.VISIBLE
|
||||
holder.binding.copyLibaoCodeIv.setOnClickListener {
|
||||
code.copyTextAndToast("$code 复制成功")
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
holder.binding.libaoSchedulePb.visibility = View.VISIBLE
|
||||
holder.binding.remainingTv.visibility = View.VISIBLE
|
||||
holder.binding.libaoCodeTv.visibility = View.GONE
|
||||
holder.binding.copyLibaoCodeIv.visibility = View.GONE
|
||||
|
||||
initProgressUI(libaoEntity, holder)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// LibaoUtils.setLiBaoBtnStatusRound(holder.binding.receiveTv, libaoEntity,true, context)
|
||||
LibaoUtils.initLibaoBtn(
|
||||
context,
|
||||
holder.binding.receiveTv,
|
||||
libaoEntity,
|
||||
false,
|
||||
null,
|
||||
true,
|
||||
"游戏详情",
|
||||
"游戏详情"
|
||||
) {
|
||||
notifyItemChanged(position)
|
||||
}
|
||||
if (!libaoEntity.packageName.isNullOrEmpty()) {
|
||||
holder.binding.receiveTv.setOnClickListener {
|
||||
val intent = LibaoDetailActivity.getIntent(context, libaoEntity, true, "游戏详情")
|
||||
if (it.context is Activity) {
|
||||
(it.context as Activity).startActivityForResult(intent, 100)
|
||||
}
|
||||
}
|
||||
}
|
||||
holder.itemView.setOnClickListener {
|
||||
if (isTypeCopy) {
|
||||
// do nothing
|
||||
} else {
|
||||
val intent = LibaoDetailActivity.getIntent(context, libaoEntity, "游戏详情")
|
||||
if (it.context is Activity) {
|
||||
(it.context as Activity).startActivityForResult(intent, 100)
|
||||
}
|
||||
|
||||
NewLogUtils.logGameDetailGiftClick(gameName, gameId, "礼包详情")
|
||||
}
|
||||
}
|
||||
}
|
||||
is MoreViewHolder -> {
|
||||
holder.binding.arrowIv.rotation = if (mIsExpand) 180f else 0f
|
||||
holder.itemView.setOnClickListener {
|
||||
if (!mIsExpand) MtaHelper.onEvent("游戏详情_新", "游戏礼包_展开", gameName)
|
||||
mIsExpand = !mIsExpand
|
||||
notifyDataSetChanged()
|
||||
NewLogUtils.logGameDetailGiftClick(gameName, gameId, "展开")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun initProgressUI(libaoEntity: LibaoEntity, holder: LibaoViewHolder) {
|
||||
val total = libaoEntity.total
|
||||
val available = libaoEntity.available
|
||||
if (total != 0) {
|
||||
val availablePercent = (available) / total.toFloat() * 100
|
||||
val count = when {
|
||||
availablePercent >= 1F -> {
|
||||
availablePercent.toInt()
|
||||
}
|
||||
availablePercent == 0F -> {
|
||||
0
|
||||
}
|
||||
else -> {
|
||||
1
|
||||
}
|
||||
}
|
||||
holder.binding.remainingTv.text = "剩余${count}%"
|
||||
holder.binding.libaoSchedulePb.progress = count
|
||||
}
|
||||
}
|
||||
|
||||
class LibaoViewHolder(var binding: ItemGameLibaoBinding) : RecyclerView.ViewHolder(binding.root)
|
||||
class MoreViewHolder(var binding: ItemGameDetailMoreBinding) : RecyclerView.ViewHolder(binding.root)
|
||||
|
||||
companion object {
|
||||
const val MORE = 0
|
||||
const val LIBAO_ITEM = 1
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,117 @@
|
||||
package com.gh.gamecenter.gamedetail.desc
|
||||
|
||||
import android.content.Context
|
||||
import android.view.LayoutInflater
|
||||
import android.view.ViewGroup
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.gh.common.DefaultUrlHandler
|
||||
import com.gh.common.util.DataCollectionUtils
|
||||
import com.gh.common.util.DirectUtils
|
||||
import com.gh.common.util.LogUtils
|
||||
import com.gh.common.util.NewsUtils
|
||||
import com.gh.gamecenter.common.utils.*
|
||||
import com.gh.gamecenter.core.utils.MtaHelper
|
||||
import com.gh.gamecenter.core.utils.TimeUtils
|
||||
import com.gh.gamecenter.databinding.ItemGameRaidersBinding
|
||||
import com.gh.gamecenter.databinding.ItemGameRaidersFixedTopBinding
|
||||
import com.gh.gamecenter.feature.entity.GameEntity
|
||||
import com.gh.gamecenter.feature.entity.NewsEntity
|
||||
import com.gh.gamecenter.newsdetail.NewsDetailActivity
|
||||
|
||||
class GameRaidersAdapter(
|
||||
val context: Context,
|
||||
val articles: ArrayList<NewsEntity>,
|
||||
val mEntrance: String,
|
||||
val game: GameEntity?
|
||||
) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
|
||||
|
||||
private val mDefaultHorizontalPadding by lazy { com.gh.gamecenter.common.R.dimen.game_detail_item_horizontal_padding.toPx() }
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
|
||||
return if (viewType == TYPE_ARTICLE) {
|
||||
RaidersViewHolder(parent.toBinding())
|
||||
} else {
|
||||
RaidersFixedTopViewHolder(
|
||||
ItemGameRaidersFixedTopBinding.inflate(
|
||||
LayoutInflater.from(context),
|
||||
parent,
|
||||
false
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int = articles.size
|
||||
|
||||
override fun getItemViewType(position: Int): Int {
|
||||
return if (articles[position].priority == Int.MAX_VALUE) {
|
||||
TYPE_ARTICLE_FIXED_TOP
|
||||
} else {
|
||||
TYPE_ARTICLE
|
||||
}
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
|
||||
val params = holder.itemView.layoutParams as RecyclerView.LayoutParams
|
||||
params.leftMargin = if (position == 0) mDefaultHorizontalPadding else 8F.dip2px()
|
||||
params.rightMargin = if (position == itemCount - 1) mDefaultHorizontalPadding else 0F.dip2px()
|
||||
holder.itemView.layoutParams = params
|
||||
|
||||
if (holder is RaidersViewHolder) {
|
||||
val newsEntity = articles[position]
|
||||
holder.binding.root.setRootBackgroundDrawable(com.gh.gamecenter.common.R.drawable.background_shape_white_radius_5)
|
||||
holder.binding.titleTv.setTextColor(com.gh.gamecenter.common.R.color.text_primary.toColor(context))
|
||||
holder.binding.contentTv.setTextColor(com.gh.gamecenter.common.R.color.text_tertiary.toColor(context))
|
||||
holder.binding.timeTv.setTextColor(com.gh.gamecenter.common.R.color.text_tertiary.toColor(context))
|
||||
holder.binding.line.setBackgroundColor(com.gh.gamecenter.common.R.color.ui_divider.toColor(context))
|
||||
holder.binding.titleTv.text = newsEntity.title ?: ""
|
||||
holder.binding.contentTv.text = newsEntity.intro ?: ""
|
||||
holder.binding.timeTv.text =
|
||||
if (TimeUtils.isToday(newsEntity.publishOn)) "今天" else TimeUtils.getFormatTime(newsEntity.publishOn)
|
||||
holder.itemView.setOnClickListener {
|
||||
skipNewsDetail(newsEntity, position)
|
||||
}
|
||||
} else if (holder is RaidersFixedTopViewHolder) {
|
||||
val newsEntity = articles[position]
|
||||
holder.binding.root.setRootBackgroundDrawable(com.gh.gamecenter.common.R.drawable.background_shape_white_radius_5)
|
||||
holder.binding.titleTv.setTextColor(com.gh.gamecenter.common.R.color.text_primary.toColor(context))
|
||||
holder.binding.descTv.setTextColor(com.gh.gamecenter.common.R.color.text_tertiary.toColor(context))
|
||||
holder.binding.titleTv.text = newsEntity.title ?: ""
|
||||
ImageUtils.display(holder.binding.backgroundIv, newsEntity.thumb)
|
||||
holder.binding.descTv.text = newsEntity.type
|
||||
holder.itemView.setOnClickListener {
|
||||
LogUtils.logGameDetailFixedTopArticleClick(game?.id, game?.name, newsEntity.link)
|
||||
|
||||
val isUrlIntercepted = DefaultUrlHandler.interceptUrl(
|
||||
context,
|
||||
newsEntity.link ?: "",
|
||||
"新手攻略"
|
||||
)
|
||||
if (!isUrlIntercepted) {
|
||||
DirectUtils.directToWebView(context, newsEntity.link ?: "")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun skipNewsDetail(article: NewsEntity, position: Int) {
|
||||
DataCollectionUtils.uploadClick(context, "新手攻略", "游戏详情", article.title)
|
||||
|
||||
MtaHelper.onEvent("游戏详情_新", "新手攻略卡片", "${game?.name}+${article.title}")
|
||||
|
||||
// 统计阅读量
|
||||
NewsUtils.statNewsViews(article.id)
|
||||
NewsDetailActivity.startNewsDetailActivity(
|
||||
context, article,
|
||||
mEntrance + "+(游戏详情[" + game?.name + "]:新手攻略-列表[" + (position + 1) + "])"
|
||||
)
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val TYPE_ARTICLE = 123
|
||||
const val TYPE_ARTICLE_FIXED_TOP = 124
|
||||
}
|
||||
|
||||
class RaidersViewHolder(var binding: ItemGameRaidersBinding) : RecyclerView.ViewHolder(binding.root)
|
||||
class RaidersFixedTopViewHolder(var binding: ItemGameRaidersFixedTopBinding) : RecyclerView.ViewHolder(binding.root)
|
||||
}
|
||||
@ -1,37 +1,39 @@
|
||||
package com.gh.gamecenter.gamedetail.detail.adapter
|
||||
package com.gh.gamecenter.gamedetail.desc
|
||||
|
||||
import android.content.Context
|
||||
import android.view.ViewGroup
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.gh.common.databind.BindingAdapters
|
||||
import com.gh.gamecenter.GameDetailActivity
|
||||
import com.gh.gamecenter.common.base.GlobalActivityManager
|
||||
import com.gh.gamecenter.common.utils.*
|
||||
import com.gh.gamecenter.core.utils.MtaHelper
|
||||
import com.gh.gamecenter.core.utils.StringUtils
|
||||
import com.gh.gamecenter.databinding.ItemGameDetailRelatedVersionBinding
|
||||
import com.gh.gamecenter.feature.entity.GameEntity
|
||||
import com.gh.gamecenter.feature.exposure.ExposureEvent
|
||||
import com.gh.gamecenter.feature.game.GameItemViewHolder
|
||||
import com.gh.gamecenter.gamedetail.detail.viewholder.BaseGameDetailItemViewHolder
|
||||
import com.gh.gamecenter.gamedetail.entity.RelatedVersion
|
||||
|
||||
class GameDetailRelatedGameAdapter(
|
||||
private val context: Context,
|
||||
private val game: GameEntity?,
|
||||
private val relatedGameList: ArrayList<GameEntity>,
|
||||
private val entrance: String,
|
||||
private val trackData: BaseGameDetailItemViewHolder.GameDetailModuleTrackData,
|
||||
private val getGameStatus: () -> String
|
||||
class GameRelatedVersionAdapter(
|
||||
private val mContext: Context,
|
||||
private val mGameId: String,
|
||||
private val mGameName: String,
|
||||
private val mGame: GameEntity?,
|
||||
private val mDatas: ArrayList<RelatedVersion>,
|
||||
private val mEntrance: String
|
||||
) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
|
||||
var exposureEventList: ArrayList<ExposureEvent> = arrayListOf()
|
||||
private val maxWidth = context.resources.displayMetrics.widthPixels
|
||||
private val mMaxWidth = mContext.resources.displayMetrics.widthPixels - 32F.dip2px()
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
|
||||
return GameDetailRelatedViewHolder(parent.toBinding())
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int = relatedGameList.size
|
||||
override fun getItemCount(): Int = mDatas.size
|
||||
|
||||
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
|
||||
val gameEntity = relatedGameList.getOrNull(position) ?: return
|
||||
val relatedVersion = mDatas[position]
|
||||
if (holder is GameDetailRelatedViewHolder) {
|
||||
val paddingStart = 16F.dip2px()
|
||||
val isEndOfRow = position >= if (itemCount % 3 == 0) {
|
||||
@ -44,42 +46,48 @@ class GameDetailRelatedGameAdapter(
|
||||
var paddingEnd = if (isEndOfRow) 16F.dip2px() else 0F.dip2px()
|
||||
holder.itemView.layoutParams = if (!isEndOfRow) {
|
||||
paddingEnd += 1
|
||||
ViewGroup.LayoutParams(maxWidth - 56F.dip2px(), ViewGroup.LayoutParams.WRAP_CONTENT)
|
||||
ViewGroup.LayoutParams(mMaxWidth - 24F.dip2px(), ViewGroup.LayoutParams.WRAP_CONTENT)
|
||||
} else {
|
||||
ViewGroup.LayoutParams(maxWidth - 1, ViewGroup.LayoutParams.WRAP_CONTENT)
|
||||
ViewGroup.LayoutParams(mMaxWidth - 1, ViewGroup.LayoutParams.WRAP_CONTENT)
|
||||
}
|
||||
holder.binding.root.setPadding(paddingStart, 8F.dip2px(), paddingEnd, 8F.dip2px())
|
||||
holder.binding.gameNameTv.setTextColor(com.gh.gamecenter.common.R.color.text_primary.toColor(context))
|
||||
val gameEntity = relatedVersion.game ?: return
|
||||
holder.binding.gameNameTv.setTextColor(com.gh.gamecenter.common.R.color.text_primary.toColor(mContext))
|
||||
holder.binding.gameNameTv.text = gameEntity.name
|
||||
BindingAdapters.setGameTags(holder.binding.gameLabelLl, gameEntity)
|
||||
holder.binding.gameIconView.displayGameIcon(gameEntity)
|
||||
holder.binding.gameIconView.setBorderColor(com.gh.gamecenter.common.R.color.resource_border)
|
||||
holder.itemView.setOnClickListener {
|
||||
MtaHelper.onEvent("游戏详情_新", "相关游戏版本", "${mGameName}+${relatedVersion.gameName}")
|
||||
GameDetailActivity.startGameDetailActivity(
|
||||
context,
|
||||
gameEntity.id,
|
||||
mContext,
|
||||
relatedVersion.gameId,
|
||||
StringUtils.buildString(
|
||||
entrance,
|
||||
mEntrance,
|
||||
"+(",
|
||||
"游戏详情",
|
||||
"[",
|
||||
gameEntity.name,
|
||||
relatedVersion.gameName,
|
||||
"]:相关游戏[",
|
||||
(position + 1).toString(),
|
||||
"])"
|
||||
),
|
||||
exposureEventList.safelyGetInRelease(position)
|
||||
)
|
||||
SensorsBridge.trackGameDetailModuleClick(
|
||||
trackData.gameId,
|
||||
trackData.gameName,
|
||||
trackData.gameType,
|
||||
"组件内容",
|
||||
trackData.moduleType,
|
||||
"相关游戏",
|
||||
trackData.sequence,
|
||||
supSequence = position + 1,
|
||||
gameStatus = getGameStatus()
|
||||
SensorsBridge.trackGameDetailPageRelatedGameClick(
|
||||
gameId = mGameId,
|
||||
gameName = mGameName,
|
||||
pageName = GlobalActivityManager.getCurrentPageEntity().pageName,
|
||||
pageId = GlobalActivityManager.getCurrentPageEntity().pageId,
|
||||
pageBusinessId = GlobalActivityManager.getCurrentPageEntity().pageBusinessId,
|
||||
lastPageName = GlobalActivityManager.getLastPageEntity().pageName,
|
||||
lastPageId = GlobalActivityManager.getLastPageEntity().pageId,
|
||||
lastPageBusinessId = GlobalActivityManager.getLastPageEntity().pageBusinessId,
|
||||
downloadStatus = mGame?.downloadStatusChinese ?: "",
|
||||
gameType = mGame?.categoryChinese ?: "",
|
||||
clickGameId = gameEntity.id,
|
||||
clickGameName = gameEntity.name ?: "",
|
||||
clickGameType = gameEntity.categoryChinese
|
||||
)
|
||||
}
|
||||
GameItemViewHolder.initGameSubtitleAndAdLabel(gameEntity, holder.binding.gameSubtitleTv)
|
||||
@ -1,36 +0,0 @@
|
||||
package com.gh.gamecenter.gamedetail.detail
|
||||
|
||||
import android.content.Context
|
||||
import android.util.AttributeSet
|
||||
import androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.view.FixAppBarLayoutBehavior
|
||||
import com.google.android.material.appbar.AppBarLayout
|
||||
import kotlin.math.abs
|
||||
|
||||
class GameDetailAppBarBehavior @JvmOverloads constructor(
|
||||
context: Context,
|
||||
attrs: AttributeSet? = null
|
||||
) : FixAppBarLayoutBehavior(context, attrs) {
|
||||
private var maxScrollHeight = 0
|
||||
|
||||
override fun setTopAndBottomOffset(offset: Int): Boolean {
|
||||
val finalOffset = if (maxScrollHeight > 0 && maxScrollHeight <= abs(offset)) -maxScrollHeight else offset
|
||||
return super.setTopAndBottomOffset(finalOffset)
|
||||
}
|
||||
|
||||
override fun onLayoutChild(parent: CoordinatorLayout, abl: AppBarLayout, layoutDirection: Int): Boolean {
|
||||
calculateMaxScrollHeight(parent, abl)
|
||||
return super.onLayoutChild(parent, abl, layoutDirection)
|
||||
}
|
||||
|
||||
private fun calculateMaxScrollHeight(parent: CoordinatorLayout, child: AppBarLayout) {
|
||||
val recyclerView = parent.findViewById<RecyclerView>(R.id.detailRv) ?: return
|
||||
val parentHeight = parent.measuredHeight
|
||||
val recyclerViewHeight = recyclerView.measuredHeight
|
||||
val childScrollTotalHeight = child.totalScrollRange
|
||||
|
||||
maxScrollHeight = (childScrollTotalHeight - parentHeight + recyclerViewHeight).coerceAtLeast(0)
|
||||
}
|
||||
}
|
||||
@ -1,21 +0,0 @@
|
||||
package com.gh.gamecenter.gamedetail.detail
|
||||
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.gh.gamecenter.common.utils.LeftPagerSnapHelper
|
||||
|
||||
class GameDetailCoverSnapHelper: LeftPagerSnapHelper() {
|
||||
override fun findTargetSnapPosition(
|
||||
layoutManager: RecyclerView.LayoutManager,
|
||||
velocityX: Int,
|
||||
velocityY: Int
|
||||
): Int {
|
||||
val closestChild = findSnapView(layoutManager) ?: return RecyclerView.NO_POSITION
|
||||
val position = layoutManager.getPosition(closestChild)
|
||||
return if (position == RecyclerView.NO_POSITION) {
|
||||
RecyclerView.NO_POSITION
|
||||
} else {
|
||||
val forwardDirection = if (layoutManager.canScrollHorizontally()) velocityX > 0 else velocityY > 0
|
||||
if (forwardDirection) position + 1 else position - 1
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,199 +0,0 @@
|
||||
package com.gh.gamecenter.gamedetail.detail.adapter
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.util.SparseArray
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.ViewGroup.MarginLayoutParams
|
||||
import androidx.constraintlayout.widget.ConstraintLayout
|
||||
import androidx.constraintlayout.widget.ConstraintSet
|
||||
import androidx.core.util.forEach
|
||||
import androidx.core.view.updateLayoutParams
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.facebook.drawee.view.SimpleDraweeView
|
||||
import com.gh.gamecenter.ImageViewerActivity
|
||||
import com.gh.gamecenter.common.base.BaseRecyclerViewHolder
|
||||
import com.gh.gamecenter.common.utils.ImageUtils
|
||||
import com.gh.gamecenter.common.utils.dip2px
|
||||
import com.gh.gamecenter.common.utils.toBinding
|
||||
import com.gh.gamecenter.common.utils.toastInInternalRelease
|
||||
import com.gh.gamecenter.databinding.ItemGameCoverGalleryBinding
|
||||
import com.gh.gamecenter.databinding.ItemGameCoverVideoBinding
|
||||
import com.gh.gamecenter.gamedetail.GameDetailViewModel
|
||||
import com.gh.gamecenter.gamedetail.detail.GameDetailFragment
|
||||
import com.gh.gamecenter.gamedetail.entity.CoverEntity
|
||||
import com.gh.gamecenter.gamedetail.video.TopVideoView
|
||||
import com.lightgame.adapter.BaseRecyclerAdapter
|
||||
import com.shuyu.gsyvideoplayer.builder.GSYVideoOptionBuilder
|
||||
import com.shuyu.gsyvideoplayer.listener.GSYSampleCallBack
|
||||
import com.shuyu.gsyvideoplayer.utils.OrientationUtils
|
||||
|
||||
class GameDetailCoverAdapter(
|
||||
context: Context,
|
||||
private val fragment: GameDetailFragment,
|
||||
private val viewModel: GameDetailViewModel,
|
||||
private val showOrHideCoverFilter: ((Boolean) -> Unit)
|
||||
) : BaseRecyclerAdapter<RecyclerView.ViewHolder>(context) {
|
||||
|
||||
private var coverRecyclerView: RecyclerView? = null
|
||||
private var coverList = arrayListOf<CoverEntity>()
|
||||
private var isSingleGallery = false
|
||||
private var hasSetFixedHeight = false
|
||||
private val imageUrlList = arrayListOf<String>()
|
||||
private val imageViewArray = SparseArray<SimpleDraweeView>()
|
||||
|
||||
fun submitList(data: List<CoverEntity>) {
|
||||
imageUrlList.clear()
|
||||
coverList = ArrayList(data)
|
||||
isSingleGallery = coverList.count { it.gallery != null } == 1
|
||||
coverList.mapNotNullTo(imageUrlList) { it.gallery?.url }
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
|
||||
override fun onAttachedToRecyclerView(recyclerView: RecyclerView) {
|
||||
super.onAttachedToRecyclerView(recyclerView)
|
||||
coverRecyclerView = recyclerView
|
||||
}
|
||||
|
||||
override fun getItemViewType(position: Int): Int {
|
||||
val coverEntity = coverList.getOrNull(position)
|
||||
return when {
|
||||
coverEntity?.video != null -> ITEM_VIDEO
|
||||
else -> ITEM_GALLERY
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
|
||||
return when (viewType) {
|
||||
ITEM_VIDEO -> GameDetailCoverVideoItemViewHolder(parent.toBinding())
|
||||
else -> GameDetailCoverGalleryItemViewHolder(parent.toBinding())
|
||||
}
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int = coverList.size
|
||||
|
||||
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
|
||||
coverList.getOrNull(position)?.let {
|
||||
if (holder is GameDetailCoverVideoItemViewHolder) {
|
||||
bindVideoItem(holder, it, position)
|
||||
}
|
||||
if (holder is GameDetailCoverGalleryItemViewHolder) {
|
||||
bindGalleryItem(holder, it, position)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun bindVideoItem(holder: GameDetailCoverVideoItemViewHolder, entity: CoverEntity, position: Int) {
|
||||
if (position == viewModel.defaultCoverEntity?.index && !hasSetFixedHeight) {
|
||||
holder.binding.root.post {
|
||||
coverRecyclerView?.updateLayoutParams<ViewGroup.LayoutParams> { height = holder.binding.root.height }
|
||||
hasSetFixedHeight = true
|
||||
}
|
||||
}
|
||||
|
||||
val topVideo = entity.video ?: return
|
||||
val orientationUtils = OrientationUtils(mContext as Activity, holder.binding.player)
|
||||
orientationUtils.isEnable = false
|
||||
GSYVideoOptionBuilder()
|
||||
.setIsTouchWigetFull(false)
|
||||
.setIsTouchWiget(false)
|
||||
.setRotateViewAuto(false)
|
||||
.setShowFullAnimation(false)
|
||||
.setSeekRatio(1F)
|
||||
.setUrl(topVideo.url)
|
||||
.setCacheWithPlay(true)
|
||||
.setShowPauseCover(true)
|
||||
.setReleaseWhenLossAudio(false)
|
||||
.setAutoFullWithSize(true)
|
||||
.setDismissControlTime(5000)
|
||||
.setVideoAllCallBack(object : GSYSampleCallBack() {
|
||||
override fun onQuitFullscreen(url: String?, vararg objects: Any) {
|
||||
orientationUtils.backToProtVideo()
|
||||
holder.binding.player.uploadVideoStreamingPlaying("退出全屏")
|
||||
}
|
||||
})
|
||||
.build(holder.binding.player)
|
||||
|
||||
holder.binding.player.gameName = viewModel.game?.name ?: ""
|
||||
holder.binding.player.viewModel = viewModel
|
||||
holder.binding.player.showOrHideCoverFilter = showOrHideCoverFilter
|
||||
holder.binding.player.video = topVideo
|
||||
holder.binding.player.updateThumb(topVideo.poster)
|
||||
|
||||
holder.binding.player.fullscreenButton.setOnClickListener {
|
||||
val horizontalVideoView =
|
||||
holder.binding.player.startWindowFullscreen(mContext, true, true) as? TopVideoView
|
||||
if (horizontalVideoView == null) {
|
||||
toastInInternalRelease("全屏失败,请向技术人员提供具体的操作步骤")
|
||||
return@setOnClickListener
|
||||
}
|
||||
orientationUtils.resolveByClick()
|
||||
horizontalVideoView.uuid = holder.binding.player.uuid
|
||||
horizontalVideoView.viewModel = viewModel
|
||||
horizontalVideoView.video = topVideo
|
||||
horizontalVideoView.updateThumb(topVideo.poster)
|
||||
horizontalVideoView.violenceUpdateMuteStatus()
|
||||
holder.binding.player.uploadVideoStreamingPlaying("开始播放")
|
||||
holder.binding.player.uploadVideoStreamingPlaying("点击全屏")
|
||||
}
|
||||
|
||||
holder.binding.player.observeVolume(fragment)
|
||||
}
|
||||
|
||||
private fun bindGalleryItem(holder: GameDetailCoverGalleryItemViewHolder, entity: CoverEntity, position: Int) {
|
||||
val imageUrl = entity.gallery?.url ?: ""
|
||||
val isLastItem = position == coverList.lastIndex
|
||||
val imageWidth = (entity.gallery?.width ?: return).toInt()
|
||||
val imageHeight = (entity.gallery?.height ?: return).toInt()
|
||||
val isLandscape = imageWidth >= imageHeight
|
||||
val ratio = imageWidth / imageHeight.toFloat()
|
||||
ConstraintSet().also {
|
||||
it.clone(holder.binding.root)
|
||||
it.setDimensionRatio(holder.binding.galleryIv.id, if (isLandscape) "h,344:193" else "")
|
||||
}.applyTo(holder.binding.root)
|
||||
holder.binding.root.updateLayoutParams<MarginLayoutParams> {
|
||||
width = if (isLandscape || isSingleGallery) ViewGroup.LayoutParams.MATCH_PARENT else ViewGroup.LayoutParams.WRAP_CONTENT
|
||||
height = if (isLandscape) ViewGroup.LayoutParams.WRAP_CONTENT else PORTRAIT_IMAGE_HEIGHT_DP.dip2px()
|
||||
rightMargin = if (isLandscape || isSingleGallery || isLastItem) 8F.dip2px() else 0
|
||||
}
|
||||
holder.binding.galleryIv.updateLayoutParams<ConstraintLayout.LayoutParams> {
|
||||
width = if (isLandscape) 0 else (PORTRAIT_IMAGE_HEIGHT_DP.dip2px() * ratio).toInt()
|
||||
height = if (isLandscape) 0 else PORTRAIT_IMAGE_HEIGHT_DP.dip2px()
|
||||
}
|
||||
if (position == viewModel.defaultCoverEntity?.index && !hasSetFixedHeight) {
|
||||
holder.binding.root.post {
|
||||
coverRecyclerView?.updateLayoutParams<ViewGroup.LayoutParams> { height = holder.binding.root.height }
|
||||
hasSetFixedHeight = true
|
||||
}
|
||||
}
|
||||
holder.binding.galleryIv.setTag(ImageUtils.TAG_TARGET_WIDTH, imageWidth)
|
||||
ImageUtils.display(holder.binding.galleryIv, imageUrl)
|
||||
imageViewArray[entity.galleryIndex] = holder.binding.galleryIv
|
||||
holder.binding.root.setOnClickListener {
|
||||
val imageViewList = arrayListOf<View>()
|
||||
imageViewArray.forEach { _, value -> imageViewList.add(value) }
|
||||
val intent = ImageViewerActivity.getIntent(
|
||||
mContext,
|
||||
imageUrlList,
|
||||
entity.galleryIndex,
|
||||
imageViewList,
|
||||
"游戏详情-视频/图片区域"
|
||||
)
|
||||
mContext.startActivity(intent)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val ITEM_VIDEO = 0
|
||||
const val ITEM_GALLERY = 1
|
||||
|
||||
private const val PORTRAIT_IMAGE_HEIGHT_DP = 280F
|
||||
}
|
||||
|
||||
class GameDetailCoverVideoItemViewHolder(val binding: ItemGameCoverVideoBinding) :
|
||||
BaseRecyclerViewHolder<Any>(binding.root)
|
||||
|
||||
class GameDetailCoverGalleryItemViewHolder(val binding: ItemGameCoverGalleryBinding) :
|
||||
BaseRecyclerViewHolder<Any>(binding.root)
|
||||
}
|
||||
@ -1,139 +0,0 @@
|
||||
package com.gh.gamecenter.gamedetail.detail.adapter
|
||||
|
||||
import android.view.ViewGroup
|
||||
import androidx.lifecycle.LifecycleOwner
|
||||
import androidx.recyclerview.widget.DiffUtil.ItemCallback
|
||||
import androidx.recyclerview.widget.ListAdapter
|
||||
import com.gh.gamecenter.common.utils.toBinding
|
||||
import com.gh.gamecenter.feature.view.DownloadButton
|
||||
import com.gh.gamecenter.gamedetail.GameDetailViewModel
|
||||
import com.gh.gamecenter.gamedetail.detail.viewholder.*
|
||||
import com.gh.gamecenter.gamedetail.entity.GameDetailData
|
||||
|
||||
class GameDetailListAdapter(
|
||||
private val downloadBtn: DownloadButton?,
|
||||
private val viewModel: GameDetailViewModel,
|
||||
private val lifecycleOwner: LifecycleOwner
|
||||
) :
|
||||
ListAdapter<GameDetailData, BaseGameDetailItemViewHolder>(createDiffCallback()) {
|
||||
override fun getItemViewType(position: Int): Int {
|
||||
val data = currentList[position]
|
||||
return when {
|
||||
data?.linkContentCard != null -> {
|
||||
when (data.linkContentCard.size) {
|
||||
1 -> ITEM_CONTENT_CARD_SINGLE
|
||||
2 -> ITEM_CONTENT_CARD_DOUBLE
|
||||
else -> ITEM_CONTENT_CARD_TRIPLE
|
||||
}
|
||||
}
|
||||
|
||||
data?.linkAdvertising != null -> if (data.linkAdvertising.img.isEmpty()) ITEM_ADVERTISING else ITEM_ADVERTISING_IMAGE
|
||||
data?.linkComprehensive != null -> ITEM_COMPREHENSIVE_PANEL
|
||||
data?.linkCustomColumn != null -> ITEM_CUSTOM_COLUMN
|
||||
data?.linkDrawer != null -> ITEM_DRAWER
|
||||
data?.linkAnnouncement != null -> ITEM_ANNOUNCEMENT
|
||||
data?.linkGameBrief != null -> ITEM_GAME_BRIEF
|
||||
data?.linkDeveloperWord != null -> ITEM_DEVELOPER_WORD
|
||||
data?.linkUpdate != null -> ITEM_UPDATE
|
||||
data?.linkComment != null -> ITEM_COMMENT
|
||||
data?.linkInfo != null -> ITEM_DETAIL_INFO
|
||||
data?.linkContentRecommend != null -> ITEM_CONTENT_RECOMMEND
|
||||
data?.linkGameVideo != null -> ITEM_GAME_VIDEO
|
||||
data?.linkGameGuide != null -> ITEM_GAME_STRATEGY
|
||||
data?.linkServer != null -> ITEM_SERVER
|
||||
data?.linkLibao != null -> ITEM_GIFT
|
||||
data?.linkRelatedGame != null -> ITEM_RELATED_GAME
|
||||
data?.linkImageRecommend != null -> ITEM_RECOMMEND_IMAGE
|
||||
data?.linkEveryonePlaying != null -> ITEM_RECOMMEND_GAME
|
||||
data?.linkRecommendGameList != null -> ITEM_RECOMMEND_GAME_COLLECTION
|
||||
else -> ITEM_RECOMMEND_COLUMN
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BaseGameDetailItemViewHolder {
|
||||
return when (viewType) {
|
||||
ITEM_CONTENT_CARD_SINGLE -> GameDetailContentCardSingleItemViewHolder(parent.toBinding(), downloadBtn, viewModel, lifecycleOwner)
|
||||
ITEM_CONTENT_CARD_DOUBLE -> GameDetailContentCardDoubleItemViewHolder(parent.toBinding(), downloadBtn, viewModel, lifecycleOwner)
|
||||
ITEM_CONTENT_CARD_TRIPLE -> GameDetailContentCardTripleItemViewHolder(parent.toBinding(), downloadBtn, viewModel, lifecycleOwner)
|
||||
ITEM_ADVERTISING -> GameDetailAdvertisingItemViewHolder(parent.toBinding(), downloadBtn, viewModel)
|
||||
ITEM_ADVERTISING_IMAGE -> GameDetailAdvertisingImageItemViewHolder(parent.toBinding(), downloadBtn, viewModel)
|
||||
ITEM_COMPREHENSIVE_PANEL -> GameDetailComprehensivePanelItemViewHolder(parent.toBinding(), downloadBtn, viewModel)
|
||||
ITEM_CUSTOM_COLUMN -> GameDetailCustomColumnItemViewHolder(parent.toBinding(), downloadBtn, viewModel)
|
||||
ITEM_DRAWER -> GameDetailDrawerItemViewHolder(parent.toBinding(), downloadBtn, viewModel)
|
||||
ITEM_ANNOUNCEMENT -> GameDetailAnnouncementItemViewHolder(parent.toBinding(), downloadBtn, viewModel)
|
||||
ITEM_GAME_BRIEF -> GameDetailBriefItemViewHolder(parent.toBinding(), downloadBtn, viewModel)
|
||||
ITEM_DEVELOPER_WORD -> GameDetailDeveloperWordItemViewHolder(
|
||||
parent.toBinding(),
|
||||
downloadBtn,
|
||||
viewModel
|
||||
)
|
||||
ITEM_UPDATE -> GameDetailUpdateItemViewHolder(parent.toBinding(), downloadBtn, viewModel)
|
||||
ITEM_COMMENT -> GameDetailCommentItemViewHolder(parent.toBinding(), downloadBtn, viewModel)
|
||||
ITEM_DETAIL_INFO -> GameDetailInfoItemViewHolder(parent.toBinding(), downloadBtn, viewModel)
|
||||
ITEM_CONTENT_RECOMMEND -> GameDetailContentRecommendItemViewHolder(parent.toBinding(), downloadBtn, viewModel, lifecycleOwner)
|
||||
ITEM_GAME_VIDEO -> GameDetailVideoItemViewHolder(parent.toBinding(), downloadBtn, viewModel)
|
||||
ITEM_GAME_STRATEGY -> GameDetailStrategyItemViewHolder(parent.toBinding(), downloadBtn, viewModel)
|
||||
ITEM_SERVER -> GameDetailServerItemViewHolder(parent.toBinding(), downloadBtn, viewModel)
|
||||
ITEM_GIFT -> GameDetailGiftItemViewHolder(parent.toBinding(), downloadBtn, viewModel)
|
||||
ITEM_RELATED_GAME -> GameDetailRelatedGameItemViewHolder(parent.toBinding(), downloadBtn, viewModel)
|
||||
ITEM_RECOMMEND_IMAGE -> GameDetailRecommendImageItemViewHolder(parent.toBinding(), downloadBtn, viewModel)
|
||||
ITEM_RECOMMEND_GAME -> GameDetailRecommendGameItemViewHolder(parent.toBinding(), downloadBtn, viewModel)
|
||||
ITEM_RECOMMEND_GAME_COLLECTION -> GameDetailRecommendGameCollectionItemViewHolder(parent.toBinding(), downloadBtn, viewModel)
|
||||
else -> GameDetailRecommendColumnItemViewHolder(parent.toBinding(), downloadBtn, viewModel)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: BaseGameDetailItemViewHolder, position: Int) {
|
||||
val item = getItem(position)
|
||||
holder.bindView(item)
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val ITEM_CONTENT_CARD_SINGLE = 0 // 内容卡片-单个
|
||||
const val ITEM_CONTENT_CARD_DOUBLE = 1 // 内容卡片-两个
|
||||
const val ITEM_CONTENT_CARD_TRIPLE = 2 // 内容卡片-三个
|
||||
const val ITEM_ADVERTISING = 3 // 广告推荐-无图片
|
||||
const val ITEM_ADVERTISING_IMAGE = 4 // 广告推荐-带图片
|
||||
const val ITEM_COMPREHENSIVE_PANEL = 5 // 综合面板
|
||||
const val ITEM_CUSTOM_COLUMN = 6 // 自定义栏目
|
||||
const val ITEM_DRAWER = 7 // 列表抽屉
|
||||
const val ITEM_ANNOUNCEMENT = 8 // 资讯公告
|
||||
const val ITEM_GAME_BRIEF = 9 // 游戏简介
|
||||
const val ITEM_DEVELOPER_WORD = 10 // 开发者的话
|
||||
const val ITEM_UPDATE = 11 // 更新内容
|
||||
const val ITEM_COMMENT = 12 // 玩家评论
|
||||
const val ITEM_DETAIL_INFO = 13 // 详情信息
|
||||
const val ITEM_CONTENT_RECOMMEND = 14 // 内容推荐(PK组件)
|
||||
const val ITEM_GAME_VIDEO = 15 // 视频
|
||||
const val ITEM_GAME_STRATEGY = 16 // 游戏攻略
|
||||
const val ITEM_SERVER = 17 // 游戏开服
|
||||
const val ITEM_GIFT = 18 // 游戏礼包
|
||||
const val ITEM_RELATED_GAME = 19 // 相关游戏
|
||||
const val ITEM_RECOMMEND_IMAGE = 20 // 图片推荐
|
||||
const val ITEM_RECOMMEND_GAME = 21 // 大家都在玩
|
||||
const val ITEM_RECOMMEND_GAME_COLLECTION = 22 // 游戏单推荐
|
||||
const val ITEM_RECOMMEND_COLUMN = 23 // 专题推荐
|
||||
|
||||
fun createDiffCallback() = object : ItemCallback<GameDetailData>() {
|
||||
override fun areItemsTheSame(oldItem: GameDetailData, newItem: GameDetailData): Boolean {
|
||||
return oldItem.areItemsTheSame(newItem)
|
||||
}
|
||||
|
||||
override fun areContentsTheSame(oldItem: GameDetailData, newItem: GameDetailData): Boolean {
|
||||
if (oldItem.linkLibao != null && newItem.linkLibao != null) {
|
||||
return false
|
||||
}
|
||||
if (oldItem.linkEveryonePlaying != null && newItem.linkEveryonePlaying != null) {
|
||||
return false
|
||||
}
|
||||
if (oldItem.linkContentRecommend != null && newItem.linkContentRecommend != null) {
|
||||
return false
|
||||
}
|
||||
if (oldItem.recommendColumn != null && newItem.recommendColumn != null) {
|
||||
return false
|
||||
}
|
||||
return oldItem.areContentsTheSame(newItem)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,330 +0,0 @@
|
||||
package com.gh.gamecenter.gamedetail.detail.adapter
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.ViewGroup.MarginLayoutParams
|
||||
import android.widget.LinearLayout
|
||||
import androidx.core.view.children
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.core.view.updateLayoutParams
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.facebook.drawee.drawable.ScalingUtils
|
||||
import com.facebook.drawee.generic.GenericDraweeHierarchyBuilder
|
||||
import com.facebook.drawee.generic.RoundingParams
|
||||
import com.facebook.drawee.view.SimpleDraweeView
|
||||
import com.gh.common.util.LibaoUtils
|
||||
import com.gh.common.util.NewLogUtils
|
||||
import com.gh.gamecenter.ImageViewerActivity
|
||||
import com.gh.gamecenter.common.databinding.RefreshFooterviewBinding
|
||||
import com.gh.gamecenter.common.utils.*
|
||||
import com.gh.gamecenter.core.utils.MtaHelper
|
||||
import com.gh.gamecenter.core.utils.SpanBuilder
|
||||
import com.gh.gamecenter.databinding.ItemGameDetailMoreBinding
|
||||
import com.gh.gamecenter.databinding.ItemGameLibaoBinding
|
||||
import com.gh.gamecenter.feature.entity.LibaoEntity
|
||||
import com.gh.gamecenter.gamedetail.detail.viewholder.BaseGameDetailItemViewHolder.GameDetailModuleTrackData
|
||||
import com.gh.gamecenter.libao.LibaoDetailActivity
|
||||
import com.gh.gamecenter.login.user.UserManager
|
||||
|
||||
class GameLibaoAdapter(
|
||||
val context: Context,
|
||||
var libaos: ArrayList<LibaoEntity>,
|
||||
val gameName: String,
|
||||
val gameId: String,
|
||||
showExpandIcon: Boolean = true,
|
||||
private val trackData: GameDetailModuleTrackData? = null,
|
||||
private val getGameStatus: (() -> String)? = null
|
||||
) :
|
||||
RecyclerView.Adapter<RecyclerView.ViewHolder>() {
|
||||
|
||||
private var mIsExpand = false
|
||||
private val mShowItemCount: Int = if (showExpandIcon) 3 else Int.MAX_VALUE // 最多展示多少个礼包
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
|
||||
return when(viewType) {
|
||||
LIBAO_ITEM -> LibaoViewHolder(parent.toBinding())
|
||||
FOOTER_ITEM -> FooterViewHolder(parent.toBinding())
|
||||
else -> MoreViewHolder(ItemGameDetailMoreBinding.inflate(LayoutInflater.from(context), parent, false))
|
||||
}
|
||||
}
|
||||
|
||||
override fun getItemViewType(position: Int): Int {
|
||||
return if (libaos.size > mShowItemCount) {
|
||||
if (!mIsExpand) {
|
||||
if (position == mShowItemCount) MORE else LIBAO_ITEM
|
||||
} else {
|
||||
if (position == libaos.size) MORE else LIBAO_ITEM
|
||||
}
|
||||
} else {
|
||||
LIBAO_ITEM
|
||||
}
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int {
|
||||
return if (libaos.size > mShowItemCount) {
|
||||
if (mIsExpand) libaos.size + 1 else mShowItemCount + 1
|
||||
} else {
|
||||
libaos.size
|
||||
}
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
|
||||
when (holder) {
|
||||
is LibaoViewHolder -> {
|
||||
val libaoEntity = libaos[position]
|
||||
holder.bindItem(context, this, gameId, gameName, libaoEntity, trackData, getGameStatus)
|
||||
}
|
||||
is MoreViewHolder -> {
|
||||
holder.binding.arrowIv.rotation = if (mIsExpand) 180f else 0f
|
||||
holder.itemView.setOnClickListener {
|
||||
if (!mIsExpand) MtaHelper.onEvent("游戏详情_新", "游戏礼包_展开", gameName)
|
||||
mIsExpand = !mIsExpand
|
||||
notifyDataSetChanged()
|
||||
NewLogUtils.logGameDetailGiftClick(gameName, gameId, "展开")
|
||||
}
|
||||
}
|
||||
is FooterViewHolder -> {
|
||||
holder.binding.footerviewHint.setTextColor(com.gh.gamecenter.common.R.color.text_instance.toColor(context))
|
||||
holder.binding.footerviewHint.text = "没有更多内容了"
|
||||
holder.binding.footerviewLoading.isVisible = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class LibaoViewHolder(var binding: ItemGameLibaoBinding) : RecyclerView.ViewHolder(binding.root) {
|
||||
fun bindItem(
|
||||
context: Context,
|
||||
adapter: RecyclerView.Adapter<*>,
|
||||
gameId: String,
|
||||
gameName: String,
|
||||
libaoEntity: LibaoEntity,
|
||||
gameDetailModuleTrackData: GameDetailModuleTrackData? = null,
|
||||
getGameStatus: (() -> String)? = null
|
||||
) {
|
||||
val position = bindingAdapterPosition
|
||||
binding.root.updateLayoutParams<MarginLayoutParams> { topMargin = if (position == 0) 0 else 8F.dip2px() }
|
||||
binding.root.background = com.gh.gamecenter.common.R.drawable.bg_shape_f8_radius_8.toDrawable(context)
|
||||
binding.libaoNameTv.setTextColor(com.gh.gamecenter.common.R.color.text_primary.toColor(context))
|
||||
binding.contentTv.setTextColor(com.gh.gamecenter.common.R.color.text_tertiary.toColor(context))
|
||||
binding.remainingTv.setTextColor(com.gh.gamecenter.common.R.color.text_theme.toColor(context))
|
||||
binding.libaoCodeTv.setTextColor(com.gh.gamecenter.common.R.color.text_secondary.toColor(context))
|
||||
|
||||
binding.libaoNameTv.text = libaoEntity.name
|
||||
binding.contentTv.text = libaoEntity.content?.fromHtml()
|
||||
|
||||
binding.horizontalScrollView.goneIf(libaoEntity.materials.isEmpty()) {
|
||||
if (binding.imagesContainer.tag == libaoEntity.id) {
|
||||
binding.imagesContainer.children.forEach { view ->
|
||||
if (view is SimpleDraweeView) {
|
||||
view.hierarchy.roundingParams = RoundingParams().apply {
|
||||
setCornersRadius(4F.dip2px().toFloat())
|
||||
setOverlayColor(com.gh.gamecenter.common.R.color.ui_container_1.toColor(context))
|
||||
}
|
||||
}
|
||||
}
|
||||
return@goneIf
|
||||
}
|
||||
binding.imagesContainer.removeAllViews()
|
||||
val imageViewList = arrayListOf<View>()
|
||||
libaoEntity.materials.forEachIndexed { index, material ->
|
||||
binding.imagesContainer.addView(SimpleDraweeView(context).apply {
|
||||
val roundingParams = RoundingParams().apply {
|
||||
setCornersRadius(4F.dip2px().toFloat())
|
||||
setOverlayColor(com.gh.gamecenter.common.R.color.ui_container_1.toColor(context))
|
||||
}
|
||||
hierarchy = GenericDraweeHierarchyBuilder(resources)
|
||||
.setFadeDuration(500)
|
||||
.setRoundingParams(roundingParams)
|
||||
.setPlaceholderImage(com.gh.gamecenter.common.R.drawable.occupy, ScalingUtils.ScaleType.FIT_XY)
|
||||
.build()
|
||||
ImageUtils.display(this, material.img)
|
||||
}.apply {
|
||||
imageViewList.add(this)
|
||||
setOnClickListener {
|
||||
context.startActivity(ImageViewerActivity.getIntent(context, libaoEntity.getMaterialImgList(), index, imageViewList, null))
|
||||
}
|
||||
}, LinearLayout.LayoutParams(24F.dip2px(), 24F.dip2px()).apply {
|
||||
setMargins(if (index != 0) 16F.dip2px() else 8F.dip2px(), 0, 0, 0)
|
||||
})
|
||||
}
|
||||
binding.imagesContainer.tag = libaoEntity.id
|
||||
}
|
||||
|
||||
val isTypeCopy = libaoEntity.receiveMethod == "copy"
|
||||
if (isTypeCopy) {
|
||||
// 类型为复制,不需要登录也能直接领取
|
||||
binding.libaoSchedulePb.visibility = View.GONE
|
||||
binding.remainingTv.visibility = View.GONE
|
||||
binding.libaoCodeTv.visibility = View.VISIBLE
|
||||
|
||||
val text = "兑换码:${libaoEntity.code}"
|
||||
binding.libaoCodeTv.text = SpanBuilder(text).color(
|
||||
binding.root.context,
|
||||
4,
|
||||
text.length,
|
||||
com.gh.gamecenter.common.R.color.text_theme
|
||||
).build()
|
||||
binding.copyLibaoCodeIv.visibility = View.VISIBLE
|
||||
binding.copyLibaoCodeIv.setOnClickListener {
|
||||
binding.receiveTv.performClick()
|
||||
}
|
||||
} else if (libaoEntity.universal || libaoEntity.status == "check") {
|
||||
//通用码礼包/或者还未添加礼包码时,不显示进度条,显示礼包码
|
||||
binding.libaoSchedulePb.visibility = View.GONE
|
||||
binding.remainingTv.visibility = View.GONE
|
||||
binding.libaoCodeTv.visibility = View.VISIBLE
|
||||
binding.copyLibaoCodeIv.visibility = View.GONE
|
||||
|
||||
if (!UserManager.getInstance().isLoggedIn) {
|
||||
binding.libaoCodeTv.text = "礼包码:-"
|
||||
} else {
|
||||
when (libaoEntity.status) {
|
||||
"linged", "repeatLing", "repeatLinged", "taoed", "repeatTao", "repeatTaoed" -> {
|
||||
val size = libaoEntity.me?.userDataLibaoList?.size ?: 0
|
||||
val code = libaoEntity.me?.userDataLibaoList?.get(size - 1)?.code ?: ""
|
||||
val text = "礼包码:$code"
|
||||
binding.libaoCodeTv.text = SpanBuilder(text).color(
|
||||
binding.root.context,
|
||||
4,
|
||||
text.length,
|
||||
com.gh.gamecenter.common.R.color.text_theme
|
||||
).build()
|
||||
binding.copyLibaoCodeIv.visibility = View.VISIBLE
|
||||
binding.copyLibaoCodeIv.setOnClickListener {
|
||||
code.copyTextAndToast("$code 复制成功")
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
binding.libaoCodeTv.text = "礼包码:-"
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (!UserManager.getInstance().isLoggedIn) {
|
||||
binding.libaoSchedulePb.visibility = View.VISIBLE
|
||||
binding.remainingTv.visibility = View.VISIBLE
|
||||
binding.libaoCodeTv.visibility = View.GONE
|
||||
binding.copyLibaoCodeIv.visibility = View.GONE
|
||||
|
||||
initProgressUI(libaoEntity)
|
||||
} else {
|
||||
when (libaoEntity.status) {
|
||||
"linged", "repeatLing", "repeatLinged", "taoed", "repeatTao", "repeatTaoed" -> {
|
||||
binding.libaoSchedulePb.visibility = View.GONE
|
||||
binding.remainingTv.visibility = View.GONE
|
||||
binding.libaoCodeTv.visibility = View.VISIBLE
|
||||
|
||||
val size = libaoEntity.me?.userDataLibaoList?.size ?: 0
|
||||
val code = libaoEntity.me?.userDataLibaoList?.get(size - 1)?.code ?: ""
|
||||
val text = "礼包码:$code"
|
||||
binding.libaoCodeTv.text = SpanBuilder(text).color(
|
||||
binding.root.context,
|
||||
4,
|
||||
text.length,
|
||||
com.gh.gamecenter.common.R.color.text_theme
|
||||
).build()
|
||||
binding.copyLibaoCodeIv.visibility = View.VISIBLE
|
||||
binding.copyLibaoCodeIv.setOnClickListener {
|
||||
code.copyTextAndToast("$code 复制成功")
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
binding.libaoSchedulePb.visibility = View.VISIBLE
|
||||
binding.remainingTv.visibility = View.VISIBLE
|
||||
binding.libaoCodeTv.visibility = View.GONE
|
||||
binding.copyLibaoCodeIv.visibility = View.GONE
|
||||
|
||||
initProgressUI(libaoEntity)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// LibaoUtils.setLiBaoBtnStatusRound(holder.binding.receiveTv, libaoEntity,true, context)
|
||||
LibaoUtils.initLibaoBtn(
|
||||
context,
|
||||
binding.receiveTv,
|
||||
libaoEntity,
|
||||
false,
|
||||
null,
|
||||
true,
|
||||
"游戏详情",
|
||||
"游戏详情"
|
||||
) {
|
||||
adapter.notifyItemChanged(position)
|
||||
}
|
||||
if (!libaoEntity.packageName.isNullOrEmpty()) {
|
||||
binding.receiveTv.setOnClickListener {
|
||||
val intent = LibaoDetailActivity.getIntent(context, libaoEntity, true, "游戏详情")
|
||||
if (it.context is Activity) {
|
||||
(it.context as Activity).startActivityForResult(intent, LIBAO_REQUEST)
|
||||
}
|
||||
}
|
||||
}
|
||||
itemView.setOnClickListener {
|
||||
if (isTypeCopy) {
|
||||
// do nothing
|
||||
} else {
|
||||
val intent = LibaoDetailActivity.getIntent(context, libaoEntity, "游戏详情")
|
||||
if (it.context is Activity) {
|
||||
(it.context as Activity).startActivityForResult(intent, LIBAO_REQUEST)
|
||||
}
|
||||
|
||||
NewLogUtils.logGameDetailGiftClick(gameName, gameId, "礼包详情")
|
||||
if (gameDetailModuleTrackData != null && getGameStatus != null) {
|
||||
SensorsBridge.trackGameDetailModuleClick(
|
||||
gameDetailModuleTrackData.gameId,
|
||||
gameDetailModuleTrackData.gameName,
|
||||
gameDetailModuleTrackData.gameType,
|
||||
"组件内容",
|
||||
gameDetailModuleTrackData.moduleType,
|
||||
gameDetailModuleTrackData.moduleName,
|
||||
gameDetailModuleTrackData.sequence,
|
||||
libaoEntity.name,
|
||||
position + 1,
|
||||
"libao",
|
||||
libaoEntity.id,
|
||||
libaoEntity.name,
|
||||
getGameStatus()
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun initProgressUI(libaoEntity: LibaoEntity) {
|
||||
val total = libaoEntity.total
|
||||
val available = libaoEntity.available
|
||||
if (total != 0) {
|
||||
val availablePercent = (available) / total.toFloat() * 100
|
||||
val count = when {
|
||||
availablePercent >= 1F -> {
|
||||
availablePercent.toInt()
|
||||
}
|
||||
availablePercent == 0F -> {
|
||||
0
|
||||
}
|
||||
else -> {
|
||||
1
|
||||
}
|
||||
}
|
||||
binding.remainingTv.text = "剩余${count}%"
|
||||
binding.libaoSchedulePb.progress = count
|
||||
}
|
||||
}
|
||||
}
|
||||
class MoreViewHolder(var binding: ItemGameDetailMoreBinding) : RecyclerView.ViewHolder(binding.root)
|
||||
class FooterViewHolder(var binding: RefreshFooterviewBinding) : RecyclerView.ViewHolder(binding.root)
|
||||
|
||||
companion object {
|
||||
const val MORE = 0
|
||||
const val LIBAO_ITEM = 1
|
||||
const val FOOTER_ITEM = 2
|
||||
|
||||
const val LIBAO_REQUEST = 100
|
||||
}
|
||||
}
|
||||
@ -1,95 +0,0 @@
|
||||
package com.gh.gamecenter.gamedetail.detail.viewholder
|
||||
|
||||
import android.content.Context
|
||||
import android.view.View
|
||||
import androidx.annotation.CallSuper
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.gh.download.DownloadManager
|
||||
import com.gh.gamecenter.feature.view.DownloadButton
|
||||
import com.gh.gamecenter.gamedetail.GameDetailViewModel
|
||||
import com.gh.gamecenter.gamedetail.entity.GameDetailData
|
||||
import com.lightgame.download.DownloadStatus
|
||||
|
||||
abstract class BaseGameDetailItemViewHolder(
|
||||
val itemView: View,
|
||||
val downloadBtn: DownloadButton?,
|
||||
val viewModel: GameDetailViewModel
|
||||
) : RecyclerView.ViewHolder(itemView) {
|
||||
protected val context: Context = itemView.context
|
||||
protected var itemData: GameDetailData? = null
|
||||
protected val gameId
|
||||
get() = viewModel.game?.id ?: ""
|
||||
protected val gameName
|
||||
get() = viewModel.game?.name ?: ""
|
||||
protected val gameType
|
||||
get() = viewModel.game?.categoryChinese ?: ""
|
||||
protected val moduleType
|
||||
get() = itemData?.typeChinese ?: ""
|
||||
protected val sequence
|
||||
get() = itemData?.position?.plus(1) ?: 0
|
||||
protected val gameStatus
|
||||
get() = getGameStatus(downloadBtn?.buttonStyle, viewModel)
|
||||
|
||||
protected val baseTrackData
|
||||
get() = GameDetailModuleTrackData(
|
||||
gameId = gameId,
|
||||
gameName = gameName,
|
||||
gameType = gameId,
|
||||
moduleType = moduleType,
|
||||
sequence = sequence,
|
||||
)
|
||||
|
||||
@CallSuper
|
||||
open fun bindView(data: GameDetailData) {
|
||||
itemData = data
|
||||
}
|
||||
|
||||
data class GameDetailModuleTrackData(
|
||||
var gameId: String = "",
|
||||
var gameName: String = "",
|
||||
var gameType: String = "",
|
||||
var gameStatus: String = "",
|
||||
var moduleType: String = "",
|
||||
var moduleName: String = "",
|
||||
var sequence: Int = 0,
|
||||
var subModuleName: String = "",
|
||||
var supSequence: Int = 0
|
||||
)
|
||||
|
||||
companion object {
|
||||
fun getGameStatus(buttonStyle: DownloadButton.ButtonStyle?, viewModel: GameDetailViewModel) = when (buttonStyle) {
|
||||
DownloadButton.ButtonStyle.WAITING,
|
||||
DownloadButton.ButtonStyle.UPDATING,
|
||||
DownloadButton.ButtonStyle.PAUSE,
|
||||
DownloadButton.ButtonStyle.FAILURE,
|
||||
DownloadButton.ButtonStyle.DOWNLOADING_NORMAL,
|
||||
DownloadButton.ButtonStyle.DOWNLOADING_PLUGIN -> "下载中"
|
||||
|
||||
DownloadButton.ButtonStyle.LAUNCH_OR_OPEN -> "已安装"
|
||||
DownloadButton.ButtonStyle.RESERVABLE -> "预约"
|
||||
DownloadButton.ButtonStyle.RESERVED -> "已预约"
|
||||
else -> determineStatus(viewModel)
|
||||
}
|
||||
|
||||
private fun determineStatus(viewModel: GameDetailViewModel): String {
|
||||
viewModel.updateGameStatus()
|
||||
if (viewModel.isGameInstalled) {
|
||||
return "已安装"
|
||||
}
|
||||
|
||||
val downloadEntity = DownloadManager.getInstance().getDownloadEntitySnapshot("", viewModel.gameId)
|
||||
return when (downloadEntity?.status) {
|
||||
DownloadStatus.done -> "待安装"
|
||||
null,
|
||||
DownloadStatus.cancel,
|
||||
DownloadStatus.hijack,
|
||||
DownloadStatus.notfound,
|
||||
DownloadStatus.uncertificated,
|
||||
DownloadStatus.unqualified,
|
||||
DownloadStatus.unavailable,
|
||||
DownloadStatus.banned -> "未下载"
|
||||
else -> "下载中"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,91 +0,0 @@
|
||||
package com.gh.gamecenter.gamedetail.detail.viewholder
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.drawable.Animatable
|
||||
import androidx.constraintlayout.widget.ConstraintLayout
|
||||
import androidx.core.view.updateLayoutParams
|
||||
import com.facebook.drawee.controller.BaseControllerListener
|
||||
import com.facebook.imagepipeline.image.ImageInfo
|
||||
import com.gh.common.util.DirectUtils
|
||||
import com.gh.gamecenter.common.utils.*
|
||||
import com.gh.gamecenter.core.utils.DisplayUtils
|
||||
import com.gh.gamecenter.databinding.ItemGameDetailImageLinkBinding
|
||||
import com.gh.gamecenter.feature.view.DownloadButton
|
||||
import com.gh.gamecenter.gamedetail.GameDetailViewModel
|
||||
import com.gh.gamecenter.gamedetail.entity.GameDetailData
|
||||
import com.gh.gamecenter.gamedetail.entity.GameDetailLink
|
||||
|
||||
class GameDetailAdvertisingImageItemViewHolder(
|
||||
val binding: ItemGameDetailImageLinkBinding,
|
||||
downloadBtn: DownloadButton?,
|
||||
viewModel: GameDetailViewModel
|
||||
) : BaseGameDetailItemViewHolder(binding.root, downloadBtn, viewModel) {
|
||||
override fun bindView(data: GameDetailData) {
|
||||
super.bindView(data)
|
||||
val entity = data.linkAdvertising ?: return
|
||||
bindImageItem(context, binding, entity, false, "游戏详情-广告推荐", baseTrackData) { gameStatus }
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun bindImageItem(
|
||||
context: Context,
|
||||
binding: ItemGameDetailImageLinkBinding,
|
||||
data: GameDetailLink,
|
||||
isAnnouncement: Boolean,
|
||||
entrance: String,
|
||||
trackData: GameDetailModuleTrackData,
|
||||
getGameStatus: () -> String
|
||||
) {
|
||||
binding.run {
|
||||
if (data.img.isNotEmpty()) {
|
||||
imageIv.updateRoundingParams {
|
||||
setOverlayColor(com.gh.gamecenter.common.R.color.ui_surface.toColor(context))
|
||||
}
|
||||
ImageUtils.displayWithCallback(imageIv, data.img, false, object : BaseControllerListener<ImageInfo>() {
|
||||
override fun onFinalImageSet(id: String?, imageInfo: ImageInfo?, animatable: Animatable?) {
|
||||
if (imageInfo == null || imageInfo.height == 0) {
|
||||
return
|
||||
}
|
||||
val scale = imageInfo.width.toFloat() / imageInfo.height.toFloat()
|
||||
maskView.updateLayoutParams<ConstraintLayout.LayoutParams> {
|
||||
height = if (scale > 2F) 40F.dip2px() else 60F.dip2px()
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
iconIv.goneIf(data.componentIcon?.icon.isNullOrEmpty()) {
|
||||
iconIv.setFixedHeight(14)
|
||||
iconIv.setTag(ImageUtils.TAG_TARGET_WIDTH, DisplayUtils.getScreenWidth() - 32F.dip2px())
|
||||
ImageUtils.display(iconIv, data.componentIcon?.icon)
|
||||
}
|
||||
titleTv.setTextColor(com.gh.gamecenter.common.R.color.text_aw_primary.toColor(context))
|
||||
titleTv.text = if (isAnnouncement) data.text else data.title
|
||||
linkTv.goneIf(data.text.isEmpty() || isAnnouncement) {
|
||||
linkTv.text = data.text
|
||||
linkTv.setTextColor(com.gh.gamecenter.common.R.color.text_primary.toColor(context))
|
||||
}
|
||||
arrowIv.goneIf(data.text.isNotEmpty() || isAnnouncement)
|
||||
container.setOnClickListener { _ ->
|
||||
data.link?.let {
|
||||
DirectUtils.directToLinkPage(context, it, entrance, "")
|
||||
SensorsBridge.trackGameDetailModuleClick(
|
||||
trackData.gameId,
|
||||
trackData.gameName,
|
||||
trackData.gameType,
|
||||
"组件内容",
|
||||
trackData.moduleType,
|
||||
trackData.moduleName,
|
||||
trackData.sequence,
|
||||
trackData.subModuleName,
|
||||
trackData.supSequence,
|
||||
it.type,
|
||||
it.link,
|
||||
it.link,
|
||||
getGameStatus()
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,75 +0,0 @@
|
||||
package com.gh.gamecenter.gamedetail.detail.viewholder
|
||||
|
||||
import android.content.Context
|
||||
import androidx.core.view.updateLayoutParams
|
||||
import com.gh.common.util.DirectUtils
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.utils.*
|
||||
import com.gh.gamecenter.core.utils.DisplayUtils
|
||||
import com.gh.gamecenter.databinding.ItemGameDetailLinkBinding
|
||||
import com.gh.gamecenter.feature.view.DownloadButton
|
||||
import com.gh.gamecenter.gamedetail.GameDetailViewModel
|
||||
import com.gh.gamecenter.gamedetail.entity.GameDetailData
|
||||
import com.gh.gamecenter.gamedetail.entity.GameDetailLink
|
||||
|
||||
class GameDetailAdvertisingItemViewHolder(
|
||||
val binding: ItemGameDetailLinkBinding,
|
||||
downloadBtn: DownloadButton?,
|
||||
viewModel: GameDetailViewModel
|
||||
) : BaseGameDetailItemViewHolder(binding.root, downloadBtn, viewModel) {
|
||||
|
||||
override fun bindView(data: GameDetailData) {
|
||||
super.bindView(data)
|
||||
val entity = data.linkAdvertising ?: return
|
||||
bindItem(context, binding, entity, false, "游戏详情-广告推荐", baseTrackData) { gameStatus }
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun bindItem(
|
||||
context: Context,
|
||||
binding: ItemGameDetailLinkBinding,
|
||||
data: GameDetailLink,
|
||||
isAnnouncement: Boolean,
|
||||
entrance: String,
|
||||
trackData: GameDetailModuleTrackData,
|
||||
getGameStatus: () -> String
|
||||
) {
|
||||
binding.run {
|
||||
container.updateLayoutParams { height = if (isAnnouncement) 28F.dip2px() else 40F.dip2px() }
|
||||
container.background = if (isAnnouncement) null else R.drawable.bg_shape_ui_container_1_radius_8_item_style.toDrawable(context)
|
||||
iconIv.goneIf(data.componentIcon?.icon.isNullOrEmpty()) {
|
||||
iconIv.setFixedHeight(14)
|
||||
iconIv.setTag(ImageUtils.TAG_TARGET_WIDTH, DisplayUtils.getScreenWidth() - 32F.dip2px())
|
||||
ImageUtils.display(iconIv, data.componentIcon?.icon)
|
||||
iconIv.updateRoundingParams {
|
||||
setOverlayColor(com.gh.gamecenter.common.R.color.ui_container_1.toColor(context))
|
||||
}
|
||||
}
|
||||
titleTv.setTextColor(com.gh.gamecenter.common.R.color.text_secondary.toColor(context))
|
||||
titleTv.textSize = if (isAnnouncement) 12F else 13F
|
||||
titleTv.text = if (isAnnouncement) data.text else data.title
|
||||
container.setOnClickListener { _ ->
|
||||
data.link?.let {
|
||||
DirectUtils.directToLinkPage(context, it, entrance, "")
|
||||
SensorsBridge.trackGameDetailModuleClick(
|
||||
trackData.gameId,
|
||||
trackData.gameName,
|
||||
trackData.gameType,
|
||||
"组件内容",
|
||||
trackData.moduleType,
|
||||
trackData.moduleName,
|
||||
trackData.sequence,
|
||||
trackData.subModuleName,
|
||||
trackData.supSequence,
|
||||
it.type,
|
||||
it.link,
|
||||
it.link,
|
||||
getGameStatus()
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,101 +0,0 @@
|
||||
package com.gh.gamecenter.gamedetail.detail.viewholder
|
||||
|
||||
import android.view.ViewGroup
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
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.databinding.ItemGameDetailAnnouncementBinding
|
||||
import com.gh.gamecenter.databinding.ItemGameDetailImageLinkBinding
|
||||
import com.gh.gamecenter.databinding.ItemGameDetailLinkBinding
|
||||
import com.gh.gamecenter.feature.view.DownloadButton
|
||||
import com.gh.gamecenter.gamedetail.GameDetailViewModel
|
||||
import com.gh.gamecenter.gamedetail.entity.GameDetailData
|
||||
import com.gh.gamecenter.gamedetail.entity.GameDetailLink
|
||||
|
||||
class GameDetailAnnouncementItemViewHolder(
|
||||
val binding: ItemGameDetailAnnouncementBinding,
|
||||
downloadBtn: DownloadButton?,
|
||||
viewModel: GameDetailViewModel
|
||||
) : BaseGameDetailItemViewHolder(binding.root, downloadBtn, viewModel) {
|
||||
|
||||
override fun bindView(data: GameDetailData) {
|
||||
super.bindView(data)
|
||||
val entity = data.linkAnnouncement ?: return
|
||||
binding.run {
|
||||
titleTv.setTextColor(com.gh.gamecenter.common.R.color.text_primary.toColor(context))
|
||||
titleTv.text = entity.name
|
||||
if (recyclerView.adapter !is GameDetailAnnouncementAdapter) {
|
||||
recyclerView.isNestedScrollingEnabled = false
|
||||
recyclerView.layoutManager = LinearLayoutManager(context)
|
||||
recyclerView.adapter = GameDetailAnnouncementAdapter(entity.data)
|
||||
} else {
|
||||
recyclerView.adapter?.run { notifyItemRangeChanged(0, itemCount) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inner class GameDetailAnnouncementAdapter(val dataList: List<GameDetailLink>) :
|
||||
RecyclerView.Adapter<RecyclerView.ViewHolder>() {
|
||||
override fun getItemViewType(position: Int): Int {
|
||||
val data = dataList[position]
|
||||
return if (data.img.isEmpty()) ITEM_LINK else ITEM_IMAGE_LINK
|
||||
}
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
|
||||
return if (viewType == ITEM_LINK) {
|
||||
GameDetailAnnouncementItemViewHolder(parent.toBinding())
|
||||
} else {
|
||||
GameDetailAnnouncementImageItemViewHolder(parent.toBinding())
|
||||
}
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int = dataList.size
|
||||
|
||||
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
|
||||
val data = dataList.getOrNull(position) ?: return
|
||||
if (holder is GameDetailAnnouncementItemViewHolder) {
|
||||
holder.binding.root.setPadding(4F.dip2px(), 0, 4F.dip2px(), 0)
|
||||
GameDetailAdvertisingItemViewHolder.bindItem(
|
||||
context,
|
||||
holder.binding,
|
||||
data,
|
||||
true,
|
||||
"游戏详情-资讯公告",
|
||||
baseTrackData.apply {
|
||||
moduleName = itemData?.linkAnnouncement?.name ?: ""
|
||||
subModuleName = data.text
|
||||
supSequence = position + 1
|
||||
}) { gameStatus }
|
||||
}
|
||||
if (holder is GameDetailAnnouncementImageItemViewHolder) {
|
||||
holder.binding.root.setPadding(16F.dip2px(), 0, 16F.dip2px(), if (position == itemCount - 1) 0 else 12F.dip2px())
|
||||
GameDetailAdvertisingImageItemViewHolder.bindImageItem(
|
||||
context,
|
||||
holder.binding,
|
||||
data,
|
||||
true,
|
||||
"游戏详情-资讯公告",
|
||||
baseTrackData.apply {
|
||||
moduleName = itemData?.linkAnnouncement?.name ?: ""
|
||||
subModuleName = data.text
|
||||
supSequence = position + 1
|
||||
}
|
||||
) { gameStatus }
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
inner class GameDetailAnnouncementItemViewHolder(val binding: ItemGameDetailLinkBinding) :
|
||||
RecyclerView.ViewHolder(binding.root)
|
||||
|
||||
inner class GameDetailAnnouncementImageItemViewHolder(val binding: ItemGameDetailImageLinkBinding) :
|
||||
RecyclerView.ViewHolder(binding.root)
|
||||
|
||||
companion object {
|
||||
const val ITEM_LINK = 0
|
||||
const val ITEM_IMAGE_LINK = 1
|
||||
}
|
||||
}
|
||||
@ -1,160 +0,0 @@
|
||||
package com.gh.gamecenter.gamedetail.detail.viewholder
|
||||
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.TextView
|
||||
import androidx.core.view.forEach
|
||||
import androidx.core.view.isEmpty
|
||||
import androidx.core.view.isVisible
|
||||
import com.facebook.drawee.view.SimpleDraweeView
|
||||
import com.gh.common.util.DirectUtils
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.constant.Constants
|
||||
import com.gh.gamecenter.common.utils.*
|
||||
import com.gh.gamecenter.databinding.ItemGameDetailBriefAwardBinding
|
||||
import com.gh.gamecenter.databinding.ItemGameDetailBriefBinding
|
||||
import com.gh.gamecenter.databinding.ItemGameDetailBriefTagBinding
|
||||
import com.gh.gamecenter.feature.view.DownloadButton
|
||||
import com.gh.gamecenter.gamedetail.GameDetailViewModel
|
||||
import com.gh.gamecenter.gamedetail.dialog.GameDetailScrollableTextDialogFragment
|
||||
import com.gh.gamecenter.gamedetail.entity.GameBrief
|
||||
import com.gh.gamecenter.gamedetail.entity.GameDetailData
|
||||
import com.gh.gamecenter.tag.TagsActivity
|
||||
import splitties.systemservices.layoutInflater
|
||||
|
||||
class GameDetailBriefItemViewHolder(
|
||||
val binding: ItemGameDetailBriefBinding,
|
||||
downloadBtn: DownloadButton?,
|
||||
viewModel: GameDetailViewModel
|
||||
) : BaseGameDetailItemViewHolder(binding.root, downloadBtn, viewModel) {
|
||||
override fun bindView(data: GameDetailData) {
|
||||
super.bindView(data)
|
||||
val entity = data.linkGameBrief ?: return
|
||||
binding.run {
|
||||
titleTv.setTextColor(com.gh.gamecenter.common.R.color.text_primary.toColor(context))
|
||||
briefTv.setTextColor(com.gh.gamecenter.common.R.color.text_secondary.toColor(context))
|
||||
divider.setBackgroundColor(com.gh.gamecenter.common.R.color.ui_divider.toColor(context))
|
||||
expandTv.background = R.drawable.bg_ui_surface_expand_gradient.toDrawable(context)
|
||||
expandTv.setTextColor(com.gh.gamecenter.common.R.color.text_theme.toColor(context))
|
||||
titleTv.text = entity.name
|
||||
tagScrollView.goneIf(entity.gameTags.isNullOrEmpty()) {
|
||||
bindGamesTags(entity.gameTags)
|
||||
}
|
||||
briefTv.text = TextHelper.getHighlightedSpannableStringThatIsWrappedInsideWrapper(
|
||||
context,
|
||||
entity.des,
|
||||
Constants.DEFAULT_TEXT_WRAPPER_2,
|
||||
highlightedTextClickListener = TextHelper.CopyToClipboardHighlightedTextClick()
|
||||
)
|
||||
briefTv.post {
|
||||
expandTv.isVisible = briefTv.lineCount == 3 && briefTv.layout.getEllipsisCount(2) > 0
|
||||
}
|
||||
expandTv.setOnClickListener {
|
||||
SensorsBridge.trackGameDetailModuleClick(
|
||||
gameId,
|
||||
gameName,
|
||||
gameType,
|
||||
"组件内容",
|
||||
moduleType,
|
||||
entity.name,
|
||||
sequence,
|
||||
gameStatus = gameStatus
|
||||
)
|
||||
GameDetailScrollableTextDialogFragment.show(
|
||||
context,
|
||||
"游戏信息",
|
||||
entity.des
|
||||
)
|
||||
}
|
||||
divider.goneIf(entity.awardData.isEmpty())
|
||||
awardScrollView.goneIf(entity.awardData.isEmpty()) {
|
||||
bindAwards(entity.awardData)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun bindGamesTags(gameTags: List<GameBrief.GameTag>) {
|
||||
if (binding.tagContainer.isEmpty()) {
|
||||
gameTags.forEachIndexed { index, gameTag ->
|
||||
val tagBinding = ItemGameDetailBriefTagBinding.inflate(context.layoutInflater)
|
||||
tagBinding.root.text = gameTag.name
|
||||
tagBinding.root.setOnClickListener {
|
||||
SensorsBridge.trackGameDetailModuleClick(
|
||||
gameId,
|
||||
gameName,
|
||||
gameType,
|
||||
"组件内容",
|
||||
moduleType,
|
||||
itemData?.linkGameBrief?.name,
|
||||
sequence,
|
||||
gameStatus = gameStatus
|
||||
)
|
||||
context.startActivity(
|
||||
TagsActivity.getIntent(
|
||||
context,
|
||||
gameTag.name,
|
||||
gameTag.name,
|
||||
"游戏详情-游戏简介",
|
||||
""
|
||||
)
|
||||
)
|
||||
}
|
||||
binding.tagContainer.addView(
|
||||
tagBinding.root,
|
||||
LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, 24F.dip2px()).apply {
|
||||
leftMargin = if (index == 0) 0 else 4F.dip2px()
|
||||
})
|
||||
}
|
||||
} else {
|
||||
binding.tagContainer.forEach {
|
||||
(it as? TextView)?.run {
|
||||
setTextColor(com.gh.gamecenter.common.R.color.text_tertiary.toColor(context))
|
||||
background = com.gh.gamecenter.common.R.drawable.bg_shape_ui_container_1_stroke_radius_6.toDrawable(context)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun bindAwards(awardList: List<GameBrief.AwardData>) {
|
||||
if (binding.awardContainer.isEmpty()) {
|
||||
awardList.forEachIndexed { index, awardData ->
|
||||
val awardBinding = ItemGameDetailBriefAwardBinding.inflate(context.layoutInflater)
|
||||
awardBinding.iconIv.display(awardData.icon)
|
||||
awardBinding.nameTv.text = awardData.award
|
||||
awardBinding.typeTv.text = awardData.awardType
|
||||
awardBinding.root.setOnClickListener {
|
||||
awardData.link?.let { link ->
|
||||
DirectUtils.directToLinkPage(context, link, "游戏详情-游戏简介", "")
|
||||
SensorsBridge.trackGameDetailModuleClick(
|
||||
gameId,
|
||||
gameName,
|
||||
gameType,
|
||||
"组件内容",
|
||||
moduleType,
|
||||
itemData?.linkGameBrief?.name,
|
||||
sequence,
|
||||
awardData.award,
|
||||
index + 1,
|
||||
link.type,
|
||||
link.link,
|
||||
link.text,
|
||||
gameStatus
|
||||
)
|
||||
}
|
||||
}
|
||||
binding.awardContainer.addView(
|
||||
awardBinding.root,
|
||||
LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, 26F.dip2px()).apply {
|
||||
leftMargin = if (index == 0) 0 else 24F.dip2px()
|
||||
})
|
||||
}
|
||||
} else {
|
||||
binding.awardContainer.forEach {
|
||||
it.findViewById<SimpleDraweeView>(R.id.iconIv)?.updateRoundingParams {
|
||||
setOverlayColor(com.gh.gamecenter.common.R.color.ui_surface.toColor(context))
|
||||
}
|
||||
it.findViewById<TextView>(R.id.nameTv)?.setTextColor(com.gh.gamecenter.common.R.color.text_tertiary.toColor(context))
|
||||
it.findViewById<TextView>(R.id.typeTv)?.setTextColor(com.gh.gamecenter.common.R.color.text_secondary.toColor(context))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,402 +0,0 @@
|
||||
package com.gh.gamecenter.gamedetail.detail.viewholder
|
||||
|
||||
import android.graphics.drawable.ColorDrawable
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.ViewGroup.MarginLayoutParams
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.PopupWindow
|
||||
import android.widget.TextView
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.core.view.updateLayoutParams
|
||||
import androidx.recyclerview.widget.DefaultItemAnimator
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.gh.common.util.*
|
||||
import com.gh.common.util.NewLogUtils
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.base.activity.BaseActivity
|
||||
import com.gh.gamecenter.common.constant.Constants
|
||||
import com.gh.gamecenter.common.exposure.ExposureSource
|
||||
import com.gh.gamecenter.common.utils.*
|
||||
import com.gh.gamecenter.core.utils.SpanBuilder
|
||||
import com.gh.gamecenter.databinding.ItemGameDetailRecyclerViewBinding
|
||||
import com.gh.gamecenter.databinding.SubItemGameDetailCommentBinding
|
||||
import com.gh.gamecenter.entity.RatingComment
|
||||
import com.gh.gamecenter.feature.view.DownloadButton
|
||||
import com.gh.gamecenter.gamedetail.GameDetailViewModel
|
||||
import com.gh.gamecenter.gamedetail.entity.GameDetailData
|
||||
import com.gh.gamecenter.gamedetail.entity.GameDetailTabEntity
|
||||
import com.gh.gamecenter.gamedetail.rating.RatingReplyActivity
|
||||
import com.gh.gamecenter.gamedetail.rating.edit.RatingEditActivity
|
||||
import com.gh.gamecenter.gamedetail.rating.logs.CommentLogsActivity
|
||||
import com.gh.gamecenter.login.user.UserManager
|
||||
import java.util.regex.Pattern
|
||||
|
||||
class GameDetailCommentItemViewHolder(
|
||||
val binding: ItemGameDetailRecyclerViewBinding,
|
||||
downloadBtn: DownloadButton?,
|
||||
viewModel: GameDetailViewModel
|
||||
) : BaseGameDetailItemViewHolder(binding.root, downloadBtn, viewModel) {
|
||||
override fun bindView(data: GameDetailData) {
|
||||
super.bindView(data)
|
||||
val entity = data.linkComment ?: return
|
||||
binding.run {
|
||||
titleTv.setTextColor(com.gh.gamecenter.common.R.color.text_primary.toColor(context))
|
||||
moreTv.setTextColor(com.gh.gamecenter.common.R.color.text_theme.toColor(context))
|
||||
moreTv.setDrawableEnd(R.drawable.ic_auxiliary_arrow_right_text_theme_12.toDrawable(context))
|
||||
titleTv.text = entity.name
|
||||
moreTv.isVisible = true
|
||||
moreTv.text = "更多"
|
||||
moreTv.setOnClickListener {
|
||||
viewModel.performTabSelected(GameDetailTabEntity.TYPE_COMMENT)
|
||||
SensorsBridge.trackGameDetailModuleClick(
|
||||
gameId,
|
||||
gameName,
|
||||
gameType,
|
||||
"右上角",
|
||||
moduleType,
|
||||
entity.name,
|
||||
sequence,
|
||||
gameStatus = gameStatus
|
||||
)
|
||||
}
|
||||
|
||||
if (recyclerView.adapter !is CommentItemAdapter) {
|
||||
recyclerView.isNestedScrollingEnabled = false
|
||||
(recyclerView.itemAnimator as DefaultItemAnimator).supportsChangeAnimations = false
|
||||
recyclerView.layoutManager = LinearLayoutManager(context, RecyclerView.HORIZONTAL, false)
|
||||
recyclerView.adapter = CommentItemAdapter(entity.data)
|
||||
} else {
|
||||
recyclerView.adapter?.run { notifyItemRangeChanged(0, itemCount) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inner class CommentItemAdapter(val dataList: ArrayList<RatingComment>) :
|
||||
RecyclerView.Adapter<RecyclerView.ViewHolder>() {
|
||||
private val path = "游戏详情-玩家评论"
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder =
|
||||
CommentItemViewHolder(parent.toBinding())
|
||||
|
||||
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
|
||||
val commentData = dataList.getOrNull(position) ?: return
|
||||
var isChildLongClick = false
|
||||
if (holder is CommentItemViewHolder) {
|
||||
holder.binding.run {
|
||||
root.background = R.drawable.bg_shape_f8_radius_8.toDrawable(context)
|
||||
root.updateLayoutParams<MarginLayoutParams> {
|
||||
leftMargin = if (position == 0) 16F.dip2px() else 8F.dip2px()
|
||||
rightMargin = if (position == itemCount - 1) 16F.dip2px() else 0
|
||||
}
|
||||
userNameTv.setTextColor(com.gh.gamecenter.common.R.color.text_primary.toColor(context))
|
||||
tvBadgeName.setTextColor(com.gh.gamecenter.common.R.color.text_tertiary.toColor(context))
|
||||
commentTv.setTextColor(com.gh.gamecenter.common.R.color.text_secondary.toColor(context))
|
||||
ipRegionTv.setTextColor(com.gh.gamecenter.common.R.color.text_tertiary.toColor(context))
|
||||
moreIv.setImageResource(R.drawable.game_comment_more)
|
||||
userIcon.display(commentData.user.border, commentData.user.icon, commentData.user.auth?.icon)
|
||||
userNameTv.text = commentData.user.name
|
||||
ratingStar.rating = commentData.star.toFloat()
|
||||
if (commentData.user.badge != null) {
|
||||
sdvUserBadge.visibility = View.VISIBLE
|
||||
tvBadgeName.visibility = View.VISIBLE
|
||||
ImageUtils.display(sdvUserBadge, commentData.user.badge?.icon)
|
||||
tvBadgeName.text = commentData.user.badge?.name
|
||||
} else {
|
||||
sdvUserBadge.visibility = View.GONE
|
||||
tvBadgeName.visibility = View.GONE
|
||||
}
|
||||
commentTv.setExpandCallback {
|
||||
root.performClick()
|
||||
}
|
||||
val p = Pattern.compile(RatingEditActivity.LABEL_REGEX)
|
||||
val m = p.matcher(commentData.content)
|
||||
if (m.find()) {
|
||||
val contents =
|
||||
TextHelper.getCommentLabelSpannableStringBuilder(commentData.content, com.gh.gamecenter.common.R.color.text_theme)
|
||||
commentTv.setTextWithHighlightedTextWrappedInsideWrapper(
|
||||
text = contents,
|
||||
highlightedTextClickListener = TextHelper.DirectToWebViewHighlightedTextClick(
|
||||
context,
|
||||
"游戏详情-玩家评论"
|
||||
)
|
||||
)
|
||||
} else {
|
||||
commentTv.setTextWithHighlightedTextWrappedInsideWrapper(
|
||||
text = commentData.content,
|
||||
highlightedTextClickListener = TextHelper.DirectToWebViewHighlightedTextClick(
|
||||
context,
|
||||
"游戏详情-玩家评论"
|
||||
)
|
||||
)
|
||||
}
|
||||
ipRegionTv.goneIf(!(commentData.source != null && commentData.source.region.isNotEmpty()))
|
||||
ipRegionTv.text = " · ${commentData.source?.region}"
|
||||
when {
|
||||
commentData.isEditContent == null -> {
|
||||
timeTv.setTextColor(com.gh.gamecenter.common.R.color.text_tertiary.toColor(context))
|
||||
timeTv.text = if (commentData.ignore) {
|
||||
val s = "${NewsUtils.getFormattedTime(commentData.time)} 保护期评论不计入总分"
|
||||
SpanBuilder(s).image(s.length - 12, s.length - 11, R.drawable.ic_ignore_rating_tips)
|
||||
.color(context, s.length - 10, s.length, com.gh.gamecenter.common.R.color.text_secondary).build()
|
||||
} else {
|
||||
NewsUtils.getFormattedTime(commentData.time)
|
||||
}
|
||||
}
|
||||
|
||||
commentData.isEditContent!! -> {
|
||||
timeTv.setTextColor(com.gh.gamecenter.common.R.color.text_F56614.toColor(context))
|
||||
timeTv.text = if (commentData.ignore) {
|
||||
"${NewsUtils.getFormattedTime(commentData.time)} 保护期间修改评论 >"
|
||||
} else {
|
||||
"${NewsUtils.getFormattedTime(commentData.time)} 已修改 >"
|
||||
}
|
||||
}
|
||||
|
||||
else -> {
|
||||
timeTv.setTextColor(com.gh.gamecenter.common.R.color.text_F56614.toColor(context))
|
||||
timeTv.text = if (commentData.ignore) {
|
||||
"${NewsUtils.getFormattedTime(commentData.time)} 保护期间修改评论"
|
||||
} else {
|
||||
"${NewsUtils.getFormattedTime(commentData.time)} 已修改"
|
||||
}
|
||||
}
|
||||
}
|
||||
sdvUserBadge.setOnClickListener {
|
||||
DialogUtils.showViewBadgeDialog(context, commentData.user.badge) {
|
||||
DirectUtils.directToBadgeWall(
|
||||
context,
|
||||
commentData.user.id,
|
||||
commentData.user.name,
|
||||
commentData.user.icon
|
||||
)
|
||||
}
|
||||
SensorsBridge.trackGameDetailModuleClick(
|
||||
gameId,
|
||||
gameName,
|
||||
gameType,
|
||||
"组件内容",
|
||||
moduleType,
|
||||
itemData?.linkComment?.name,
|
||||
sequence,
|
||||
subModuleName = "玩家评论列表",
|
||||
supSequence = position + 1,
|
||||
gameStatus = gameStatus
|
||||
)
|
||||
}
|
||||
userIcon.setOnClickListener {
|
||||
DirectUtils.directToHomeActivity(
|
||||
context,
|
||||
commentData.user.id,
|
||||
viewModel.entrance,
|
||||
path
|
||||
)
|
||||
NewLogUtils.logGameDetailCommentClick(
|
||||
viewModel.game?.name ?: "",
|
||||
viewModel.game?.id ?: "",
|
||||
"个人主页"
|
||||
)
|
||||
SensorsBridge.trackGameDetailModuleClick(
|
||||
gameId,
|
||||
gameName,
|
||||
gameType,
|
||||
"组件内容",
|
||||
moduleType,
|
||||
itemData?.linkComment?.name,
|
||||
sequence,
|
||||
subModuleName = "玩家评论列表",
|
||||
supSequence = position + 1,
|
||||
gameStatus = gameStatus
|
||||
)
|
||||
}
|
||||
userNameTv.setOnClickListener {
|
||||
userIcon.performClick()
|
||||
}
|
||||
tvBadgeName.setOnClickListener { sdvUserBadge.performClick() }
|
||||
commentTv.setOnLongClickListener(View.OnLongClickListener {
|
||||
isChildLongClick = true
|
||||
commentData.content.replace(RatingEditActivity.LABEL_REPLACE_REGEX.toRegex(), "")
|
||||
.copyTextAndToast()
|
||||
return@OnLongClickListener true
|
||||
})
|
||||
moreIv.setOnClickListener {
|
||||
showMorePopWindow(it, commentData.user.id == UserManager.getInstance().userId) { text ->
|
||||
when (text) {
|
||||
MORE_COPY -> {
|
||||
commentData.content.replace(RatingEditActivity.LABEL_REPLACE_REGEX.toRegex(), "")
|
||||
.copyTextAndToast()
|
||||
}
|
||||
|
||||
MORE_MODIFY -> {
|
||||
val intent =
|
||||
RatingEditActivity.getPatchIntent(context, viewModel.game!!, commentData)
|
||||
SyncDataBetweenPageHelper.startActivityForResult(
|
||||
context,
|
||||
intent,
|
||||
RATING_PATCH_REQUEST,
|
||||
position
|
||||
)
|
||||
}
|
||||
|
||||
MORE_REPORT -> {
|
||||
context.ifLogin(BaseActivity.mergeEntranceAndPath(viewModel.entrance, path)) {
|
||||
DialogUtils.showReportReasonDialog(
|
||||
context,
|
||||
Constants.REPORT_LIST.toList() as java.util.ArrayList<String>
|
||||
) { reason, desc ->
|
||||
SimpleRequestHelper.reportGameComment(
|
||||
viewModel.game?.id ?: "",
|
||||
commentData.id,
|
||||
if (reason != "其他原因") reason else desc
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MORE_DELETE -> {
|
||||
DialogHelper.showDeleteGameCommentDialog(
|
||||
context,
|
||||
R.string.delete_game_comment.toResString()
|
||||
) {
|
||||
SimpleRequestHelper.deleteGameComment(
|
||||
viewModel.game?.id ?: "",
|
||||
commentData.id
|
||||
) {
|
||||
// 删除列表中的评论(如果当前列表有的话)
|
||||
val index = dataList.indexOfFirst { item ->
|
||||
item.id == commentData.id
|
||||
}
|
||||
if (index != -1) {
|
||||
dataList.removeAt(index)
|
||||
notifyItemRemoved(index)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
timeTv.setOnClickListener {
|
||||
SensorsBridge.trackGameDetailModuleClick(
|
||||
gameId,
|
||||
gameName,
|
||||
gameType,
|
||||
"组件内容",
|
||||
moduleType,
|
||||
itemData?.linkComment?.name,
|
||||
sequence,
|
||||
subModuleName = "玩家评论列表",
|
||||
supSequence = position + 1,
|
||||
gameStatus = gameStatus
|
||||
)
|
||||
if (commentData.isEditContent == null && commentData.ignore) {
|
||||
DialogUtils.showStopServerExplanationDialog(
|
||||
context,
|
||||
if (viewModel.game?.commentDescription?.isNotEmpty() == true)
|
||||
viewModel.game?.commentDescription else context.getString(R.string.rating_protection),
|
||||
viewModel.game?.name
|
||||
?: ""
|
||||
)
|
||||
} else if (commentData.isEditContent == true) {
|
||||
val intent = CommentLogsActivity.getIntent(context, viewModel.game!!.id, commentData.id)
|
||||
context.startActivity(intent)
|
||||
}
|
||||
}
|
||||
root.setOnClickListener {
|
||||
if (isChildLongClick) {
|
||||
isChildLongClick = false
|
||||
return@setOnClickListener
|
||||
}
|
||||
val exposureSource = arrayListOf(
|
||||
ExposureSource("游戏详情"),
|
||||
ExposureSource("详情tab"),
|
||||
ExposureSource("玩家评价"),
|
||||
).toJson()
|
||||
val intent = RatingReplyActivity.getIntent(
|
||||
context = context,
|
||||
gameId = viewModel.game?.id ?: "",
|
||||
commentId = commentData.id,
|
||||
exposureSource = exposureSource,
|
||||
entrance = viewModel.entrance ?: "",
|
||||
path = path
|
||||
)
|
||||
SyncDataBetweenPageHelper.startActivityForResult(
|
||||
context,
|
||||
intent,
|
||||
RATING_REPLY_REQUEST,
|
||||
position
|
||||
)
|
||||
NewLogUtils.logGameDetailCommentClick(
|
||||
viewModel.game?.name ?: "",
|
||||
viewModel.game?.id ?: "",
|
||||
"评论内容"
|
||||
)
|
||||
SensorsBridge.trackGameDetailModuleClick(
|
||||
gameId,
|
||||
gameName,
|
||||
gameType,
|
||||
"组件内容",
|
||||
moduleType,
|
||||
itemData?.linkComment?.name,
|
||||
sequence,
|
||||
subModuleName = "玩家评论列表",
|
||||
supSequence = position + 1,
|
||||
gameStatus = gameStatus
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun showMorePopWindow(v: View, isMyRating: Boolean, clickListener: (String) -> Unit) {
|
||||
val contentList = if (isMyRating) arrayListOf(MORE_COPY, MORE_MODIFY, MORE_DELETE)
|
||||
else arrayListOf(MORE_COPY, MORE_REPORT)
|
||||
|
||||
val inflater = LayoutInflater.from(v.context)
|
||||
val layout = inflater.inflate(com.gh.gamecenter.common.R.layout.layout_popup_container, null)
|
||||
val popupWindow = PopupWindow(
|
||||
layout,
|
||||
LinearLayout.LayoutParams.WRAP_CONTENT,
|
||||
LinearLayout.LayoutParams.WRAP_CONTENT
|
||||
)
|
||||
popupWindow.apply {
|
||||
setBackgroundDrawable(ColorDrawable(0))
|
||||
isTouchable = true
|
||||
isFocusable = true
|
||||
isOutsideTouchable = true
|
||||
}
|
||||
|
||||
val container = layout.findViewById<LinearLayout>(R.id.container)
|
||||
for (text in contentList) {
|
||||
val item = inflater.inflate(R.layout.layout_popup_option_item, container, false)
|
||||
container.addView(item)
|
||||
|
||||
val hitText = item.findViewById<TextView>(R.id.hint_text)
|
||||
hitText.text = text
|
||||
|
||||
item.setOnClickListener {
|
||||
clickListener.invoke(text)
|
||||
popupWindow.dismiss()
|
||||
}
|
||||
}
|
||||
|
||||
popupWindow.showAutoOrientation(v)
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int = dataList.size
|
||||
}
|
||||
|
||||
inner class CommentItemViewHolder(val binding: SubItemGameDetailCommentBinding) :
|
||||
RecyclerView.ViewHolder(binding.root)
|
||||
|
||||
companion object {
|
||||
const val RATING_REPLY_REQUEST = 233
|
||||
const val RATING_PATCH_REQUEST = 234
|
||||
const val MORE_COPY = "复制"
|
||||
const val MORE_MODIFY = "修改"
|
||||
const val MORE_DELETE = "删除"
|
||||
const val MORE_REPORT = "投诉"
|
||||
}
|
||||
}
|
||||
@ -1,313 +0,0 @@
|
||||
package com.gh.gamecenter.gamedetail.detail.viewholder
|
||||
|
||||
import android.graphics.Typeface
|
||||
import android.view.ViewGroup
|
||||
import android.view.ViewGroup.MarginLayoutParams
|
||||
import androidx.constraintlayout.widget.ConstraintSet
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.core.view.updateLayoutParams
|
||||
import androidx.recyclerview.widget.DefaultItemAnimator
|
||||
import androidx.recyclerview.widget.GridLayoutManager
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.gh.common.util.DirectUtils
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.constant.Constants
|
||||
import com.gh.gamecenter.common.utils.*
|
||||
import com.gh.gamecenter.core.utils.ExtraTagHandler
|
||||
import com.gh.gamecenter.databinding.*
|
||||
import com.gh.gamecenter.feature.view.DownloadButton
|
||||
import com.gh.gamecenter.gamedetail.GameDetailViewModel
|
||||
import com.gh.gamecenter.gamedetail.entity.GameDetailComprehensivePanelItem
|
||||
import com.gh.gamecenter.gamedetail.entity.GameDetailComprehensivePanelItem.Companion.FUNCTION_TYPE_ONE_LINE_ONE_POINT
|
||||
import com.gh.gamecenter.gamedetail.entity.GameDetailComprehensivePanelItem.Companion.SHOW_TYPE_PART
|
||||
import com.gh.gamecenter.gamedetail.entity.GameDetailComprehensivePanelItem.ContentData
|
||||
import com.gh.gamecenter.gamedetail.entity.GameDetailData
|
||||
import splitties.views.topPadding
|
||||
|
||||
class GameDetailComprehensivePanelItemViewHolder(
|
||||
val binding: ItemGameDetailComprehensivePanelBinding,
|
||||
downloadBtn: DownloadButton?,
|
||||
viewModel: GameDetailViewModel
|
||||
) : BaseGameDetailItemViewHolder(binding.root, downloadBtn, viewModel) {
|
||||
override fun bindView(data: GameDetailData) {
|
||||
super.bindView(data)
|
||||
val entity = data.linkComprehensive ?: return
|
||||
val dataList = entity.data ?: return
|
||||
binding.run {
|
||||
root.topPadding = if (entity.showName) 0 else 16F.dip2px()
|
||||
panelRv.background = com.gh.gamecenter.common.R.drawable.bg_shape_f8_radius_8.toDrawable(context)
|
||||
titleTv.setTextColor(com.gh.gamecenter.common.R.color.text_primary.toColor(context))
|
||||
titleTv.goneIf(!entity.showName) {
|
||||
titleTv.text = entity.name
|
||||
}
|
||||
if (panelRv.adapter !is ComprehensivePanelAdapter) {
|
||||
panelRv.isNestedScrollingEnabled = false
|
||||
(panelRv.itemAnimator as DefaultItemAnimator).supportsChangeAnimations = false
|
||||
panelRv.layoutManager = LinearLayoutManager(context)
|
||||
panelRv.adapter = ComprehensivePanelAdapter(dataList)
|
||||
} else {
|
||||
if (sequence != panelRv.tag) {
|
||||
(panelRv.adapter as? ComprehensivePanelAdapter)?.dataList = dataList
|
||||
}
|
||||
panelRv.adapter?.run { notifyItemRangeChanged(0, itemCount) }
|
||||
}
|
||||
panelRv.tag = sequence
|
||||
}
|
||||
}
|
||||
|
||||
inner class ComprehensivePanelAdapter(var dataList: List<GameDetailComprehensivePanelItem>) :
|
||||
RecyclerView.Adapter<RecyclerView.ViewHolder>() {
|
||||
override fun getItemViewType(position: Int): Int {
|
||||
val data = dataList[position]
|
||||
return when (data.type) {
|
||||
GameDetailComprehensivePanelItem.TYPE_FUNCTION -> ITEM_FUNCTION
|
||||
GameDetailComprehensivePanelItem.TYPE_FAQ -> ITEM_FAQ
|
||||
else -> ITEM_DECLARATION
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
|
||||
return when (viewType) {
|
||||
ITEM_FUNCTION -> ComprehensivePanelFunctionViewHolder(parent.toBinding())
|
||||
ITEM_FAQ -> ComprehensivePanelFAQViewHolder(parent.toBinding())
|
||||
else -> ComprehensivePanelDeclarationViewHolder(parent.toBinding())
|
||||
}
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
|
||||
val data = dataList.getOrNull(position) ?: return
|
||||
if (holder is ComprehensivePanelFunctionViewHolder) {
|
||||
holder.binding.run {
|
||||
root.updateLayoutParams<MarginLayoutParams> {
|
||||
topMargin = if (position == 0) 0 else 8F.dip2px()
|
||||
}
|
||||
titleTv.goneIf(!data.showTitle) {
|
||||
titleTv.setTextColor(com.gh.gamecenter.common.R.color.text_primary.toColor(context))
|
||||
titleTv.text = data.title
|
||||
}
|
||||
val contentData = data.data ?: return
|
||||
holder.showPart = data.functionType == FUNCTION_TYPE_ONE_LINE_ONE_POINT && data.showType == SHOW_TYPE_PART
|
||||
expandTv.isVisible = viewModel.comprehensivePanelExpandBtnStatusMap.getOrPut("${sequence}${position}") { holder.showPart && contentData.size > data.showRowNum }
|
||||
expandTv.text = if (holder.isExpand) "收起" else "全部"
|
||||
expandTv.setOnClickListener { _ ->
|
||||
holder.isExpand = !holder.isExpand
|
||||
(recyclerView.adapter as? ComprehensivePanelFunctionAdapter)?.dataList =
|
||||
if (holder.showPart && !holder.isExpand) {
|
||||
contentData.take(data.showRowNum)
|
||||
} else {
|
||||
contentData
|
||||
}
|
||||
recyclerView.adapter?.notifyDataSetChanged()
|
||||
expandTv.text = if (holder.isExpand) "收起" else "全部"
|
||||
}
|
||||
val spanCount = if (data.functionType == FUNCTION_TYPE_ONE_LINE_ONE_POINT) 1 else 2
|
||||
val finalContentData = if (holder.showPart && !holder.isExpand) {
|
||||
contentData.take(data.showRowNum)
|
||||
} else {
|
||||
contentData
|
||||
}
|
||||
if (recyclerView.adapter !is ComprehensivePanelFunctionAdapter) {
|
||||
recyclerView.isNestedScrollingEnabled = false
|
||||
(recyclerView.itemAnimator as DefaultItemAnimator).supportsChangeAnimations = false
|
||||
recyclerView.layoutManager = GridLayoutManager(context, spanCount)
|
||||
recyclerView.adapter = ComprehensivePanelFunctionAdapter(data, finalContentData, holder)
|
||||
} else {
|
||||
(recyclerView.layoutManager as? GridLayoutManager)?.spanCount = spanCount
|
||||
(recyclerView.adapter as? ComprehensivePanelFunctionAdapter)?.run {
|
||||
dataList = finalContentData
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (holder is ComprehensivePanelFAQViewHolder) {
|
||||
holder.binding.run {
|
||||
root.updateLayoutParams<MarginLayoutParams> {
|
||||
topMargin = if (position == 0) 0 else 16F.dip2px()
|
||||
bottomMargin = if (position == itemCount - 1) 0 else if (data.showTitle) 12F.dip2px() else 8F.dip2px()
|
||||
}
|
||||
titleTv.goneIf(!data.showTitle) {
|
||||
titleTv.setTextColor(com.gh.gamecenter.common.R.color.text_primary.toColor(context))
|
||||
titleTv.text = data.title
|
||||
}
|
||||
val contentData = data.data ?: return
|
||||
if (recyclerView.adapter !is ComprehensivePanelFAQAdapter) {
|
||||
recyclerView.isNestedScrollingEnabled = false
|
||||
(recyclerView.itemAnimator as DefaultItemAnimator).supportsChangeAnimations = false
|
||||
recyclerView.layoutManager = LinearLayoutManager(context)
|
||||
recyclerView.adapter = ComprehensivePanelFAQAdapter(data.title, contentData)
|
||||
} else {
|
||||
(recyclerView.adapter as? ComprehensivePanelFAQAdapter)?.run {
|
||||
dataList = contentData
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (holder is ComprehensivePanelDeclarationViewHolder) {
|
||||
holder.binding.run {
|
||||
root.updateLayoutParams<MarginLayoutParams> {
|
||||
topMargin = if (position == 0) 0 else 12F.dip2px()
|
||||
}
|
||||
titleTv.goneIf(!data.showTitle) {
|
||||
titleTv.setTextColor(com.gh.gamecenter.common.R.color.text_primary.toColor(context))
|
||||
titleTv.text = data.title
|
||||
}
|
||||
declarationTv.setTextColor(com.gh.gamecenter.common.R.color.text_tertiary.toColor(context))
|
||||
declarationTv.setTextWithInterceptingInternalUrl(
|
||||
data.declaration.dropFontColorInDarkMode(declarationTv.context)
|
||||
.fromHtmlCompat(PicassoImageGetter(declarationTv), ExtraTagHandler())
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int = dataList.size
|
||||
}
|
||||
|
||||
inner class ComprehensivePanelFunctionAdapter(
|
||||
private val gameDetailComprehensivePanelItem: GameDetailComprehensivePanelItem,
|
||||
var dataList: List<ContentData>,
|
||||
private val parentViewHolder: ComprehensivePanelFunctionViewHolder
|
||||
) :
|
||||
RecyclerView.Adapter<ComprehensivePanelFunctionItemViewHolder>() {
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ComprehensivePanelFunctionItemViewHolder =
|
||||
ComprehensivePanelFunctionItemViewHolder(parent.toBinding())
|
||||
|
||||
override fun getItemCount(): Int = dataList.size
|
||||
|
||||
override fun onBindViewHolder(holder: ComprehensivePanelFunctionItemViewHolder, position: Int) {
|
||||
val data = dataList.getOrNull(position) ?: return
|
||||
holder.binding.numberIv.setImageResource(R.drawable.bg_game_detail_comprehensive_panel_function_number)
|
||||
holder.binding.numberTv.run {
|
||||
setTextColor(com.gh.gamecenter.common.R.color.text_aw_primary.toColor(context))
|
||||
setTypeface(Typeface.createFromAsset(context.assets, Constants.DIN_FONT_PATH))
|
||||
text = (position + 1).toString()
|
||||
}
|
||||
holder.binding.contentTv.run {
|
||||
setTextColor(com.gh.gamecenter.common.R.color.text_secondary.toColor(context))
|
||||
maxLines = if (parentViewHolder.showPart && !parentViewHolder.isExpand) 1 else Int.MAX_VALUE
|
||||
text = data.text
|
||||
post {
|
||||
val hasEllipsize = layout.getEllipsisCount(0) > 0
|
||||
if (parentViewHolder.showPart && hasEllipsize && !parentViewHolder.binding.expandTv.isVisible) {
|
||||
parentViewHolder.binding.expandTv.isVisible = true
|
||||
viewModel.comprehensivePanelExpandBtnStatusMap["${sequence}${parentViewHolder.bindingAdapterPosition}"] = true
|
||||
}
|
||||
|
||||
// 计算最后一行是否有足够位置放下 全部/收起 按钮
|
||||
if (position == itemCount - 1) {
|
||||
val lastLine = layout.lineCount - 1
|
||||
val lastLineString = text.substring(layout.getLineStart(lastLine), layout.getLineEnd(lastLine))
|
||||
val distanceToEnd = width - paint.measureText(lastLineString)
|
||||
val showExpandInTheLastLine = distanceToEnd >= parentViewHolder.binding.expandTv.width
|
||||
ConstraintSet().apply {
|
||||
clone(parentViewHolder.binding.root)
|
||||
clear(parentViewHolder.binding.expandTv.id, ConstraintSet.TOP)
|
||||
clear(parentViewHolder.binding.expandTv.id, ConstraintSet.BOTTOM)
|
||||
if (showExpandInTheLastLine) {
|
||||
connect(parentViewHolder.binding.expandTv.id, ConstraintSet.BOTTOM, parentViewHolder.binding.recyclerView.id, ConstraintSet.BOTTOM)
|
||||
} else {
|
||||
connect(parentViewHolder.binding.expandTv.id, ConstraintSet.TOP, parentViewHolder.binding.recyclerView.id, ConstraintSet.BOTTOM)
|
||||
connect(parentViewHolder.binding.expandTv.id, ConstraintSet.BOTTOM, ConstraintSet.PARENT_ID, ConstraintSet.BOTTOM)
|
||||
}
|
||||
}.applyTo(parentViewHolder.binding.root)
|
||||
}
|
||||
}
|
||||
}
|
||||
holder.binding.root.setOnClickListener { _ ->
|
||||
data.link?.let {
|
||||
DirectUtils.directToLinkPage(context, it, "游戏详情-功能说明", "")
|
||||
SensorsBridge.trackGameDetailModuleClick(
|
||||
gameId,
|
||||
gameName,
|
||||
gameType,
|
||||
"组件内容",
|
||||
moduleType,
|
||||
"功能说明",
|
||||
sequence,
|
||||
gameDetailComprehensivePanelItem.title,
|
||||
position + 1,
|
||||
it.type,
|
||||
it.link,
|
||||
it.text,
|
||||
gameStatus
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inner class ComprehensivePanelFAQAdapter(private val subModuleName: String, var dataList: List<ContentData>) :
|
||||
RecyclerView.Adapter<ComprehensivePanelFAQItemViewHolder>() {
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ComprehensivePanelFAQItemViewHolder =
|
||||
ComprehensivePanelFAQItemViewHolder(parent.toBinding())
|
||||
|
||||
override fun getItemCount(): Int = dataList.size
|
||||
|
||||
override fun onBindViewHolder(holder: ComprehensivePanelFAQItemViewHolder, position: Int) {
|
||||
val data = dataList.getOrNull(position) ?: return
|
||||
holder.binding.root.updateLayoutParams<MarginLayoutParams> {
|
||||
topMargin = if (position == 0) 0 else 8F.dip2px()
|
||||
}
|
||||
holder.binding.root.background = R.drawable.bg_shape_ui_surface_radius_4_item_style.toDrawable(context)
|
||||
holder.binding.contentTv.run {
|
||||
setTextColor(com.gh.gamecenter.common.R.color.text_secondary.toColor(context))
|
||||
text = data.text
|
||||
}
|
||||
holder.binding.arrowIv.goneIf(data.link == null) {
|
||||
holder.binding.arrowIv.setImageResource(R.drawable.ic_auxiliary_arrow_right_8)
|
||||
}
|
||||
holder.binding.root.setOnClickListener { _ ->
|
||||
data.link?.let {
|
||||
DirectUtils.directToLinkPage(context, it, "游戏详情-功能说明", "")
|
||||
SensorsBridge.trackGameDetailModuleClick(
|
||||
gameId,
|
||||
gameName,
|
||||
gameType,
|
||||
"组件内容",
|
||||
moduleType,
|
||||
"功能说明",
|
||||
sequence,
|
||||
subModuleName,
|
||||
position + 1,
|
||||
it.type,
|
||||
it.link,
|
||||
it.text,
|
||||
gameStatus
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inner class ComprehensivePanelFunctionViewHolder(val binding: ItemGameDetailComprehensivePanelRvBinding) :
|
||||
RecyclerView.ViewHolder(binding.root) {
|
||||
var showPart: Boolean = false
|
||||
var isExpand = false
|
||||
get() = viewModel.comprehensivePanelExpandTextStatusMap.getOrPut("${sequence}${bindingAdapterPosition}") { !showPart }
|
||||
set(value) {
|
||||
viewModel.comprehensivePanelExpandTextStatusMap["${sequence}${bindingAdapterPosition}"] = value
|
||||
field = value
|
||||
}
|
||||
}
|
||||
|
||||
inner class ComprehensivePanelFAQViewHolder(val binding: ItemGameDetailComprehensivePanelRvBinding) :
|
||||
RecyclerView.ViewHolder(binding.root)
|
||||
|
||||
inner class ComprehensivePanelDeclarationViewHolder(val binding: ItemGameDetailComprehensivePanelDeclarationBinding) :
|
||||
RecyclerView.ViewHolder(binding.root)
|
||||
|
||||
inner class ComprehensivePanelFunctionItemViewHolder(val binding: ItemGameDetailComprehensivePanelFunctionBinding) :
|
||||
RecyclerView.ViewHolder(binding.root)
|
||||
|
||||
inner class ComprehensivePanelFAQItemViewHolder(val binding: ItemGameDetailComprehensivePanelFaqBinding) :
|
||||
RecyclerView.ViewHolder(binding.root)
|
||||
|
||||
companion object {
|
||||
const val ITEM_FUNCTION = 0
|
||||
const val ITEM_FAQ = 1
|
||||
const val ITEM_DECLARATION = 2
|
||||
}
|
||||
}
|
||||
@ -1,69 +0,0 @@
|
||||
package com.gh.gamecenter.gamedetail.detail.viewholder
|
||||
|
||||
import androidx.lifecycle.LifecycleOwner
|
||||
import com.gh.gamecenter.databinding.ItemGameDetailContentCardDoubleBinding
|
||||
import com.gh.gamecenter.databinding.LayoutGameDetailContentCardBinding
|
||||
import com.gh.gamecenter.feature.view.DownloadButton
|
||||
import com.gh.gamecenter.gamedetail.GameDetailViewModel
|
||||
import com.gh.gamecenter.gamedetail.entity.ContentCardEntity
|
||||
import com.gh.gamecenter.gamedetail.entity.GameDetailData
|
||||
|
||||
class GameDetailContentCardDoubleItemViewHolder(
|
||||
val binding: ItemGameDetailContentCardDoubleBinding,
|
||||
downloadBtn: DownloadButton?,
|
||||
viewModel: GameDetailViewModel,
|
||||
private val lifecycleOwner: LifecycleOwner
|
||||
) :
|
||||
BaseGameDetailItemViewHolder(binding.root, downloadBtn, viewModel) {
|
||||
override fun bindView(data: GameDetailData) {
|
||||
super.bindView(data)
|
||||
data.linkContentCard?.let {
|
||||
val getGameStatus = { gameStatus }
|
||||
bindContentCard(
|
||||
lifecycleOwner,
|
||||
viewModel,
|
||||
it.first(),
|
||||
binding.firstCardContainer,
|
||||
baseTrackData.apply { supSequence = 0 },
|
||||
getGameStatus
|
||||
)
|
||||
bindContentCard(
|
||||
lifecycleOwner,
|
||||
viewModel,
|
||||
it[1],
|
||||
binding.secondCardContainer,
|
||||
baseTrackData.apply { supSequence = 1 },
|
||||
getGameStatus
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun bindContentCard(
|
||||
lifecycleOwner: LifecycleOwner,
|
||||
viewModel: GameDetailViewModel,
|
||||
contentCardEntity: ContentCardEntity,
|
||||
itemBinding: LayoutGameDetailContentCardBinding,
|
||||
trackData: GameDetailModuleTrackData,
|
||||
getGameStatus: () -> String
|
||||
) {
|
||||
itemBinding.run {
|
||||
GameDetailContentCardSingleItemViewHolder.bindContentCard(
|
||||
root.context,
|
||||
lifecycleOwner,
|
||||
viewModel,
|
||||
contentCardEntity,
|
||||
root,
|
||||
titleTv,
|
||||
iconIv,
|
||||
contentTv,
|
||||
contentBannerView,
|
||||
redDotTv,
|
||||
newIv,
|
||||
trackData,
|
||||
getGameStatus
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,281 +0,0 @@
|
||||
package com.gh.gamecenter.gamedetail.detail.viewholder
|
||||
|
||||
import android.content.Context
|
||||
import android.widget.ImageView
|
||||
import android.widget.TextView
|
||||
import androidx.constraintlayout.widget.ConstraintLayout
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.lifecycle.LifecycleOwner
|
||||
import com.facebook.drawee.view.SimpleDraweeView
|
||||
import com.gh.common.constant.Config
|
||||
import com.gh.common.util.DirectUtils
|
||||
import com.gh.common.util.NewFlatLogUtils
|
||||
import com.gh.gamecenter.ShellActivity
|
||||
import com.gh.gamecenter.ShellActivity.Type
|
||||
import com.gh.gamecenter.WebActivity
|
||||
import com.gh.gamecenter.common.entity.LinkEntity
|
||||
import com.gh.gamecenter.common.exposure.ExposureSource
|
||||
import com.gh.gamecenter.common.utils.*
|
||||
import com.gh.gamecenter.common.view.TextBannerView
|
||||
import com.gh.gamecenter.core.utils.TimeUtils
|
||||
import com.gh.gamecenter.databinding.ItemGameDetailContentCardSingleBinding
|
||||
import com.gh.gamecenter.feature.entity.MeEntity
|
||||
import com.gh.gamecenter.feature.exposure.ExposureEvent
|
||||
import com.gh.gamecenter.feature.view.DownloadButton
|
||||
import com.gh.gamecenter.gamedetail.GameDetailViewModel
|
||||
import com.gh.gamecenter.gamedetail.entity.ContentCardEntity
|
||||
import com.gh.gamecenter.gamedetail.entity.ContentCardEntity.Companion.TYPE_ARCHIVE
|
||||
import com.gh.gamecenter.gamedetail.entity.ContentCardEntity.Companion.TYPE_BBS
|
||||
import com.gh.gamecenter.gamedetail.entity.ContentCardEntity.Companion.TYPE_GIFT
|
||||
import com.gh.gamecenter.gamedetail.entity.ContentCardEntity.Companion.TYPE_RELATED_VERSION
|
||||
import com.gh.gamecenter.gamedetail.entity.ContentCardEntity.Companion.TYPE_SERVER
|
||||
import com.gh.gamecenter.gamedetail.entity.ContentCardEntity.Companion.TYPE_TOOLKIT
|
||||
import com.gh.gamecenter.gamedetail.entity.ContentCardEntity.Companion.TYPE_ZONE
|
||||
import com.gh.gamecenter.gamedetail.entity.GameDetailData
|
||||
import com.gh.gamecenter.gamedetail.entity.GameDetailTabEntity
|
||||
import com.gh.gamecenter.gamedetail.fuli.kaifu.ServersCalendarActivity
|
||||
import com.gh.gamecenter.gamedetail.libao.LibaoListFragment
|
||||
import com.gh.gamecenter.livedata.Event
|
||||
import com.gh.gamecenter.newsdetail.NewsDetailActivity
|
||||
import kotlin.math.abs
|
||||
|
||||
class GameDetailContentCardSingleItemViewHolder(
|
||||
val binding: ItemGameDetailContentCardSingleBinding,
|
||||
downloadBtn: DownloadButton?,
|
||||
viewModel: GameDetailViewModel,
|
||||
private val lifecycleOwner: LifecycleOwner,
|
||||
) : BaseGameDetailItemViewHolder(binding.root, downloadBtn, viewModel) {
|
||||
|
||||
override fun bindView(data: GameDetailData) {
|
||||
super.bindView(data)
|
||||
val contentCardEntity = data.linkContentCard?.first() ?: return
|
||||
binding.run {
|
||||
bindContentCard(
|
||||
context,
|
||||
lifecycleOwner,
|
||||
viewModel,
|
||||
contentCardEntity,
|
||||
container,
|
||||
titleTv,
|
||||
iconIv,
|
||||
contentTv,
|
||||
contentBannerView,
|
||||
redDotTv,
|
||||
newIv,
|
||||
baseTrackData.apply { supSequence = 0 }
|
||||
) { gameStatus }
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
fun bindContentCard(
|
||||
context: Context,
|
||||
lifecycleOwner: LifecycleOwner,
|
||||
viewModel: GameDetailViewModel,
|
||||
contentCardEntity: ContentCardEntity,
|
||||
containerView: ConstraintLayout,
|
||||
titleTv: TextView,
|
||||
iconIv: SimpleDraweeView,
|
||||
contentTv: TextView,
|
||||
contentBannerView: TextBannerView,
|
||||
redDotTv: TextView,
|
||||
newIv: ImageView,
|
||||
trackData: GameDetailModuleTrackData,
|
||||
getGameStatus: () -> String
|
||||
) {
|
||||
if (contentCardEntity.id == containerView.tag) {
|
||||
if (contentBannerView.isVisible) contentBannerView.updateView()
|
||||
containerView.background = com.gh.gamecenter.common.R.drawable.bg_shape_f8_radius_8.toDrawable(context)
|
||||
titleTv.setTextColor(com.gh.gamecenter.common.R.color.text_primary.toColor(context))
|
||||
contentTv.setTextColor(com.gh.gamecenter.common.R.color.text_tertiary.toColor(context))
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
containerView.tag = contentCardEntity.id
|
||||
titleTv.text = contentCardEntity.title
|
||||
ImageUtils.display(iconIv, contentCardEntity.icon)
|
||||
|
||||
val showContentTv =
|
||||
contentCardEntity.showDes && (contentCardEntity.des.isNotEmpty() || contentCardEntity.link.type == TYPE_GIFT)
|
||||
contentTv.visibleIf(showContentTv) {
|
||||
contentTv.text =
|
||||
if (contentCardEntity.link.type == TYPE_GIFT && contentCardEntity.des.isEmpty()) "${contentCardEntity.libao?.total}个游戏礼包" else contentCardEntity.des
|
||||
contentTv.setTextColor(com.gh.gamecenter.common.R.color.text_tertiary.toColor(context))
|
||||
}
|
||||
|
||||
val showContentBannerView =
|
||||
contentCardEntity.showDes && contentCardEntity.link.type == TYPE_SERVER && contentCardEntity.server != null && contentCardEntity.des.isEmpty()
|
||||
contentBannerView.goneIf(!showContentBannerView) {
|
||||
val server = contentCardEntity.server ?: return@goneIf
|
||||
val nowTime = System.currentTimeMillis()
|
||||
var timeDiff = 0L
|
||||
var closestIndex = 0
|
||||
val bannerTextDataList = server.calendar.mapIndexed { index, serverCalendarEntity ->
|
||||
val diff = abs(nowTime - serverCalendarEntity.getTime() * 1000L)
|
||||
if (diff < timeDiff || index == 0) {
|
||||
timeDiff = diff
|
||||
closestIndex = index
|
||||
}
|
||||
val serverTime =
|
||||
if (TimeUtils.isToday(serverCalendarEntity.getTime()))
|
||||
serverCalendarEntity.getFormatTime("今天 HH:mm")
|
||||
else if (TimeUtils.isTomorrow(serverCalendarEntity.getTime()))
|
||||
serverCalendarEntity.getFormatTime("明天 HH:mm")
|
||||
else
|
||||
serverCalendarEntity.getFormatTime("MM-dd HH:mm")
|
||||
TextBannerView.BannerTextData("${serverTime ?: ""} ${serverCalendarEntity.type}")
|
||||
}
|
||||
contentBannerView.setDataList(bannerTextDataList, closestIndex)
|
||||
contentBannerView.startBannerLoop()
|
||||
}
|
||||
|
||||
redDotTv.goneIf(!((contentCardEntity.link.type == TYPE_SERVER && contentCardEntity.server?.total != 0) || contentCardEntity.link.type == TYPE_GIFT)) {
|
||||
if ((contentCardEntity.link.type == TYPE_SERVER) && (contentCardEntity.server?.calendar?.isNotEmpty() == true))
|
||||
redDotTv.text = contentCardEntity.server?.total.toString()
|
||||
if ((contentCardEntity.link.type == TYPE_GIFT) && (contentCardEntity.libao != null))
|
||||
redDotTv.text = contentCardEntity.libao?.total.toString()
|
||||
}
|
||||
|
||||
val showNewTag = contentCardEntity.link.type == TYPE_ARCHIVE && contentCardEntity.archive != null && contentCardEntity.showNewTag
|
||||
newIv.goneIf(!showNewTag)
|
||||
|
||||
containerView.setOnClickListener {
|
||||
NewFlatLogUtils.logGameDetailGameContentCardClick(
|
||||
contentCardEntity.title ?: "",
|
||||
viewModel.game?.name ?: "",
|
||||
viewModel.game?.id ?: "",
|
||||
contentCardEntity.link.type ?: "",
|
||||
contentCardEntity.link.link ?: "",
|
||||
contentCardEntity.link.text ?: ""
|
||||
)
|
||||
SensorsBridge.trackGameDetailModuleClick(
|
||||
gameId = trackData.gameId,
|
||||
gameName = trackData.gameName,
|
||||
gameType = trackData.gameType,
|
||||
contentType = "组件内容",
|
||||
moduleType = trackData.moduleType,
|
||||
moduleName = trackData.moduleName,
|
||||
sequence = trackData.sequence,
|
||||
linkText = contentCardEntity.link.text ?: "",
|
||||
linkType = contentCardEntity.link.type ?: "",
|
||||
linkId = contentCardEntity.id,
|
||||
gameStatus = getGameStatus()
|
||||
)
|
||||
|
||||
val dialog = contentCardEntity.dialog
|
||||
if (dialog != null) {// 展示内容卡片提示弹窗
|
||||
DialogHelper.showDialog(
|
||||
context = context,
|
||||
title = dialog.title ?: "",
|
||||
content = dialog.body ?: "",
|
||||
confirmText = context.getString(com.gh.gamecenter.common.R.string.confirm),
|
||||
cancelText = context.getString(com.gh.gamecenter.common.R.string.cancel),
|
||||
confirmClickCallback = {
|
||||
jumpToContentCardLink(context, contentCardEntity, viewModel)
|
||||
}
|
||||
)
|
||||
} else {
|
||||
jumpToContentCardLink(context, contentCardEntity, viewModel)
|
||||
}
|
||||
}
|
||||
|
||||
viewModel.contentCardClickedLiveData.observe(lifecycleOwner) {
|
||||
if (it.peekContent() == contentCardEntity.link.type) {
|
||||
it.getContentWithHandled()?.let { containerView.performClick() }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun jumpToContentCardLink(context: Context, contentCardEntity: ContentCardEntity, viewModel: GameDetailViewModel) {
|
||||
val path = "游戏详情->内容卡片"
|
||||
when (contentCardEntity.link.type) {
|
||||
TYPE_GIFT,
|
||||
TYPE_ARCHIVE -> {
|
||||
val type = if (contentCardEntity.link.type == TYPE_GIFT) GameDetailTabEntity.TYPE_GIFT else GameDetailTabEntity.TYPE_ARCHIVE
|
||||
val tabList = viewModel.gameDetailTabListLiveData.value?.data
|
||||
if (tabList?.find { it.type == type } != null) {
|
||||
viewModel.performTabSelected(type)
|
||||
} else if (contentCardEntity.link.type == TYPE_GIFT) {
|
||||
val bundle = LibaoListFragment.getBundle(viewModel.game, false)
|
||||
context.startActivity(ShellActivity.getIntent(context, Type.SIMPLE_LIBAO_LIST, bundle))
|
||||
} else if (contentCardEntity.link.type == TYPE_ARCHIVE) {
|
||||
DirectUtils.directToCloudArchive(context, viewModel.game?.id ?: "", viewModel.game?.name ?: "", "", "游戏详情页-内容卡片")
|
||||
}
|
||||
}
|
||||
|
||||
TYPE_SERVER -> {
|
||||
if (viewModel.game != null && contentCardEntity.server != null) {
|
||||
context.startActivity(
|
||||
ServersCalendarActivity.getIntent(
|
||||
context,
|
||||
viewModel.game!!, contentCardEntity.server!!,
|
||||
MeEntity()
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
TYPE_RELATED_VERSION -> {
|
||||
viewModel.scrollToListPositionLiveData.postValue(Event(LinkEntity(type = GameDetailData.TYPE_RELATED_GAME)))
|
||||
}
|
||||
|
||||
TYPE_ZONE -> {
|
||||
if (contentCardEntity.zoneTab && viewModel.game?.zone != null && viewModel.game?.zone!!.style == "link") {
|
||||
context.startActivity(
|
||||
WebActivity.getIntent(
|
||||
context,
|
||||
viewModel.game?.zone!!.link,
|
||||
true
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
TYPE_BBS -> {
|
||||
val funcBbs = contentCardEntity.funcBbs
|
||||
funcBbs?.let {
|
||||
DirectUtils.directForumDetail(context, it.link, path)
|
||||
}
|
||||
}
|
||||
|
||||
TYPE_TOOLKIT -> {
|
||||
if (contentCardEntity.toolkit.isNotEmpty()) {
|
||||
contentCardEntity.toolkit.safelyGetInRelease(0)?.let {
|
||||
val url = it.url
|
||||
if (url != null && url.contains(Config.URL_ARTICLE)) {
|
||||
val newsId = url.substring(url.lastIndexOf("/") + 1, url.length - 5) // 5: ".html"
|
||||
val intent = NewsDetailActivity.getIntentById(context, newsId, path)
|
||||
context.startActivity(intent)
|
||||
} else {
|
||||
context.startActivity(
|
||||
WebActivity.getWebByCollectionTools(
|
||||
context,
|
||||
it,
|
||||
false
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
else -> DirectUtils.directToLinkPage(
|
||||
context,
|
||||
contentCardEntity.link,
|
||||
viewModel.entrance ?: "",
|
||||
path,
|
||||
ExposureEvent.createEvent(
|
||||
null,
|
||||
listOf(
|
||||
ExposureSource("游戏详情", viewModel.game?.id ?: ""),
|
||||
ExposureSource("内容卡片", contentCardEntity.id)
|
||||
)
|
||||
),
|
||||
"游戏详情页-内容卡片"
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,46 +0,0 @@
|
||||
package com.gh.gamecenter.gamedetail.detail.viewholder
|
||||
|
||||
import androidx.lifecycle.LifecycleOwner
|
||||
import com.gh.gamecenter.databinding.ItemGameDetailContentCardTripleBinding
|
||||
import com.gh.gamecenter.feature.view.DownloadButton
|
||||
import com.gh.gamecenter.gamedetail.GameDetailViewModel
|
||||
import com.gh.gamecenter.gamedetail.detail.viewholder.GameDetailContentCardDoubleItemViewHolder.Companion.bindContentCard
|
||||
import com.gh.gamecenter.gamedetail.entity.GameDetailData
|
||||
|
||||
class GameDetailContentCardTripleItemViewHolder(
|
||||
val binding: ItemGameDetailContentCardTripleBinding,
|
||||
downloadBtn: DownloadButton?,
|
||||
viewModel: GameDetailViewModel,
|
||||
private val lifecycleOwner: LifecycleOwner
|
||||
) : BaseGameDetailItemViewHolder(binding.root, downloadBtn, viewModel) {
|
||||
override fun bindView(data: GameDetailData) {
|
||||
super.bindView(data)
|
||||
data.linkContentCard?.let {
|
||||
val getGameStatus = { gameStatus }
|
||||
bindContentCard(
|
||||
lifecycleOwner,
|
||||
viewModel,
|
||||
it.first(),
|
||||
binding.firstCardContainer,
|
||||
baseTrackData.apply { supSequence = 0 },
|
||||
getGameStatus
|
||||
)
|
||||
bindContentCard(
|
||||
lifecycleOwner,
|
||||
viewModel,
|
||||
it[1].apply { showDes = false },
|
||||
binding.secondCardContainer,
|
||||
baseTrackData.apply { supSequence = 1 },
|
||||
getGameStatus
|
||||
)
|
||||
bindContentCard(
|
||||
lifecycleOwner,
|
||||
viewModel,
|
||||
it[2].apply { showDes = false },
|
||||
binding.thirdCardContainer,
|
||||
baseTrackData.apply { supSequence = 2 },
|
||||
getGameStatus
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,157 +0,0 @@
|
||||
package com.gh.gamecenter.gamedetail.detail.viewholder
|
||||
|
||||
import android.content.Context
|
||||
import android.view.ViewGroup
|
||||
import android.view.ViewGroup.MarginLayoutParams
|
||||
import androidx.core.view.updateLayoutParams
|
||||
import androidx.lifecycle.LifecycleOwner
|
||||
import com.gh.common.util.DirectUtils
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.base.GlobalActivityManager
|
||||
import com.gh.gamecenter.common.entity.PKEntity
|
||||
import com.gh.gamecenter.common.utils.*
|
||||
import com.gh.gamecenter.core.utils.TimeUtils
|
||||
import com.gh.gamecenter.databinding.ItemPkBinding
|
||||
import com.gh.gamecenter.feature.view.DownloadButton
|
||||
import com.gh.gamecenter.gamedetail.GameDetailViewModel
|
||||
import com.gh.gamecenter.gamedetail.entity.GameDetailData
|
||||
|
||||
class GameDetailContentRecommendItemViewHolder(
|
||||
val binding: ItemPkBinding,
|
||||
downloadBtn: DownloadButton?,
|
||||
viewModel: GameDetailViewModel,
|
||||
private val lifecycleOwner: LifecycleOwner,
|
||||
) : BaseGameDetailItemViewHolder(binding.root, downloadBtn, viewModel) {
|
||||
private var pkEntity: PKEntity? = null
|
||||
|
||||
override fun bindView(data: GameDetailData) {
|
||||
super.bindView(data)
|
||||
val link = data.linkContentRecommend ?: return
|
||||
pkEntity = data.pkData
|
||||
if (pkEntity == null) {
|
||||
binding.root.updateLayoutParams<MarginLayoutParams> { height = 0 }
|
||||
return
|
||||
}
|
||||
|
||||
binding.run {
|
||||
if (link.type == TYPE_PK) {
|
||||
if (!pkView.isInitialized()) {
|
||||
viewModel.pkVoteResultLiveData.observe(lifecycleOwner) {
|
||||
if (it.peekContent().first == pkEntity?.id) {
|
||||
val pair = it.getContentWithHandled()
|
||||
if (pair != null && pkView.isInitialized()) {
|
||||
pkView.vote(pair.second)
|
||||
statisticsTv.text = "已有${pkEntity?.totalNum}人参与"
|
||||
pkView.showResultWithAnimation()
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
pkView.updateView()
|
||||
}
|
||||
binding.root.updateLayoutParams<MarginLayoutParams> {
|
||||
height = ViewGroup.LayoutParams.WRAP_CONTENT
|
||||
setMargins(16F.dip2px(), 16F.dip2px(), 16F.dip2px(), 8F.dip2px())
|
||||
}
|
||||
bindPKItem(context, this, pkEntity!!, onPositiveClickAction = positive@{
|
||||
if (pkEntity == null) return@positive
|
||||
SensorsBridge.trackPKClick(
|
||||
GlobalActivityManager.getCurrentPageEntity().pageId,
|
||||
GlobalActivityManager.getCurrentPageEntity().pageName,
|
||||
GlobalActivityManager.getCurrentPageEntity().pageBusinessId,
|
||||
pkEntity!!.id,
|
||||
pkEntity!!.title,
|
||||
pkEntity!!.option1.text,
|
||||
clickSite = "选项"
|
||||
)
|
||||
viewModel.postPKVote(pkEntity!!.id, true)
|
||||
}, onNegativeClickAction = negative@{
|
||||
if (pkEntity == null) return@negative
|
||||
SensorsBridge.trackPKClick(
|
||||
GlobalActivityManager.getCurrentPageEntity().pageId,
|
||||
GlobalActivityManager.getCurrentPageEntity().pageName,
|
||||
GlobalActivityManager.getCurrentPageEntity().pageBusinessId,
|
||||
pkEntity!!.id,
|
||||
pkEntity!!.title,
|
||||
pkEntity!!.option2.text,
|
||||
clickSite = "选项"
|
||||
)
|
||||
viewModel.postPKVote(pkEntity!!.id, false)
|
||||
}) {
|
||||
SensorsBridge.trackGameDetailModuleClick(
|
||||
gameId,
|
||||
gameName,
|
||||
gameType,
|
||||
"组件内容",
|
||||
moduleType,
|
||||
pkEntity?.title,
|
||||
sequence,
|
||||
null,
|
||||
null,
|
||||
pkEntity?.link?.type,
|
||||
pkEntity?.link?.link,
|
||||
pkEntity?.link?.text,
|
||||
gameStatus
|
||||
)
|
||||
SensorsBridge.trackPKClick(
|
||||
GlobalActivityManager.getCurrentPageEntity().pageId,
|
||||
GlobalActivityManager.getCurrentPageEntity().pageName,
|
||||
GlobalActivityManager.getCurrentPageEntity().pageBusinessId,
|
||||
pkEntity!!.id,
|
||||
pkEntity!!.title,
|
||||
"",
|
||||
pkEntity!!.link?.type ?: "",
|
||||
pkEntity!!.link?.link ?: "",
|
||||
pkEntity!!.link?.text ?: "",
|
||||
clickSite = "跳转链接"
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val TYPE_PK = "pk"
|
||||
const val TIME_PATTERN = "yyyy.MM.dd HH:mm:ss"
|
||||
|
||||
fun bindPKItem(
|
||||
context: Context,
|
||||
binding: ItemPkBinding,
|
||||
pkEntity: PKEntity,
|
||||
onPositiveClickAction: () -> Unit,
|
||||
onNegativeClickAction: () -> Unit,
|
||||
onLinkClickAction: () -> Unit
|
||||
) {
|
||||
binding.run {
|
||||
root.background = R.drawable.bg_shape_f8_radius_8.toDrawable(context)
|
||||
pkTitleTv.setTextColor(com.gh.gamecenter.common.R.color.text_primary.toColor(context))
|
||||
endDateTv.setTextColor(com.gh.gamecenter.common.R.color.text_secondary.toColor(context))
|
||||
statisticsTv.setTextColor(com.gh.gamecenter.common.R.color.text_tertiary.toColor(context))
|
||||
linkTv.background = com.gh.gamecenter.common.R.drawable.button_round_theme_alpha_10.toDrawable(context)
|
||||
linkTv.setTextColor(com.gh.gamecenter.common.R.color.primary_theme.toColor(context))
|
||||
pkView.run {
|
||||
setData(pkEntity)
|
||||
onPositiveClick = onPositiveClickAction
|
||||
onNegativeClick = onNegativeClickAction
|
||||
}
|
||||
pkTitleTv.text = pkEntity.title
|
||||
val endDateText = if (pkEntity.isExpired) "已" else "将"
|
||||
endDateTv.text = "${endDateText}于${TimeUtils.getFormatTime(pkEntity.time.end, TIME_PATTERN)}结束"
|
||||
statisticsTv.text = "已有${pkEntity.totalNum}人参与"
|
||||
linkTv.goneIf(pkEntity.link == null) {
|
||||
linkTv.setOnClickListener { _ ->
|
||||
pkEntity.link?.let {
|
||||
DirectUtils.directToLinkPage(
|
||||
context,
|
||||
it,
|
||||
"内容推荐-PK",
|
||||
""
|
||||
)
|
||||
}
|
||||
onLinkClickAction.invoke()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user