Compare commits
194 Commits
revert-a02
...
legacy-rel
| Author | SHA1 | Date | |
|---|---|---|---|
| 1040f5ff4d | |||
| 97be320529 | |||
| 59cde4e2bf | |||
| cc0c7c7fae | |||
| 9e9ce6a84f | |||
| 7d0b500ff9 | |||
| 425456b263 | |||
| f6abab9a2d | |||
| d194f969e4 | |||
| 95f66344fb | |||
| 570e2fa9bc | |||
| 9e07080043 | |||
| e10a329159 | |||
| b3bc7b43f7 | |||
| 811d42457c | |||
| ac0b819ea9 | |||
| d931fb5940 | |||
| cea62b55e2 | |||
| ff6cdb1ba3 | |||
| b6e531fa96 | |||
| e7a37df690 | |||
| 239b056abb | |||
| 315be3797c | |||
| bdcca58770 | |||
| 644b93ab02 | |||
| 1ee0f292ba | |||
| f609637f0b | |||
| 9d10add8eb | |||
| f5a39f982e | |||
| 1a063bb0c1 | |||
| 86340d603f | |||
| 0731cc1fde | |||
| 86dfee2ff9 | |||
| edf82952ce | |||
| 4412d159bb | |||
| e119b7fecd | |||
| 3fe7c8252e | |||
| 36ebab77ee | |||
| e84db01984 | |||
| ae605d4a55 | |||
| 882bf4b551 | |||
| 968164af55 | |||
| 0119e6f123 | |||
| 7093552259 | |||
| 2be52d21ee | |||
| cb093cc3f0 | |||
| 3cbdd94189 | |||
| 11013319bf | |||
| aa954b3af9 | |||
| 93f279a384 | |||
| 4e54833cc9 | |||
| f95862da8b | |||
| 1515df34b5 | |||
| 8a8ef40dc1 | |||
| b6194fed26 | |||
| 02752f6c81 | |||
| b33d367dfd | |||
| d5046ab431 | |||
| a53168c9bc | |||
| 3cbc8c2f74 | |||
| 7398b83004 | |||
| 8013426ded | |||
| b86d85b15f | |||
| 5a73afbab3 | |||
| e19ee25839 | |||
| 61bf39e95f | |||
| ef82ae2378 | |||
| 2dcccc22a8 | |||
| cb0e77d204 | |||
| a6ea178609 | |||
| 6a62f08891 | |||
| ddb48481d2 | |||
| 48a55a6b31 | |||
| 50fcb0c3ea | |||
| e97722b6fb | |||
| 2163b2ff9e | |||
| b9558e2732 | |||
| 5daddeadda | |||
| 58b1c0295c | |||
| a56082d002 | |||
| 877ab7cf39 | |||
| 428e3496d8 | |||
| b33419ea05 | |||
| e9bcd0a0d6 | |||
| 98b877671a | |||
| 6c61a62799 | |||
| 391e409ee1 | |||
| cfd1ee845a | |||
| 34b123a0a7 | |||
| 51515171a8 | |||
| e9139c66e1 | |||
| 24941a165a | |||
| 9d661eefa7 | |||
| 373fa7fc80 | |||
| d9743a89d6 | |||
| 0f596836dc | |||
| eb08575f3e | |||
| 405268bbce | |||
| 2453e34a74 | |||
| 2830367826 | |||
| 782d94289f | |||
| 3e2c2fe18f | |||
| 1afd154364 | |||
| b24cac0cb1 | |||
| d5db516112 | |||
| b2a7a606e5 | |||
| 219866e195 | |||
| dea7ceb5f6 | |||
| da1da1c1af | |||
| 9b4fa45492 | |||
| 01df42b76b | |||
| cef8aa1968 | |||
| 4147612d9b | |||
| 9b57d10e2d | |||
| 19f4e70ada | |||
| 49b7e4c245 | |||
| 638de59562 | |||
| 69b092be46 | |||
| 27d1d02d58 | |||
| e4bfa5e6bf | |||
| 3ea3238011 | |||
| 2dcae2168b | |||
| 4b1c198818 | |||
| e42e2fbd56 | |||
| 713e4157db | |||
| 76cf7dce1d | |||
| f492d2ea97 | |||
| 37a3689a2c | |||
| 7429f17538 | |||
| 32ba015686 | |||
| e5365fd527 | |||
| 1c873d0194 | |||
| 1424ee2b45 | |||
| 69cb916364 | |||
| 04f1d712cd | |||
| ee14ae51be | |||
| 4683217e44 | |||
| df94d6677a | |||
| 6f85e12edf | |||
| 020c826f1d | |||
| 5640d778a2 | |||
| 2300475a9e | |||
| 612b4061d5 | |||
| 49c7ff8f8e | |||
| 1c408f3966 | |||
| 055f5b23da | |||
| 9810b3e8fe | |||
| dba7042b12 | |||
| 6695dc596e | |||
| 079ba014f8 | |||
| 46955685bb | |||
| 14eeb00539 | |||
| 56843f18d4 | |||
| 53a46892a4 | |||
| a2153761c2 | |||
| 26a8c0abd8 | |||
| 21bf0fd8e9 | |||
| 9787d23ea0 | |||
| 6ae34b81db | |||
| 0b1e770c03 | |||
| f4681dab31 | |||
| 79a7f994eb | |||
| 3276fca27c | |||
| 372db8e52c | |||
| 9b6d986f1c | |||
| 0e88db1600 | |||
| 05b59c8732 | |||
| 28f68cae95 | |||
| 22713db44e | |||
| d9389ac4aa | |||
| 31ec9311fc | |||
| fca62df263 | |||
| 978c01d7dc | |||
| b7a24e331a | |||
| b1eac6a043 | |||
| 9f8a712be6 | |||
| 930ab904ed | |||
| 3c207244e6 | |||
| 0f59e03afa | |||
| c5d99fa304 | |||
| a313cd8050 | |||
| ce477e2bd0 | |||
| 7cf2adaa37 | |||
| 0852497df2 | |||
| 592df6ea44 | |||
| 7b5d1b1bf3 | |||
| 5b1a614eb7 | |||
| ae9fbfb8c4 | |||
| 48b118d342 | |||
| 39625369d7 | |||
| 05b9920f6d | |||
| 8a5fa2c31a | |||
| c2dc6d7dbe | |||
| db4eb9f811 |
@ -72,7 +72,7 @@ android_build:
|
||||
only:
|
||||
- dev
|
||||
- release
|
||||
- feature-GHZS-6019
|
||||
- feat/GHZSCY-6644
|
||||
|
||||
# 代码检查
|
||||
sonarqube_analysis:
|
||||
@ -128,6 +128,9 @@ oss-upload&send-email:
|
||||
- sysadm-devops
|
||||
stage: oss-upload&send-email
|
||||
image: hub.shanqu.cc/devops/android-apk-oss-upload:latest
|
||||
id_tokens:
|
||||
VAULT_ID_TOKEN:
|
||||
aud: https://vault.shanqu.cc
|
||||
variables:
|
||||
GIT_STRATEGY: none
|
||||
VAULT_ADDR: https://vault.shanqu.cc # 固定值
|
||||
@ -146,6 +149,7 @@ oss-upload&send-email:
|
||||
artifacts: true
|
||||
script:
|
||||
### 绑定上传参数 ###
|
||||
|
||||
- export OSS_PATH="release/dev/${CI_PROJECT_NAME}/$(date "+%Y/%m/%d")"
|
||||
### 开启上传 ###
|
||||
- /usr/local/bin/python /upload.py
|
||||
@ -154,4 +158,4 @@ oss-upload&send-email:
|
||||
only:
|
||||
- dev
|
||||
- release
|
||||
- feature-GHZS-6019
|
||||
- feat/GHZSCY-6644
|
||||
@ -9,6 +9,7 @@
|
||||
|
||||
<queries>
|
||||
<package android:name="com.lg.vspace" />
|
||||
<package android:name="com.gh.gamecenter.addon" />
|
||||
</queries>
|
||||
|
||||
<!-- 华为/荣耀角标 -->
|
||||
@ -55,6 +56,9 @@
|
||||
<!-- 如果有视频相关的广告且使用textureView播放,请务必添加,否则黑屏 -->
|
||||
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
||||
|
||||
<!-- 悬浮窗 -->
|
||||
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
|
||||
|
||||
<uses-sdk tools:overrideLibrary="
|
||||
com.shuyu.gsyvideoplayer,
|
||||
com.shuyu.gsyvideoplayer.lib,
|
||||
@ -305,10 +309,6 @@
|
||||
android:name="com.gh.gamecenter.CleanApkActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.SelectUserIconActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.CommentDetailActivity"
|
||||
android:screenOrientation="portrait"
|
||||
@ -333,14 +333,6 @@
|
||||
android:screenOrientation="portrait"
|
||||
android:windowSoftInputMode="stateHidden" />
|
||||
|
||||
<activity
|
||||
android:name=".category.CategoryDirectoryActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name=".category.CategoryListActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.UserInfoActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
@ -497,9 +489,6 @@
|
||||
android:configChanges="orientation|screenSize|keyboardHidden"
|
||||
android:screenOrientation="portrait"
|
||||
android:theme="@style/TransparentStatusBarAndNavigationBar" />
|
||||
<activity
|
||||
android:name=".gamedetail.myrating.MyRatingActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.gamedetail.fuli.kaifu.ServersCalendarActivity"
|
||||
@ -565,14 +554,6 @@
|
||||
android:name=".simulatorgame.SimulatorManagementActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name=".catalog.CatalogActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name=".catalog.NewCatalogListActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name=".forum.search.ForumOrUserSearchActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
@ -875,6 +856,8 @@
|
||||
|
||||
<service android:name="com.gh.gamecenter.install.InstallService" />
|
||||
|
||||
<service android:name="com.gh.download.suspendwindow.DownloadSuspendWindowService" />
|
||||
|
||||
<receiver
|
||||
android:name="com.gh.gamecenter.receiver.DownloadReceiver"
|
||||
android:exported="false">
|
||||
|
||||
1
app/src/main/assets/lottie/draw_overlay_permission.json
Normal file
1
app/src/main/assets/lottie/draw_overlay_permission.json
Normal file
File diff suppressed because one or more lines are too long
@ -61,6 +61,9 @@ object AdDelegateHelper {
|
||||
val vGameLaunchAd: AdConfig?
|
||||
get() = mVGameLaunchAd
|
||||
|
||||
val splashAdDisplayInterval: Int
|
||||
get() = mSplashAd?.ownerAd?.startAd?.displayInterval ?: 3
|
||||
|
||||
private const val AD_SDK_CSJ = "穿山甲"
|
||||
const val AD_TYPE_SDK = "third_party_ads" // 第三方 SDK 广告
|
||||
const val AD_TYPE_OWNER = "owner_ads" // 自有广告
|
||||
@ -523,12 +526,15 @@ object AdDelegateHelper {
|
||||
handler: BaseActivity.BaseHandler,
|
||||
hideCallback: () -> Unit
|
||||
) {
|
||||
val jumpBtn: View = startAdContainer.findViewById(R.id.jumpBtn)
|
||||
val jumpBtn = startAdContainer.findViewById<TextView>(R.id.jumpBtn)
|
||||
val jumpDetailBtn: TextView = startAdContainer.findViewById(R.id.jumpDetailBtn)
|
||||
val adImage: SimpleDraweeView = startAdContainer.findViewById(R.id.adImage)
|
||||
val adVideo = startAdContainer.findViewById<SplashAdVideoView>(R.id.ad_video)
|
||||
val icpContainer: View? = startAdContainer.findViewById(R.id.startAdIcpContainer)
|
||||
startAdContainer.visibility = View.VISIBLE
|
||||
icpContainer?.visibility = View.VISIBLE
|
||||
jumpBtn.text = startAdContainer.context.getString(R.string.splash_jump, splashAdDisplayInterval)
|
||||
|
||||
jumpDetailBtn.text = ad.desc
|
||||
jumpDetailBtn.setDrawableEnd(
|
||||
AppCompatResources.getDrawable(
|
||||
@ -536,7 +542,16 @@ object AdDelegateHelper {
|
||||
R.drawable.ic_startup_ad_arrow
|
||||
), null, null
|
||||
)
|
||||
|
||||
adImage.visibleIf(true)
|
||||
ImageUtils.display(adImage, ad.img)
|
||||
|
||||
if (ad.isImageType) {
|
||||
adVideo.visibleIf(false)
|
||||
} else {
|
||||
adVideo.visibleIf(true)
|
||||
adVideo.startPlay(ad.video.url)
|
||||
}
|
||||
startAdContainer.setOnClickListener {
|
||||
// 拦截点击事件传递
|
||||
}
|
||||
|
||||
78
app/src/main/java/com/gh/ad/SplashAdVideoView.kt
Normal file
78
app/src/main/java/com/gh/ad/SplashAdVideoView.kt
Normal file
@ -0,0 +1,78 @@
|
||||
package com.gh.ad
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.util.AttributeSet
|
||||
import android.view.WindowManager
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.video.detail.CustomManager
|
||||
import com.shuyu.gsyvideoplayer.utils.GSYVideoType
|
||||
import com.shuyu.gsyvideoplayer.utils.GSYVideoType.SCREEN_TYPE_FULL
|
||||
import com.shuyu.gsyvideoplayer.video.StandardGSYVideoPlayer
|
||||
import com.shuyu.gsyvideoplayer.video.base.GSYVideoViewBridge
|
||||
|
||||
class SplashAdVideoView @JvmOverloads constructor(
|
||||
context: Context,
|
||||
attrs: AttributeSet? = null
|
||||
) :
|
||||
StandardGSYVideoPlayer(context, attrs) {
|
||||
|
||||
fun startPlay(url: String) {
|
||||
GSYVideoType.setShowType(SCREEN_TYPE_FULL)
|
||||
GSYVideoType.setRenderType(GSYVideoType.SUFRACE)
|
||||
CustomManager.getCustomManager(getKey()).isNeedMute = true
|
||||
|
||||
setUp(url, true, "")
|
||||
|
||||
setNeedAutoAdaptation(false)
|
||||
startPlayLogic()
|
||||
}
|
||||
|
||||
override fun getGSYVideoManager(): GSYVideoViewBridge {
|
||||
CustomManager.getCustomManager(getKey()).initContext(context.applicationContext)
|
||||
return CustomManager.getCustomManager(getKey())
|
||||
}
|
||||
|
||||
private fun getKey() = "splash_ad"
|
||||
|
||||
/**
|
||||
* 覆盖父类方法,防止在是视频 Preparing 阶段封面图被隐藏,导致白屏
|
||||
*/
|
||||
override fun changeUiToPreparingShow() = Unit
|
||||
|
||||
override fun getLayoutId(): Int {
|
||||
return R.layout.layout_splash_ad_video
|
||||
}
|
||||
|
||||
override fun onAutoCompletion() {
|
||||
setStateAndUi(CURRENT_STATE_AUTO_COMPLETE);
|
||||
|
||||
mSaveChangeViewTIme = 0
|
||||
mCurrentPosition = 0
|
||||
|
||||
if (!mIfCurrentIsFullscreen) {
|
||||
getGSYVideoManager().setLastListener(null)
|
||||
}
|
||||
mAudioManager.abandonAudioFocus(onAudioFocusChangeListener);
|
||||
if (mContext is Activity) {
|
||||
try {
|
||||
(mContext as Activity).getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
releaseNetWorkState()
|
||||
|
||||
if (mVideoAllCallBack != null && isCurrentMediaListener()) {
|
||||
mVideoAllCallBack.onAutoComplete(mOriginUrl, mTitle, this)
|
||||
}
|
||||
mHadPlay = false
|
||||
}
|
||||
|
||||
fun clearAll() {
|
||||
GSYVideoType.setShowType(GSYVideoType.SCREEN_TYPE_DEFAULT)
|
||||
GSYVideoType.setRenderType(GSYVideoType.TEXTURE)
|
||||
release()
|
||||
CustomManager.removeManager(getKey())
|
||||
}
|
||||
}
|
||||
@ -21,13 +21,13 @@ import com.gh.gamecenter.common.utils.PackageFlavorHelper
|
||||
import com.gh.gamecenter.core.provider.IPushProvider
|
||||
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
|
||||
|
||||
// TODO:移动到对应的模块
|
||||
class GlobalActivityLifecycleObserver : Application.ActivityLifecycleCallbacks {
|
||||
private var isFromBackgroundToForeground = false // 是否后台回到前台
|
||||
private var activityCount = 0
|
||||
|
||||
override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {
|
||||
// do nothing
|
||||
@ -35,8 +35,8 @@ class GlobalActivityLifecycleObserver : Application.ActivityLifecycleCallbacks {
|
||||
|
||||
override fun onActivityStarted(activity: Activity) {
|
||||
GlobalActivityManager.currentActivity = activity
|
||||
activityCount++
|
||||
if (activityCount == 1 && isFromBackgroundToForeground) {
|
||||
GlobalActivityManager.activityCount ++
|
||||
if (GlobalActivityManager.activityCount == 1 && isFromBackgroundToForeground) {
|
||||
if (AdDelegateHelper.shouldShowStartUpAd(true)
|
||||
&& !HaloApp.getInstance().isDisableSplashAdTemporarily
|
||||
&& activity !is SplashScreenActivity
|
||||
@ -50,13 +50,16 @@ class GlobalActivityLifecycleObserver : Application.ActivityLifecycleCallbacks {
|
||||
isFromBackgroundToForeground = false
|
||||
}
|
||||
|
||||
if (activityCount == 1) {
|
||||
if (GlobalActivityManager.activityCount == 1) {
|
||||
// 清除桌面角标
|
||||
if (activity !is SplashScreenActivity && activity !is AuthorizationActivity) {
|
||||
val pushProvider = ARouter.getInstance().build(RouteConsts.provider.push).navigation() as? IPushProvider
|
||||
pushProvider?.cleanBadgeNumber(activity.applicationContext)
|
||||
}
|
||||
}
|
||||
if (QuickLoginHelper.isLoginAuthPage(activity)) {
|
||||
QuickLoginHelper.addCustomViewToLoginAuthPage(activity)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onActivityResumed(activity: Activity) {
|
||||
@ -108,8 +111,8 @@ class GlobalActivityLifecycleObserver : Application.ActivityLifecycleCallbacks {
|
||||
}
|
||||
|
||||
override fun onActivityStopped(activity: Activity) {
|
||||
activityCount--
|
||||
isFromBackgroundToForeground = activityCount <= 0
|
||||
GlobalActivityManager.activityCount --
|
||||
isFromBackgroundToForeground = GlobalActivityManager.activityCount <= 0
|
||||
}
|
||||
|
||||
override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) {
|
||||
@ -117,7 +120,9 @@ class GlobalActivityLifecycleObserver : Application.ActivityLifecycleCallbacks {
|
||||
}
|
||||
|
||||
override fun onActivityDestroyed(activity: Activity) {
|
||||
// do nothing
|
||||
if (QuickLoginHelper.isLoginAuthPage(activity)) {
|
||||
QuickLoginHelper.release()
|
||||
}
|
||||
}
|
||||
|
||||
private fun isSuggestionActivity(activity: Activity): Boolean {
|
||||
|
||||
@ -49,6 +49,7 @@ import com.gh.gamecenter.login.user.LoginTag
|
||||
import com.gh.gamecenter.login.user.UserManager
|
||||
import com.gh.gamecenter.login.user.UserRepository
|
||||
import com.gh.gamecenter.login.utils.LoginHelper
|
||||
import com.gh.gamecenter.login.utils.QuickLoginHelper
|
||||
import com.gh.gamecenter.login.view.LoginActivity
|
||||
import com.gh.gamecenter.personalhome.border.AvatarBorderActivity
|
||||
import com.gh.gamecenter.setting.SettingBridge
|
||||
@ -138,12 +139,12 @@ class DefaultJsApi(
|
||||
|
||||
@JavascriptInterface
|
||||
fun login(msg: Any) {
|
||||
// if (SPUtils.getBoolean(Constants.SP_HAS_GET_PHONE_INFO) || NetworkUtils.isOpenMobileData(context)) {
|
||||
// QuickLoginHelper.startLogin(context, "浏览器")
|
||||
// } else {
|
||||
if (NetworkUtils.isQuickLoginEnabled(context)) {
|
||||
QuickLoginHelper.startLogin(context, "浏览器")
|
||||
} else {
|
||||
val intent = LoginActivity.getIntent(context, "浏览器")
|
||||
context.startActivity(intent)
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
@JavascriptInterface
|
||||
|
||||
@ -268,10 +268,6 @@ object DefaultUrlHandler {
|
||||
directToGameVideo(context, id, entrance, "")
|
||||
}
|
||||
|
||||
EntranceConsts.HOST_CATEGORY -> {
|
||||
val title = uri.getQueryParameter("title")
|
||||
DirectUtils.directCategoryDirectory(context, id, title ?: "", entrance, "")
|
||||
}
|
||||
EntranceConsts.HOST_COLUMN_COLLECTION -> {
|
||||
val name = uri.getQueryParameter("name")
|
||||
DirectUtils.directToColumnCollection(context, id, -1, entrance, name ?: "")
|
||||
|
||||
@ -20,6 +20,7 @@ import com.gh.gamecenter.common.retrofit.BiResponse;
|
||||
import com.gh.gamecenter.common.retrofit.Response;
|
||||
import com.gh.gamecenter.common.utils.DarkModeUtils;
|
||||
import com.gh.gamecenter.common.utils.EnvHelper;
|
||||
import com.gh.gamecenter.core.AppExecutor;
|
||||
import com.gh.gamecenter.core.utils.GsonUtils;
|
||||
import com.gh.gamecenter.core.utils.SPUtils;
|
||||
import com.gh.gamecenter.core.utils.UrlFilterUtils;
|
||||
@ -47,7 +48,6 @@ import java.util.Locale;
|
||||
|
||||
import io.reactivex.Single;
|
||||
import io.reactivex.SingleSource;
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.functions.Function;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
import io.reactivex.subjects.BehaviorSubject;
|
||||
@ -225,7 +225,6 @@ public class Config {
|
||||
RetrofitManager.getInstance()
|
||||
.getVApi().getSettings(BuildConfig.VERSION_NAME, Build.VERSION.SDK_INT)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(new BiResponse<VSetting>() {
|
||||
@Override
|
||||
public void onSuccess(VSetting data) {
|
||||
@ -258,7 +257,6 @@ public class Config {
|
||||
}
|
||||
})
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(new BiResponse<AppEntity>() {
|
||||
@Override
|
||||
public void onSuccess(AppEntity data) {
|
||||
@ -290,7 +288,6 @@ public class Config {
|
||||
RetrofitManager.getInstance()
|
||||
.getApi().getSettings(PackageUtils.getGhVersionName(), channel)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(new Response<SettingsEntity>() {
|
||||
@Override
|
||||
public void onResponse(SettingsEntity response) {
|
||||
@ -303,7 +300,7 @@ public class Config {
|
||||
edit.apply();
|
||||
|
||||
if (!SPUtils.getBoolean(Constants.SP_TEENAGER_MODE)) {
|
||||
EventBus.getDefault().post(new EBReuse("Refresh"));
|
||||
AppExecutor.getUiExecutor().execute(() -> EventBus.getDefault().post(new EBReuse("Refresh")));
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -311,7 +308,6 @@ public class Config {
|
||||
RetrofitManager.getInstance()
|
||||
.getApi().getNewSettings(Build.MANUFACTURER, Build.MODEL, channel, Build.VERSION.SDK_INT, BuildConfig.VERSION_NAME)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(new BiResponse<NewSettingsEntity>() {
|
||||
@Override
|
||||
public void onSuccess(NewSettingsEntity data) {
|
||||
@ -326,7 +322,6 @@ public class Config {
|
||||
RetrofitManager.getInstance()
|
||||
.getApi().getGameGuidePopup(Build.MANUFACTURER, Build.VERSION.RELEASE, Build.MODEL, channel, BuildConfig.VERSION_NAME)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(new BiResponse<GameGuidePopupEntity>() {
|
||||
@Override
|
||||
public void onSuccess(GameGuidePopupEntity data) {
|
||||
@ -338,7 +333,6 @@ public class Config {
|
||||
if (manufacturer.equals("OPPO") || manufacturer.equals("VIVO")) {
|
||||
RetrofitManager.getInstance().getNewApi().getBrowserHintUrl(manufacturer)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(new BiResponse<ResponseBody>() {
|
||||
@Override
|
||||
public void onSuccess(ResponseBody data) {
|
||||
@ -369,7 +363,6 @@ public class Config {
|
||||
RetrofitManager.getInstance()
|
||||
.getNewApi().getNewSettings(PackageUtils.getGhVersionName(), channel, filterString)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(new BiResponse<NewApiSettingsEntity>() {
|
||||
@Override
|
||||
public void onSuccess(NewApiSettingsEntity data) {
|
||||
@ -378,7 +371,7 @@ public class Config {
|
||||
mNewSimulatorEntity = data.getSimulator();
|
||||
if (HaloApp.getInstance().isNewForThisVersion && mNightModeSetting != null && mNightModeSetting.getInstall()) {
|
||||
DarkModeUtils.INSTANCE.updateFollowSystemDarkModeToSp(true);
|
||||
DarkModeUtils.INSTANCE.initDarkMode();
|
||||
AppExecutor.getUiExecutor().execute(DarkModeUtils.INSTANCE::initDarkMode);
|
||||
}
|
||||
SPUtils.setString(Constants.SP_NEW_API_SETTINGS, GsonUtils.toJson(data));
|
||||
|
||||
@ -396,7 +389,7 @@ public class Config {
|
||||
|
||||
// 更新包名监听是否开启
|
||||
if (mNewApiSettingsEntity.isPackageObserveEnable()) {
|
||||
observePackageChange(mNewApiSettingsEntity.getPackageObserveActions());
|
||||
AppExecutor.getUiExecutor().execute(() -> observePackageChange(mNewApiSettingsEntity.getPackageObserveActions()));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@ -158,7 +158,7 @@ class InstallPermissionDialogFragment : BaseDialogFragment() {
|
||||
}
|
||||
if (isXapk) {
|
||||
val xapkUnzipVersions = Config.getSettings()?.permissionPopupAppliedVersions?.xapkUnzip
|
||||
if (xapkUnzipVersions?.contains(Build.VERSION.SDK_INT.toString()) == false) {
|
||||
if (xapkUnzipVersions?.contains(Build.VERSION.SDK_INT.toString()) == false || XapkInstaller.systemHasFlaw) {
|
||||
callBack?.invoke(false)
|
||||
return
|
||||
}
|
||||
|
||||
@ -6,16 +6,16 @@ import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.recyclerview.widget.GridLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.gh.gamecenter.common.base.BaseRecyclerViewHolder
|
||||
import com.gh.gamecenter.common.base.fragment.BaseDialogFragment
|
||||
import com.gh.gamecenter.common.utils.ImageUtils
|
||||
import com.gh.gamecenter.common.utils.fromHtml
|
||||
import com.gh.gamecenter.GameDetailActivity
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.base.BaseRecyclerViewHolder
|
||||
import com.gh.gamecenter.common.base.fragment.BaseDialogFragment
|
||||
import com.gh.gamecenter.common.entity.SimpleGameEntity
|
||||
import com.gh.gamecenter.common.utils.ImageUtils
|
||||
import com.gh.gamecenter.common.utils.fromHtml
|
||||
import com.gh.gamecenter.common.view.FixLinearLayoutManager
|
||||
import com.gh.gamecenter.databinding.DialogReserveBinding
|
||||
import com.gh.gamecenter.databinding.DialogReserveItemBinding
|
||||
import com.gh.gamecenter.common.entity.SimpleGameEntity
|
||||
import com.gh.gamecenter.mygame.MyGameActivity
|
||||
import com.lightgame.adapter.BaseRecyclerAdapter
|
||||
|
||||
@ -43,7 +43,7 @@ class ReserveDialog : BaseDialogFragment() {
|
||||
View.VISIBLE
|
||||
} else View.GONE
|
||||
binding.more.setOnClickListener {
|
||||
val intent = MyGameActivity.getIntentWithConfig(requireContext(), 2)
|
||||
val intent = MyGameActivity.getIntentWithConfig(requireContext(), MyGameActivity.RESERVATION_INDEX)
|
||||
startActivity(intent)
|
||||
dismissAllowingStateLoss()
|
||||
}
|
||||
|
||||
@ -1,13 +1,13 @@
|
||||
package com.gh.common.prioritychain
|
||||
|
||||
import android.app.Activity
|
||||
import android.os.Handler
|
||||
import android.view.Gravity
|
||||
import android.view.LayoutInflater
|
||||
import android.widget.FrameLayout
|
||||
import com.gh.common.util.NewFlatLogUtils
|
||||
import com.gh.gamecenter.GameDetailActivity
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.base.fragment.BaseFragment
|
||||
import com.gh.gamecenter.common.constant.Constants
|
||||
import com.gh.gamecenter.common.view.BugFixedPopupWindow
|
||||
import com.gh.gamecenter.core.utils.DisplayUtils
|
||||
@ -19,7 +19,7 @@ import com.gh.gamecenter.wrapper.MainWrapperViewModel
|
||||
class AccelerateNotificationHandler(priority: Int) : PriorityChainHandler(priority) {
|
||||
|
||||
private var mActivity: Activity? = null
|
||||
private var mBaseHandler: BaseFragment.BaseHandler? = null
|
||||
private var mHandler: Handler? = null
|
||||
private var mGameList: List<GameEntity>? = null
|
||||
private var mViewModel: MainWrapperViewModel? = null
|
||||
|
||||
@ -28,13 +28,13 @@ class AccelerateNotificationHandler(priority: Int) : PriorityChainHandler(priori
|
||||
*/
|
||||
fun doPreProcess(
|
||||
activity: Activity,
|
||||
baseHandler: BaseFragment.BaseHandler,
|
||||
handler: Handler,
|
||||
gameEntityList: List<GameEntity>?,
|
||||
viewModel: MainWrapperViewModel
|
||||
) {
|
||||
mActivity = activity
|
||||
mGameList = gameEntityList
|
||||
mBaseHandler = baseHandler
|
||||
mHandler = handler
|
||||
mViewModel = viewModel
|
||||
|
||||
if (getStatus() == STATUS_PENDING) {
|
||||
@ -59,7 +59,7 @@ class AccelerateNotificationHandler(priority: Int) : PriorityChainHandler(priori
|
||||
val accelerateSet =
|
||||
HashSet(SPUtils.getStringSet(Constants.SP_ACCELERATE_NOTIFICATION_POP_UP_SET))
|
||||
if (!mGameList.isNullOrEmpty() && !accelerateSet.contains(mGameList!![0].messageId)) {
|
||||
showAccelerateNotificationPopupWindow(mActivity!!, mViewModel, mBaseHandler, mGameList!![0]) {
|
||||
showAccelerateNotificationPopupWindow(mActivity!!, mViewModel, mHandler, mGameList!![0]) {
|
||||
processNext()
|
||||
}
|
||||
accelerateSet.add(mGameList!![0].messageId)
|
||||
@ -82,7 +82,7 @@ class AccelerateNotificationHandler(priority: Int) : PriorityChainHandler(priori
|
||||
fun showAccelerateNotificationPopupWindow(
|
||||
activity: Activity,
|
||||
viewModel: MainWrapperViewModel?,
|
||||
baseHandler: BaseFragment.BaseHandler?,
|
||||
handler: Handler?,
|
||||
gameEntity: GameEntity?,
|
||||
dismissCallback: (() -> Unit)?
|
||||
) {
|
||||
@ -131,7 +131,7 @@ class AccelerateNotificationHandler(priority: Int) : PriorityChainHandler(priori
|
||||
setOnDismissListener {
|
||||
dismissCallback?.invoke()
|
||||
}
|
||||
baseHandler?.postDelayed({ dismiss() }, 5000)
|
||||
handler?.postDelayed({ dismiss() }, 5000)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,169 @@
|
||||
package com.gh.common.prioritychain
|
||||
|
||||
import android.app.Activity
|
||||
import android.os.Handler
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.PopupWindow
|
||||
import androidx.constraintlayout.widget.ConstraintLayout
|
||||
import androidx.core.view.updateLayoutParams
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.constant.Constants
|
||||
import com.gh.gamecenter.common.utils.dip2px
|
||||
import com.gh.gamecenter.common.view.BugFixedPopupWindow
|
||||
import com.gh.gamecenter.core.utils.SPUtils
|
||||
import com.gh.gamecenter.databinding.PopupBottomTabGuideBinding
|
||||
import com.gh.gamecenter.entity.BottomTab
|
||||
|
||||
class BottomTabGuideHandler(priority: Int): PriorityChainHandler(priority) {
|
||||
private var mActivity: Activity? = null
|
||||
private var mHandler: Handler? = null
|
||||
private var mViewPager: ViewGroup? = null
|
||||
private var mGuide: BottomTab.Guide? = null
|
||||
private var mTriangleTransX = 0F
|
||||
private var mGuideTransX = 0F
|
||||
private var mRestWidth = 0F
|
||||
private var mIsCenterPosition = false
|
||||
private var mIsRightPosition = false
|
||||
|
||||
private var mPopupWindow: PopupWindow? = null
|
||||
|
||||
fun doPreProcess(
|
||||
shouldShow: Boolean,
|
||||
activity: Activity? = null,
|
||||
handler: Handler? = null,
|
||||
viewPager: ViewGroup? = null,
|
||||
guide: BottomTab.Guide? = null,
|
||||
triangleTransX: Float = 0F,
|
||||
guideTransX: Float = 0F,
|
||||
restWidth: Float = 0F,
|
||||
isCenterPosition: Boolean = false,
|
||||
isRightPosition: Boolean = false
|
||||
) {
|
||||
mActivity = activity
|
||||
mHandler = handler
|
||||
mViewPager = viewPager
|
||||
mGuide = guide
|
||||
mTriangleTransX = triangleTransX
|
||||
mGuideTransX = guideTransX
|
||||
mRestWidth = restWidth
|
||||
mIsCenterPosition = isCenterPosition
|
||||
mIsRightPosition = isRightPosition
|
||||
|
||||
if (getStatus() == STATUS_PENDING) {
|
||||
if (shouldShow) {
|
||||
updateStatus(STATUS_VALID)
|
||||
process()
|
||||
} else {
|
||||
processNext()
|
||||
}
|
||||
} else {
|
||||
if (shouldShow) {
|
||||
updateStatus(STATUS_VALID)
|
||||
} else {
|
||||
updateStatus(STATUS_INVALID)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onProcess(): Boolean {
|
||||
when (getStatus()) {
|
||||
STATUS_VALID -> {
|
||||
if (mGuide == null || mActivity == null || mViewPager == null) {
|
||||
processNext()
|
||||
return false
|
||||
}
|
||||
|
||||
val guideSet = HashSet(SPUtils.getStringSet(Constants.SP_BOTTOM_TAB_GUIDE_SET))
|
||||
if (!guideSet.contains(mGuide?.bottomTabId + mGuide?.text)) {
|
||||
mPopupWindow = showBottomTabPopupWindow(
|
||||
mActivity!!,
|
||||
mHandler,
|
||||
mViewPager!!,
|
||||
mGuide!!,
|
||||
mTriangleTransX,
|
||||
mGuideTransX,
|
||||
mRestWidth,
|
||||
mIsCenterPosition,
|
||||
mIsRightPosition
|
||||
) {
|
||||
processNext()
|
||||
}
|
||||
guideSet.add(mGuide?.bottomTabId + mGuide?.text)
|
||||
SPUtils.setStringSet(Constants.SP_BOTTOM_TAB_GUIDE_SET, guideSet)
|
||||
return true
|
||||
} else {
|
||||
processNext()
|
||||
}
|
||||
}
|
||||
|
||||
STATUS_INVALID -> {
|
||||
processNext()
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
fun dismiss() {
|
||||
if (mPopupWindow?.isShowing == true) {
|
||||
mPopupWindow?.dismiss()
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val KEY_BOTTOM_TAB_GUIDE_AUTO_DISMISS = 100
|
||||
private const val AUTO_DISMISS_DELAY_TIME = 5000L
|
||||
|
||||
fun showBottomTabPopupWindow(
|
||||
activity: Activity,
|
||||
handler: Handler?,
|
||||
viewPager: ViewGroup,
|
||||
guide: BottomTab.Guide,
|
||||
triangleTransX: Float,
|
||||
guideTransX: Float,
|
||||
restWidth: Float,
|
||||
isCenterPosition: Boolean,
|
||||
isRightPosition: Boolean,
|
||||
dismissCallback: (() -> Unit)?
|
||||
): PopupWindow {
|
||||
val binding = PopupBottomTabGuideBinding.inflate(LayoutInflater.from(activity))
|
||||
binding.guideTv.text = guide.text
|
||||
binding.guideTriangleIv.translationX = triangleTransX
|
||||
binding.guideTv.translationX = guideTransX
|
||||
binding.guideIconIv.translationX = guideTransX
|
||||
binding.guideTv.updateLayoutParams<ConstraintLayout.LayoutParams> {
|
||||
horizontalBias = if (isCenterPosition) 0.5F else if (isRightPosition) 1F else 0F
|
||||
}
|
||||
|
||||
val popupWindow = BugFixedPopupWindow(
|
||||
binding.root,
|
||||
ConstraintLayout.LayoutParams.MATCH_PARENT,
|
||||
ConstraintLayout.LayoutParams.WRAP_CONTENT
|
||||
)
|
||||
popupWindow.contentView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED)
|
||||
val measureWidth = popupWindow.contentView.measuredWidth
|
||||
val measureHeight = popupWindow.contentView.measuredHeight
|
||||
if (measureWidth > restWidth) {
|
||||
binding.guideTv.translationX = 0F
|
||||
binding.guideIconIv.translationX = 0F
|
||||
}
|
||||
|
||||
return popupWindow.apply {
|
||||
isFocusable = false
|
||||
isOutsideTouchable = false
|
||||
animationStyle = R.style.popup_window_ease_in_and_out_anim_style
|
||||
setOnDismissListener {
|
||||
dismissCallback?.invoke()
|
||||
}
|
||||
handler?.post {
|
||||
if (!activity.isFinishing) {
|
||||
showAsDropDown(viewPager, 0, 8F.dip2px() - measureHeight)
|
||||
}
|
||||
handler.sendEmptyMessageDelayed(KEY_BOTTOM_TAB_GUIDE_AUTO_DISMISS, AUTO_DISMISS_DELAY_TIME)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -60,7 +60,7 @@ class CustomFloatingWindowHandler(priority: Int) : PriorityChainHandler(priority
|
||||
when (getStatus()) {
|
||||
STATUS_VALID -> {
|
||||
_showFloatingAction.value = Event(data)
|
||||
processNext()
|
||||
return true
|
||||
// floatingWindowProvider.showFloatingWindowOnly(
|
||||
// mFragment!!,
|
||||
// mRecyclerView!!,
|
||||
@ -79,4 +79,9 @@ class CustomFloatingWindowHandler(priority: Int) : PriorityChainHandler(priority
|
||||
return false
|
||||
}
|
||||
|
||||
fun dismiss() {
|
||||
if (getStatus() == STATUS_HANDLING || getStatus() == STATUS_VALID) {
|
||||
processNext()
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -18,6 +18,8 @@ import com.gh.gamecenter.core.AppExecutor
|
||||
import com.gh.gamecenter.core.utils.SPUtils
|
||||
import com.gh.gamecenter.entity.DialogEntity
|
||||
import com.gh.gamecenter.feature.entity.WelcomeDialogEntity
|
||||
import com.gh.gamecenter.hud.PendingInstallHUDHandler
|
||||
import com.gh.gamecenter.hud.ResumeDownloadHudHandler
|
||||
import com.gh.gamecenter.login.user.UserManager
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager
|
||||
import com.halo.assistant.HaloApp
|
||||
@ -57,6 +59,8 @@ object GlobalPriorityChainHelper : ISuperiorChain {
|
||||
val notificationPermissionDialogHandler = NotificationPermissionDialogHandler(0)
|
||||
val reserveDialogHandler = ReserveDialogHandler(1)
|
||||
val welcomeDialogHandler = WelcomeDialogHandler(2)
|
||||
val pendingInstallHandler = PendingInstallHUDHandler(3)
|
||||
val resumeDownloadHandler = ResumeDownloadHudHandler(4)
|
||||
|
||||
mainChain.addHandler(launchRedirectHandler)
|
||||
mainChain.addHandler(updateDialogHandler)
|
||||
@ -64,6 +68,8 @@ object GlobalPriorityChainHelper : ISuperiorChain {
|
||||
mainChain.addHandler(welcomeDialogHandler)
|
||||
mainChain.addHandler(reserveDialogHandler)
|
||||
mainChain.addHandler(notificationPermissionDialogHandler)
|
||||
mainChain.addHandler(pendingInstallHandler)
|
||||
mainChain.addHandler(resumeDownloadHandler)
|
||||
|
||||
launchRedirectHandler.doPreProcess()
|
||||
updateDialogHandler.doPreProcess()
|
||||
|
||||
@ -0,0 +1,297 @@
|
||||
package com.gh.common.prioritychain
|
||||
|
||||
import android.app.Activity
|
||||
import android.os.Handler
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.widget.PopupWindow
|
||||
import androidx.constraintlayout.widget.ConstraintLayout
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.constant.Constants
|
||||
import com.gh.gamecenter.common.utils.dip2px
|
||||
import com.gh.gamecenter.common.utils.goneIf
|
||||
import com.gh.gamecenter.common.view.BugFixedPopupWindow
|
||||
import com.gh.gamecenter.common.view.NoDefaultMinWidthTabLayout
|
||||
import com.gh.gamecenter.core.utils.DisplayUtils
|
||||
import com.gh.gamecenter.core.utils.SPUtils
|
||||
import com.gh.gamecenter.databinding.PopupMultiTabGuideBinding
|
||||
import com.gh.gamecenter.entity.BottomTab
|
||||
import com.gh.gamecenter.wrapper.BaseTabWrapperFragment
|
||||
import com.gh.gamecenter.wrapper.MainWrapperFragment
|
||||
import com.google.android.material.tabs.TabLayout
|
||||
import com.google.android.material.tabs.TabLayout.TabView
|
||||
|
||||
class MultiTabGuideHandler(priority: Int): PriorityChainHandler(priority) {
|
||||
private var mActivity: Activity? = null
|
||||
private var mHandler: Handler? = null
|
||||
private var mGuide: BottomTab.Guide? = null
|
||||
private var mTabLayout: TabLayout? = null
|
||||
private var mTabView: TabView? = null
|
||||
private var mIsSingleLineTab = false
|
||||
private var mMainWrapperFragment: MainWrapperFragment? = null
|
||||
private var mTabWrapperFragment: BaseTabWrapperFragment? = null
|
||||
|
||||
fun doPreProcess(
|
||||
shouldShow: Boolean,
|
||||
activity: Activity? = null,
|
||||
handler: Handler? = null,
|
||||
guide: BottomTab.Guide? = null,
|
||||
tabLayout: TabLayout? = null,
|
||||
tabView: TabLayout.TabView? = null,
|
||||
isSingleLineTab: Boolean = false,
|
||||
mainWrapperFragment: MainWrapperFragment? = null,
|
||||
tabWrapperFragment: BaseTabWrapperFragment? = null
|
||||
) {
|
||||
mActivity = activity
|
||||
mHandler = handler
|
||||
mGuide = guide
|
||||
mTabLayout = tabLayout
|
||||
mTabView = tabView
|
||||
mIsSingleLineTab = isSingleLineTab
|
||||
mMainWrapperFragment = mainWrapperFragment
|
||||
mTabWrapperFragment = tabWrapperFragment
|
||||
|
||||
if (getStatus() == STATUS_PENDING) {
|
||||
if (shouldShow) {
|
||||
updateStatus(STATUS_VALID)
|
||||
process()
|
||||
} else {
|
||||
processNext()
|
||||
}
|
||||
} else {
|
||||
if (shouldShow) {
|
||||
updateStatus(STATUS_VALID)
|
||||
} else {
|
||||
updateStatus(STATUS_INVALID)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onProcess(): Boolean {
|
||||
when (getStatus()) {
|
||||
STATUS_VALID -> {
|
||||
if (mGuide == null || mActivity == null || mTabView == null || mTabLayout == null) {
|
||||
processNext()
|
||||
return false
|
||||
}
|
||||
|
||||
return showMultiTabGuide(
|
||||
true,
|
||||
mActivity!!,
|
||||
mHandler,
|
||||
mGuide!!,
|
||||
mTabLayout!!,
|
||||
mTabView!!,
|
||||
mIsSingleLineTab,
|
||||
mMainWrapperFragment,
|
||||
mTabWrapperFragment
|
||||
) {
|
||||
processNext()
|
||||
}
|
||||
}
|
||||
|
||||
STATUS_INVALID -> {
|
||||
processNext()
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val TAB_GUIDE_TRIANGLE_OFFSET_DP = 5F
|
||||
private const val TAB_GUIDE_START_TRIANGLE_OFFSET_DP = 12F
|
||||
private const val TAB_GUIDE_RIGHT_SIDE_ICON_RIGHT_RESERVED_OFFSET_DP = 51F + TAB_GUIDE_TRIANGLE_OFFSET_DP // 光宝在文案右侧时预留引导到屏幕右侧的距离
|
||||
private const val TAB_GUIDE_RIGHT_SIDE_ICON_LEFT_RESERVED_OFFSET_DP = TAB_GUIDE_START_TRIANGLE_OFFSET_DP + TAB_GUIDE_TRIANGLE_OFFSET_DP // 光宝在文案作侧时预留引导到屏幕右侧的距离
|
||||
|
||||
fun showMultiTabGuide(
|
||||
isImmediately: Boolean,
|
||||
activity: Activity,
|
||||
handler: Handler?,
|
||||
guide: BottomTab.Guide,
|
||||
tabLayout: TabLayout,
|
||||
tabView: TabView,
|
||||
isSingleLineTab: Boolean = false,
|
||||
mainWrapperFragment: MainWrapperFragment? = null,
|
||||
tabWrapperFragment: BaseTabWrapperFragment? = null,
|
||||
dismissCallback: (() -> Unit)? = null
|
||||
): Boolean {
|
||||
val guideSet = HashSet(SPUtils.getStringSet(Constants.SP_MULTI_TAB_NAV_GUIDE_SET))
|
||||
val hasShownGuide = guideSet.contains(guide.multiTabId + guide.text)
|
||||
val isCurrentBottomTab = mainWrapperFragment == null || guide.bottomTabId == mainWrapperFragment.currentTab?.id
|
||||
if (!hasShownGuide && isCurrentBottomTab) {
|
||||
val screenWidth = DisplayUtils.getScreenWidth(activity)
|
||||
val outLocation = IntArray(2)
|
||||
tabView.getLocationOnScreen(outLocation)
|
||||
val tabViewCenterPosX = outLocation.first() + tabView.width / 2F
|
||||
val iconLeftMaxPosX = if (isSingleLineTab) tabLayout.width else tabLayout.width - TAB_GUIDE_RIGHT_SIDE_ICON_LEFT_RESERVED_OFFSET_DP.dip2px()
|
||||
val iconRightMaxPosX = if (isSingleLineTab) tabLayout.width else tabLayout.width - TAB_GUIDE_RIGHT_SIDE_ICON_RIGHT_RESERVED_OFFSET_DP.dip2px()
|
||||
val isIconLeftValid = tabViewCenterPosX <= iconLeftMaxPosX
|
||||
val isIconRightValid = tabViewCenterPosX <= iconRightMaxPosX
|
||||
val isTabViewShowOnScreen = tabViewCenterPosX > 0 && (isIconLeftValid || isIconRightValid)
|
||||
val isTabLayoutScrollStateIdle = (tabLayout as? NoDefaultMinWidthTabLayout)?.isScrollStateIdle == true
|
||||
if (isTabViewShowOnScreen && isTabLayoutScrollStateIdle) {
|
||||
val trianglePosX = tabViewCenterPosX - TAB_GUIDE_TRIANGLE_OFFSET_DP.dip2px()
|
||||
val guideStartPosX = trianglePosX - TAB_GUIDE_START_TRIANGLE_OFFSET_DP.dip2px()
|
||||
val xoff = tabView.width / 2 - TAB_GUIDE_START_TRIANGLE_OFFSET_DP.dip2px() - TAB_GUIDE_TRIANGLE_OFFSET_DP.dip2px()
|
||||
val restGuideWidth = screenWidth - guideStartPosX
|
||||
|
||||
showMultiTabPopupWindow(
|
||||
activity,
|
||||
handler,
|
||||
guide,
|
||||
tabView,
|
||||
xoff,
|
||||
screenWidth,
|
||||
restGuideWidth,
|
||||
isIconRightValid,
|
||||
dismissCallback
|
||||
)
|
||||
guideSet.add(guide.multiTabId + guide.text)
|
||||
SPUtils.setStringSet(Constants.SP_MULTI_TAB_NAV_GUIDE_SET, guideSet)
|
||||
|
||||
return true
|
||||
} else if (isImmediately) {
|
||||
(tabLayout as? NoDefaultMinWidthTabLayout)?.let {
|
||||
it.onScrollListener = object :
|
||||
NoDefaultMinWidthTabLayout.OnScrollListener() {
|
||||
override fun onScrollStateChanged(view: NoDefaultMinWidthTabLayout, scrollState: Int) {
|
||||
if (scrollState == SCROLL_STATE_IDLE) {
|
||||
showMultiTabGuideIfTabViewShow(
|
||||
activity,
|
||||
handler,
|
||||
guide,
|
||||
it,
|
||||
tabView,
|
||||
isSingleLineTab,
|
||||
mainWrapperFragment
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (isImmediately && !isCurrentBottomTab) {
|
||||
tabWrapperFragment?.setResumeAndPauseListener {
|
||||
if (it) {
|
||||
handler?.post {
|
||||
(tabLayout as? NoDefaultMinWidthTabLayout)?.let { tl ->
|
||||
showMultiTabGuideIfBottomTabShow(
|
||||
activity,
|
||||
handler,
|
||||
guide,
|
||||
tl,
|
||||
tabView,
|
||||
isSingleLineTab,
|
||||
mainWrapperFragment,
|
||||
tabWrapperFragment
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dismissCallback?.invoke()
|
||||
return false
|
||||
}
|
||||
|
||||
fun showMultiTabGuideIfTabViewShow(
|
||||
activity: Activity,
|
||||
handler: Handler?,
|
||||
guide: BottomTab.Guide,
|
||||
tabLayout: NoDefaultMinWidthTabLayout,
|
||||
tabView: TabView,
|
||||
isSingleLineTab: Boolean = false,
|
||||
mainWrapperFragment: MainWrapperFragment?
|
||||
) {
|
||||
if (showMultiTabGuide(
|
||||
false,
|
||||
activity,
|
||||
handler,
|
||||
guide,
|
||||
tabLayout,
|
||||
tabView,
|
||||
isSingleLineTab,
|
||||
mainWrapperFragment
|
||||
)
|
||||
) {
|
||||
tabLayout.onScrollListener = null
|
||||
}
|
||||
}
|
||||
|
||||
fun showMultiTabGuideIfBottomTabShow(
|
||||
activity: Activity,
|
||||
handler: Handler?,
|
||||
guide: BottomTab.Guide,
|
||||
tabLayout: NoDefaultMinWidthTabLayout,
|
||||
tabView: TabView,
|
||||
isSingleLineTab: Boolean = false,
|
||||
mainWrapperFragment: MainWrapperFragment?,
|
||||
tabWrapperFragment: BaseTabWrapperFragment?
|
||||
) {
|
||||
if (showMultiTabGuide(
|
||||
false,
|
||||
activity,
|
||||
handler,
|
||||
guide,
|
||||
tabLayout,
|
||||
tabView,
|
||||
isSingleLineTab,
|
||||
mainWrapperFragment,
|
||||
tabWrapperFragment
|
||||
)
|
||||
) {
|
||||
tabWrapperFragment?.setResumeAndPauseListener(null)
|
||||
}
|
||||
}
|
||||
|
||||
fun showMultiTabPopupWindow(
|
||||
activity: Activity,
|
||||
handler: Handler?,
|
||||
guide: BottomTab.Guide,
|
||||
tabView: TabView,
|
||||
xoff: Int,
|
||||
screenWidth: Int,
|
||||
restGuideWidth: Float,
|
||||
isIconRight: Boolean,
|
||||
dismissCallback: (() -> Unit)?
|
||||
): PopupWindow {
|
||||
val binding = PopupMultiTabGuideBinding.inflate(LayoutInflater.from(activity))
|
||||
binding.guideTv.text = guide.text
|
||||
binding.guideTriangleIv.translationX = 12F.dip2px().toFloat()
|
||||
binding.guideTv.setPadding(if (isIconRight) 8F.dip2px() else 52F.dip2px(), 0, if (isIconRight) 52F.dip2px() else 8F.dip2px(), 0)
|
||||
binding.guideIconIv.goneIf(!isIconRight)
|
||||
binding.guideIconFlipIv.goneIf(isIconRight)
|
||||
|
||||
val popupWindow = BugFixedPopupWindow(
|
||||
binding.root,
|
||||
ConstraintLayout.LayoutParams.WRAP_CONTENT,
|
||||
ConstraintLayout.LayoutParams.WRAP_CONTENT
|
||||
)
|
||||
popupWindow.contentView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED)
|
||||
val measureWidth = popupWindow.contentView.measuredWidth
|
||||
if (measureWidth >= screenWidth) {
|
||||
popupWindow.width = screenWidth
|
||||
binding.guideTriangleIv.translationX += screenWidth - restGuideWidth
|
||||
} else if (measureWidth > restGuideWidth) {
|
||||
binding.guideTriangleIv.translationX += measureWidth - restGuideWidth
|
||||
}
|
||||
|
||||
return popupWindow.apply {
|
||||
isTouchable = false
|
||||
isFocusable = false
|
||||
isOutsideTouchable = true
|
||||
animationStyle = R.style.popup_window_ease_in_and_out_anim_style
|
||||
setOnDismissListener {
|
||||
dismissCallback?.invoke()
|
||||
}
|
||||
handler?.post {
|
||||
if (!activity.isFinishing) {
|
||||
showAsDropDown(tabView, xoff, (-25F).dip2px())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,16 @@
|
||||
package com.gh.common.prioritychain
|
||||
|
||||
import com.gh.gamecenter.home.video.ScrollCalculatorHelper
|
||||
|
||||
class VideoHandler(priority: Int, val scrollCalculatorHelper: ScrollCalculatorHelper): PriorityChainHandler(priority) {
|
||||
|
||||
init {
|
||||
updateStatus(STATUS_VALID)
|
||||
}
|
||||
|
||||
override fun onProcess(): Boolean {
|
||||
scrollCalculatorHelper.enableAndPlayIfValid()
|
||||
return true
|
||||
}
|
||||
|
||||
}
|
||||
@ -89,4 +89,8 @@ class AppProviderImpl : IAppProvider {
|
||||
}
|
||||
|
||||
override fun getPluginVersion(): String = VCore.getInstance().getPluginVersion()
|
||||
|
||||
override fun initImageLoaderIfNeeded() {
|
||||
HaloApp.getInstance().initFresco()
|
||||
}
|
||||
}
|
||||
@ -100,6 +100,10 @@ class ConfigProviderImpl : IConfigProvider {
|
||||
return Config.getNightModeSetting()?.setting ?: false
|
||||
}
|
||||
|
||||
override fun isJiguangSwitch(): Boolean {
|
||||
return Config.getNewApiSettingsEntity()?.jiguangSwitch ?: false
|
||||
}
|
||||
|
||||
override fun init(context: Context?) {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
@ -1,11 +1,16 @@
|
||||
package com.gh.common.provider
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
import com.alibaba.android.arouter.facade.annotation.Route
|
||||
import com.gh.common.util.EntranceUtils
|
||||
import com.gh.gamecenter.common.avoidcallback.Callback
|
||||
import com.gh.gamecenter.common.constant.RouteConsts
|
||||
import com.gh.gamecenter.core.provider.IEntranceUtilsProvider
|
||||
import com.lightgame.utils.AppManager
|
||||
|
||||
@Route(path = RouteConsts.provider.entranceUtils, name = "EntranceUtils暴露服务")
|
||||
class EntranceUtilsProviderImpl : IEntranceUtilsProvider {
|
||||
@ -17,6 +22,19 @@ class EntranceUtilsProviderImpl : IEntranceUtilsProvider {
|
||||
EntranceUtils.saveShortcut(activityName, bundle)
|
||||
}
|
||||
|
||||
override fun jumpActivityWithCallback(context: Context, bundle: Bundle, callback: () -> Unit) {
|
||||
if (context is FragmentActivity && !context.supportFragmentManager.isDestroyed) {
|
||||
EntranceUtils.jumpActivity(context, null, bundle, object : Callback {
|
||||
override fun onActivityResult(resultCode: Int, data: Intent?) {
|
||||
callback()
|
||||
}
|
||||
})
|
||||
} else {
|
||||
EntranceUtils.jumpActivity(AppManager.getInstance().currentActivity(), bundle)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
override fun init(context: Context?) {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
@ -0,0 +1,23 @@
|
||||
package com.gh.common.provider
|
||||
|
||||
import android.content.Context
|
||||
import com.alibaba.android.arouter.facade.annotation.Route
|
||||
import com.gh.gamecenter.common.constant.Constants
|
||||
import com.gh.gamecenter.common.constant.RouteConsts
|
||||
import com.gh.gamecenter.core.provider.IMiniGameRecentlyPlayedProvider
|
||||
import com.gh.gamecenter.minigame.MiniGameRecentlyPlayUseCase
|
||||
|
||||
@Route(path = RouteConsts.provider.miniGameRecentPlayed, name = "MiniGameRecentlyPlayed暴露服务")
|
||||
class MiniGameRecentlyPlayedProviderImpl : IMiniGameRecentlyPlayedProvider {
|
||||
override fun clearMiniGameRecentlyPlayed(gameType: String) {
|
||||
MiniGameRecentlyPlayUseCase.clearRecentlyPlayedMiniGameList(gameType)
|
||||
}
|
||||
|
||||
override fun refreshQQMiniRecentPlayed() {
|
||||
MiniGameRecentlyPlayUseCase.loadRecentlyPlayedMiniGameList(Constants.QQ_MINI_GAME)
|
||||
}
|
||||
|
||||
override fun init(context: Context?) {
|
||||
// no implement
|
||||
}
|
||||
}
|
||||
@ -1,14 +1,21 @@
|
||||
package com.gh.common.util;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.gh.gamecenter.common.constant.EntranceConsts;
|
||||
import com.gh.gamecenter.login.view.LoginActivity;
|
||||
import com.gh.gamecenter.common.utils.NetworkUtils;
|
||||
import com.gh.gamecenter.core.utils.CurrentActivityHolder;
|
||||
import com.gh.gamecenter.login.user.UserManager;
|
||||
import com.gh.gamecenter.login.utils.QuickLoginHelper;
|
||||
import com.gh.gamecenter.login.view.LoginActivity;
|
||||
import com.lightgame.utils.Utils;
|
||||
|
||||
import kotlin.Unit;
|
||||
import kotlin.jvm.functions.Function0;
|
||||
|
||||
|
||||
/**
|
||||
* Created by khy on 28/06/17.
|
||||
@ -22,15 +29,15 @@ public class CheckLoginUtils {
|
||||
LogUtils.login("dialog", null, entrance);
|
||||
LogUtils.login("activity", null, entrance);
|
||||
|
||||
// if (SPUtils.getBoolean(Constants.SP_HAS_GET_PHONE_INFO) || NetworkUtils.isOpenMobileData(context)) {
|
||||
// startQuickLogin(context, entrance);
|
||||
// } else {
|
||||
// 有可能App未启动
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putString(EntranceConsts.KEY_ENTRANCE, entrance);
|
||||
bundle.putString(EntranceConsts.KEY_TO, LoginActivity.class.getName());
|
||||
EntranceUtils.jumpActivity(context, bundle);
|
||||
// }
|
||||
if (NetworkUtils.isQuickLoginEnabled(context)) {
|
||||
startQuickLogin(context, entrance, null);
|
||||
} else {
|
||||
// 有可能App未启动
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putString(EntranceConsts.KEY_ENTRANCE, entrance);
|
||||
bundle.putString(EntranceConsts.KEY_TO, LoginActivity.class.getName());
|
||||
EntranceUtils.jumpActivity(context, bundle);
|
||||
}
|
||||
} else {
|
||||
if (listener != null) {
|
||||
listener.onLogin();
|
||||
@ -38,16 +45,16 @@ public class CheckLoginUtils {
|
||||
}
|
||||
}
|
||||
|
||||
// private static void startQuickLogin(Context context, String entrance) {
|
||||
// // 需要确保传入的 context 不为 application
|
||||
// if (!(context instanceof Activity)) {
|
||||
// context = CurrentActivityHolder.getCurrentActivity();
|
||||
// }
|
||||
//
|
||||
// if (context != null) {
|
||||
// QuickLoginHelper.startLogin(context, entrance);
|
||||
// }
|
||||
// }
|
||||
private static void startQuickLogin(Context context, String entrance, Function0<Unit> callback) {
|
||||
// 需要确保传入的 context 不为 application
|
||||
if (!(context instanceof Activity)) {
|
||||
context = CurrentActivityHolder.getCurrentActivity();
|
||||
}
|
||||
|
||||
if (context != null) {
|
||||
QuickLoginHelper.startLogin(context, entrance, callback);
|
||||
}
|
||||
}
|
||||
|
||||
public static void checkLogin(final Context context, Bundle nextToBundle, boolean isTriggerNextStep, String entrance, OnLoginListener listener) {
|
||||
if (!isLogin()) {
|
||||
@ -55,15 +62,25 @@ public class CheckLoginUtils {
|
||||
LogUtils.login("dialog", null, entrance);
|
||||
LogUtils.login("activity", null, entrance);
|
||||
|
||||
// 有可能App未启动
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putString(EntranceConsts.KEY_ENTRANCE, entrance);
|
||||
bundle.putString(EntranceConsts.KEY_TO, LoginActivity.class.getName());
|
||||
EntranceUtils.jumpActivity(context, nextToBundle, bundle, (resultCode, data) -> {
|
||||
if (isTriggerNextStep && listener != null && isLogin()) {
|
||||
listener.onLogin();
|
||||
}
|
||||
});
|
||||
if (NetworkUtils.isQuickLoginEnabled(context)) {
|
||||
startQuickLogin(context, entrance, () -> {
|
||||
if (isTriggerNextStep && listener != null && isLogin()) {
|
||||
listener.onLogin();
|
||||
}
|
||||
return null;
|
||||
});
|
||||
} else {
|
||||
// 有可能App未启动
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putString(EntranceConsts.KEY_ENTRANCE, entrance);
|
||||
bundle.putString(EntranceConsts.KEY_TO, LoginActivity.class.getName());
|
||||
EntranceUtils.jumpActivity(context, nextToBundle, bundle, (resultCode, data) -> {
|
||||
if (isTriggerNextStep && listener != null && isLogin()) {
|
||||
listener.onLogin();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
} else {
|
||||
if (listener != null) {
|
||||
listener.onLogin();
|
||||
|
||||
@ -5,7 +5,6 @@ import android.text.TextUtils;
|
||||
import android.view.View;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.gh.common.constant.Config;
|
||||
import com.gh.common.filter.RegionSetting;
|
||||
import com.gh.common.filter.RegionSettingHelper;
|
||||
import com.gh.common.repository.ReservationRepository;
|
||||
@ -19,6 +18,7 @@ import com.gh.gamecenter.common.constant.Constants;
|
||||
import com.gh.gamecenter.common.entity.LinkEntity;
|
||||
import com.gh.gamecenter.common.utils.ExtensionsKt;
|
||||
import com.gh.gamecenter.core.utils.SPUtils;
|
||||
import com.gh.gamecenter.core.utils.SpeedUtils;
|
||||
import com.gh.gamecenter.feature.entity.GameEntity;
|
||||
import com.gh.gamecenter.feature.entity.PluginLocation;
|
||||
import com.gh.gamecenter.feature.view.DownloadButton;
|
||||
@ -48,11 +48,6 @@ public class DetailDownloadUtils {
|
||||
GameEntity gameEntity = viewHolder.getGameEntity();
|
||||
String downloadAddWord = gameEntity.getDownloadAddWord();
|
||||
|
||||
// 隐藏下载按钮上的畅玩文案
|
||||
if (viewHolder.getOverlayTv() != null) {
|
||||
viewHolder.getOverlayTv().setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
// 多版本下载箭头
|
||||
if (viewHolder.getMultiVersionDownloadTv() != null) {
|
||||
viewHolder.getMultiVersionDownloadTv().setVisibility(View.GONE);
|
||||
@ -117,17 +112,6 @@ public class DetailDownloadUtils {
|
||||
}
|
||||
}
|
||||
|
||||
// 更新默认的下载按钮
|
||||
updateWithSingleApk(
|
||||
gameEntity,
|
||||
viewHolder,
|
||||
viewHolder.getDownloadPb(),
|
||||
downloadAddWord,
|
||||
showVGame,
|
||||
showDualDownloadButton,
|
||||
downloadEntity
|
||||
);
|
||||
|
||||
if (showDualDownloadButton) {
|
||||
// 双下载按钮时更新占位的下载按钮
|
||||
updateWithSingleApk(
|
||||
@ -140,6 +124,17 @@ public class DetailDownloadUtils {
|
||||
downloadEntity
|
||||
);
|
||||
}
|
||||
|
||||
// 更新默认的下载按钮
|
||||
updateWithSingleApk(
|
||||
gameEntity,
|
||||
viewHolder,
|
||||
viewHolder.getDownloadPb(),
|
||||
downloadAddWord,
|
||||
showVGame,
|
||||
showDualDownloadButton,
|
||||
downloadEntity
|
||||
);
|
||||
} else {
|
||||
// 游戏包含多 APK 的情况
|
||||
viewHolder.getMultiVersionDownloadTv().setText("选择下载你的版本" + (TextUtils.isEmpty(downloadAddWord) ? "" : "-" + downloadAddWord));
|
||||
@ -192,49 +187,53 @@ public class DetailDownloadUtils {
|
||||
Context context = viewHolder.getContext();
|
||||
TextView overlayTv = viewHolder.getOverlayTv();
|
||||
|
||||
String status = GameUtils.getDownloadBtnText(context, gameEntity, false, showAsVGame, PluginLocation.only_game);
|
||||
boolean containsAddWord = !TextUtils.isEmpty(downloadAddWord); // 是否存在下载补充文案
|
||||
|
||||
// 根据游戏实体获取下载按钮文案
|
||||
String rawBtnText = GameUtils.getDownloadBtnText(context, gameEntity, false, showAsVGame, PluginLocation.only_game);
|
||||
|
||||
if (showAsVGame) {
|
||||
// 显示为畅玩游戏
|
||||
if (context.getString(R.string.launch).equals(status)) {
|
||||
if (context.getString(R.string.launch).equals(rawBtnText)) {
|
||||
downloadButton.setButtonStyle(DownloadButton.ButtonStyle.LAUNCH_OR_OPEN);
|
||||
} else {
|
||||
downloadButton.setButtonStyle(DownloadButton.ButtonStyle.NORMAL);
|
||||
}
|
||||
|
||||
String btnText;
|
||||
String decoratedBtnText;
|
||||
// 双下载按钮时,显示特殊样式
|
||||
if (showDualDownloadButton
|
||||
&& (context.getString(R.string.launch).equals(status) || context.getString(R.string.install).equals(status) || context.getString(R.string.smooth).equals(status) || context.getString(R.string.update).equals(status))) {
|
||||
if (context.getString(R.string.smooth).equals(status)) {
|
||||
btnText = context.getString(R.string.download_v);
|
||||
} else if (context.getString(R.string.update).equals(status)) {
|
||||
btnText = context.getString(R.string.update_v);
|
||||
&& (context.getString(R.string.launch).equals(rawBtnText) || context.getString(R.string.install).equals(rawBtnText) || context.getString(R.string.smooth).equals(rawBtnText) || context.getString(R.string.update).equals(rawBtnText))) {
|
||||
if (context.getString(R.string.smooth).equals(rawBtnText)) {
|
||||
decoratedBtnText = context.getString(R.string.download_v);
|
||||
} else if (context.getString(R.string.update).equals(rawBtnText)) {
|
||||
decoratedBtnText = context.getString(R.string.update_v);
|
||||
} else {
|
||||
btnText = context.getString(R.string.launch_v);
|
||||
decoratedBtnText = context.getString(R.string.launch_v);
|
||||
}
|
||||
|
||||
if (overlayTv != null && downloadButton.getVisibility() != View.GONE) {
|
||||
overlayTv.setVisibility(View.VISIBLE);
|
||||
overlayTv.setText(btnText);
|
||||
overlayTv.setText(decoratedBtnText);
|
||||
downloadButton.setText("");
|
||||
}
|
||||
} else {
|
||||
btnText = status + (TextUtils.isEmpty(downloadAddWord) ? "" : downloadAddWord) + getDownloadSizeText(viewHolder);
|
||||
decoratedBtnText = rawBtnText + (containsAddWord? "" : downloadAddWord) + getWrappedDownloadSizeText(viewHolder);
|
||||
|
||||
if (overlayTv != null && downloadButton.getVisibility() != View.GONE) {
|
||||
if (context.getString(R.string.launch).equals(status)
|
||||
|| context.getString(R.string.install).equals(status)) {
|
||||
if (context.getString(R.string.launch).equals(rawBtnText)
|
||||
|| context.getString(R.string.install).equals(rawBtnText)) {
|
||||
overlayTv.setVisibility(View.VISIBLE);
|
||||
overlayTv.setText("启动(畅玩)");
|
||||
} else {
|
||||
overlayTv.setVisibility(View.GONE);
|
||||
downloadButton.setText(btnText);
|
||||
downloadButton.setText(decoratedBtnText);
|
||||
}
|
||||
} else {
|
||||
if (overlayTv != null) {
|
||||
overlayTv.setVisibility(View.GONE);
|
||||
}
|
||||
downloadButton.setText(btnText);
|
||||
downloadButton.setText(decoratedBtnText);
|
||||
}
|
||||
}
|
||||
|
||||
@ -247,11 +246,11 @@ public class DetailDownloadUtils {
|
||||
}
|
||||
} else {
|
||||
// 非畅玩,显示为普通游戏
|
||||
if (context.getString(R.string.pluggable).equals(status)) {
|
||||
if (context.getString(R.string.pluggable).equals(rawBtnText)) {
|
||||
downloadButton.setButtonStyle(DownloadButton.ButtonStyle.PLUGIN);
|
||||
} else if (context.getString(R.string.launch).equals(status)) {
|
||||
} else if (context.getString(R.string.launch).equals(rawBtnText)) {
|
||||
downloadButton.setButtonStyle(DownloadButton.ButtonStyle.LAUNCH_OR_OPEN);
|
||||
} else if (context.getString(R.string.install).equals(status)) {
|
||||
} else if (context.getString(R.string.install).equals(rawBtnText)) {
|
||||
downloadButton.setButtonStyle(DownloadButton.ButtonStyle.INSTALL_NORMAL);
|
||||
} else {
|
||||
downloadButton.setButtonStyle(DownloadButton.ButtonStyle.NORMAL);
|
||||
@ -271,48 +270,78 @@ public class DetailDownloadUtils {
|
||||
}
|
||||
}
|
||||
|
||||
String btnText;
|
||||
String extraBtnText;
|
||||
String decoratedBtnText;
|
||||
String localBtnText;
|
||||
boolean useAlternativeTextStyle = false; // 是否使用带图标的文案,仅不包含补充文案时使用且
|
||||
|
||||
// 更新下载按钮文案
|
||||
if (viewHolder.isNewsDetail()) {
|
||||
btnText = status;
|
||||
extraBtnText = status;
|
||||
} else if (context.getString(R.string.pluggable).equals(status)) {
|
||||
btnText = "升级" + (TextUtils.isEmpty(downloadAddWord) ? "" : "至" + downloadAddWord) + getDownloadSizeText(viewHolder);
|
||||
extraBtnText = "升级" + (TextUtils.isEmpty(downloadAddWord) ? "" : "至" + downloadAddWord);
|
||||
} else if (context.getString(R.string.launch).equals(status)) {
|
||||
btnText = status + (TextUtils.isEmpty(downloadAddWord) ? "" : "-" + downloadAddWord);
|
||||
extraBtnText = context.getString(R.string.launch_local);
|
||||
} else if (context.getString(R.string.attempt).equals(status)) {
|
||||
btnText = status + getDownloadSizeText(viewHolder);
|
||||
extraBtnText = status;
|
||||
decoratedBtnText = rawBtnText;
|
||||
localBtnText = rawBtnText;
|
||||
} else if (context.getString(R.string.pluggable).equals(rawBtnText)) {
|
||||
decoratedBtnText = "升级" + (!containsAddWord ? "" : "至" + downloadAddWord) + getWrappedDownloadSizeText(viewHolder);
|
||||
localBtnText = "升级" + (!containsAddWord ? "" : "至" + downloadAddWord);
|
||||
} else if (context.getString(R.string.launch).equals(rawBtnText)) {
|
||||
decoratedBtnText = rawBtnText + (!containsAddWord ? "" : "-" + downloadAddWord);
|
||||
localBtnText = context.getString(R.string.launch_local);
|
||||
} else if (context.getString(R.string.attempt).equals(rawBtnText)) {
|
||||
decoratedBtnText = context.getString(R.string.attempt);
|
||||
localBtnText = rawBtnText;
|
||||
if (showDualDownloadButton
|
||||
&& viewHolder.getLocalDownloadContainer() != null
|
||||
&& viewHolder.getLocalDownloadContainer().getVisibility() == View.VISIBLE) {
|
||||
viewHolder.getLocalDownloadSizeTv().setVisibility(View.VISIBLE);
|
||||
} else if (viewHolder.getOverlayTv() != null) {
|
||||
useAlternativeTextStyle = true;
|
||||
}
|
||||
} else if (context.getString(R.string.install).equals(status)) {
|
||||
btnText = context.getString(R.string.install);
|
||||
extraBtnText = context.getString(R.string.install_local);
|
||||
} else if (context.getString(R.string.update).equals(status)) {
|
||||
btnText = context.getString(R.string.update);
|
||||
extraBtnText = context.getString(R.string.update_local);
|
||||
} else if (context.getString(R.string.install).equals(rawBtnText)) {
|
||||
decoratedBtnText = context.getString(R.string.install);
|
||||
localBtnText = context.getString(R.string.install_local);
|
||||
} else if (context.getString(R.string.update).equals(rawBtnText)) {
|
||||
decoratedBtnText = context.getString(R.string.update);
|
||||
localBtnText = context.getString(R.string.update_local);
|
||||
if (showDualDownloadButton
|
||||
&& viewHolder.getLocalDownloadContainer() != null
|
||||
&& viewHolder.getLocalDownloadContainer().getVisibility() == View.VISIBLE) {
|
||||
viewHolder.getLocalDownloadSizeTv().setVisibility(View.VISIBLE);
|
||||
}
|
||||
} else {
|
||||
btnText = status + (TextUtils.isEmpty(downloadAddWord) ? "" : downloadAddWord) + getDownloadSizeText(viewHolder);
|
||||
extraBtnText = context.getString(R.string.download_local);
|
||||
if (containsAddWord) {
|
||||
decoratedBtnText = rawBtnText + downloadAddWord + getWrappedDownloadSizeText(viewHolder);
|
||||
} else {
|
||||
decoratedBtnText = rawBtnText;
|
||||
}
|
||||
localBtnText = context.getString(R.string.download_local);
|
||||
if (showDualDownloadButton
|
||||
&& viewHolder.getLocalDownloadContainer() != null
|
||||
&& viewHolder.getLocalDownloadContainer().getVisibility() == View.VISIBLE) {
|
||||
viewHolder.getLocalDownloadSizeTv().setVisibility(View.VISIBLE);
|
||||
} else if (viewHolder.getOverlayTv() != null && !containsAddWord) {
|
||||
useAlternativeTextStyle = true;
|
||||
}
|
||||
}
|
||||
downloadButton.setText(btnText);
|
||||
|
||||
if (useAlternativeTextStyle) {
|
||||
downloadButton.setText("");
|
||||
viewHolder.getOverlayTv().setText(decoratedBtnText);
|
||||
viewHolder.getOverlayTv().setVisibility(View.VISIBLE);
|
||||
viewHolder.getOverlayTv().setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_special_download, 0, 0, 0);
|
||||
if (viewHolder.getExtraOverlayTv() != null) {
|
||||
viewHolder.getExtraOverlayTv().setVisibility(View.VISIBLE);
|
||||
viewHolder.getExtraOverlayTv().setText(gameEntity.getApk().get(0).getSize());
|
||||
}
|
||||
} else {
|
||||
if (viewHolder.getOverlayTv() != null && !showDualDownloadButton) {
|
||||
viewHolder.getOverlayTv().setVisibility(View.GONE);
|
||||
if (viewHolder.getExtraOverlayTv() != null) {
|
||||
viewHolder.getExtraOverlayTv().setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
downloadButton.setText(decoratedBtnText);
|
||||
}
|
||||
|
||||
if (viewHolder.getLocalDownloadTitleTv() != null) {
|
||||
viewHolder.getLocalDownloadTitleTv().setText(extraBtnText);
|
||||
viewHolder.getLocalDownloadTitleTv().setText(localBtnText);
|
||||
}
|
||||
}
|
||||
|
||||
@ -349,10 +378,13 @@ public class DetailDownloadUtils {
|
||||
if (overlayTv != null
|
||||
&& downloadEntity.getStatus() != DownloadStatus.done) {
|
||||
overlayTv.setVisibility(View.GONE);
|
||||
if (viewHolder.getExtraOverlayTv() != null) {
|
||||
viewHolder.getExtraOverlayTv().setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
if (showAsVGame) {
|
||||
updateVStyleDownloadButton(viewHolder, downloadButton, downloadEntity, status);
|
||||
updateVStyleDownloadButton(viewHolder, downloadButton, downloadEntity, rawBtnText);
|
||||
} else {
|
||||
updateDefaultStyleDownloadButton(context, viewHolder, downloadButton, gameEntity, downloadEntity);
|
||||
}
|
||||
@ -441,7 +473,7 @@ public class DetailDownloadUtils {
|
||||
return false;
|
||||
}
|
||||
|
||||
private static String getDownloadSizeText(DetailViewHolder viewHolder) {
|
||||
private static String getWrappedDownloadSizeText(DetailViewHolder viewHolder) {
|
||||
return String.format("(%s)", viewHolder.getGameEntity().getApk().isEmpty() ? "" : viewHolder.getGameEntity().getApk().get(0).getSize());
|
||||
}
|
||||
|
||||
@ -452,7 +484,7 @@ public class DetailDownloadUtils {
|
||||
switch (downloadEntity.getStatus()) {
|
||||
case redirected:
|
||||
case downloading:
|
||||
downloadButton.setText("游戏加载中 " + downloadEntity.getPercent() + "%");
|
||||
downloadButton.setText(SpeedUtils.getSpeed(downloadEntity.getSpeed()));
|
||||
downloadButton.setButtonStyle(DownloadButton.ButtonStyle.DOWNLOADING_NORMAL);
|
||||
break;
|
||||
case waiting:
|
||||
@ -466,11 +498,13 @@ public class DetailDownloadUtils {
|
||||
case diskisfull:
|
||||
case diskioerror:
|
||||
case pause:
|
||||
downloadButton.setText("继续加载 " + downloadEntity.getPercent() + "%");
|
||||
String pausedText = viewHolder.getContext().getString(R.string.paused);
|
||||
downloadButton.setText(getValidProgress(downloadEntity) + "% " + pausedText);
|
||||
downloadButton.setButtonStyle(DownloadButton.ButtonStyle.DOWNLOADING_NORMAL);
|
||||
break;
|
||||
case done:
|
||||
if (!status.contains("更新")) {
|
||||
String updateText = viewHolder.getContext().getString(R.string.update);
|
||||
if (!status.contains(updateText)) {
|
||||
if (VHelper.isInstalled(downloadEntity.getPackageName())) {
|
||||
downloadButton.setButtonStyle(DownloadButton.ButtonStyle.LAUNCH_OR_OPEN);
|
||||
} else {
|
||||
@ -510,8 +544,9 @@ public class DetailDownloadUtils {
|
||||
case diskisfull:
|
||||
case diskioerror:
|
||||
case overflow:
|
||||
String downloadingText = "游戏加载中 " + downloadEntity.getPercent() + "%";
|
||||
String resumeText = "继续加载 " + downloadEntity.getPercent() + "%";
|
||||
String pausedText = context.getString(R.string.paused);
|
||||
String downloadingText = SpeedUtils.getSpeed(downloadEntity.getSpeed());
|
||||
String resumeText = getValidProgress(downloadEntity) + "% " + pausedText;
|
||||
downloadButton.setText((downloadEntity.getStatus() == DownloadStatus.downloading || downloadEntity.getStatus() == DownloadStatus.redirected) ? downloadingText : resumeText);
|
||||
if (downloadEntity.isPluggable() && PackagesManager.isInstalled(downloadEntity.getPackageName())) {
|
||||
downloadButton.setButtonStyle(DownloadButton.ButtonStyle.DOWNLOADING_PLUGIN);
|
||||
@ -561,6 +596,10 @@ public class DetailDownloadUtils {
|
||||
}
|
||||
}
|
||||
|
||||
public static int getValidProgress(DownloadEntity downloadEntity) {
|
||||
return (int) Math.ceil(downloadEntity.getPercent());
|
||||
}
|
||||
|
||||
private static boolean handleDownloadButtonAsXapk(DownloadEntity downloadEntity, DownloadButton downloadButton) {
|
||||
String xapkStatus = downloadEntity.getMeta().get(XapkInstaller.XAPK_UNZIP_STATUS);
|
||||
|
||||
|
||||
@ -19,8 +19,6 @@ import com.gh.common.util.EntranceUtils.jumpActivity
|
||||
import com.gh.common.util.EntranceUtils.jumpActivityCompat
|
||||
import com.gh.gamecenter.*
|
||||
import com.gh.gamecenter.amway.AmwayActivity
|
||||
import com.gh.gamecenter.catalog.CatalogActivity
|
||||
import com.gh.gamecenter.category.CategoryDirectoryActivity
|
||||
import com.gh.gamecenter.category2.CategoryV2Activity
|
||||
import com.gh.gamecenter.common.base.activity.BaseActivity
|
||||
import com.gh.gamecenter.common.base.activity.BaseActivity_TabLayout
|
||||
@ -151,14 +149,12 @@ object DirectUtils {
|
||||
"qqqun",
|
||||
"tag",
|
||||
"all_community_article",
|
||||
"category",
|
||||
"block",
|
||||
"column_collection",
|
||||
"server",
|
||||
"top_game_comment",
|
||||
"wechat_bind",
|
||||
"video",
|
||||
"catalog",
|
||||
"category_v2",
|
||||
"common_collection",
|
||||
"game_list",
|
||||
@ -285,10 +281,6 @@ object DirectUtils {
|
||||
)
|
||||
)
|
||||
|
||||
"category", "分类" -> directCategoryDirectory(context, linkEntity.link!!, linkEntity.text!!)
|
||||
|
||||
"catalog" -> directCatalog(context, linkEntity.link!!, linkEntity.text!!, entrance, path)
|
||||
|
||||
"category_v2" -> directCategoryV2(
|
||||
context,
|
||||
linkEntity.link!!,
|
||||
@ -481,6 +473,7 @@ object DirectUtils {
|
||||
"column_test_v2" -> context.startActivity(
|
||||
GameServerTestV2Activity.getIntent(
|
||||
context,
|
||||
linkEntity.link ?: "none",
|
||||
entrance,
|
||||
exposureEvent
|
||||
)
|
||||
@ -1422,47 +1415,6 @@ object DirectUtils {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 跳转分类
|
||||
*/
|
||||
@JvmStatic
|
||||
fun directCategoryDirectory(
|
||||
context: Context,
|
||||
categoryId: String,
|
||||
categoryTitle: String,
|
||||
entrance: String? = null,
|
||||
path: String? = ""
|
||||
) {
|
||||
if (categoryId.isEmpty()) return
|
||||
val bundle = Bundle()
|
||||
bundle.putString(KEY_TO, CategoryDirectoryActivity::class.java.name)
|
||||
bundle.putString(KEY_CATEGORY_ID, categoryId)
|
||||
bundle.putString(KEY_CATEGORY_TITLE, categoryTitle)
|
||||
bundle.putString(KEY_ENTRANCE, entrance ?: ENTRANCE_BROWSER)
|
||||
bundle.putString(KEY_PATH, path)
|
||||
jumpActivity(context, bundle)
|
||||
}
|
||||
|
||||
/**
|
||||
* 跳转新分类
|
||||
*/
|
||||
@JvmStatic
|
||||
fun directCatalog(
|
||||
context: Context,
|
||||
catalogId: String,
|
||||
catalogTitle: String,
|
||||
entrance: String? = null,
|
||||
path: String? = "",
|
||||
) {
|
||||
if (catalogId.isEmpty()) return
|
||||
val bundle = Bundle()
|
||||
bundle.putString(KEY_TO, CatalogActivity::class.java.name)
|
||||
bundle.putString(KEY_CATALOG_ID, catalogId)
|
||||
bundle.putString(KEY_CATALOG_TITLE, catalogTitle)
|
||||
bundle.putString(KEY_ENTRANCE, BaseActivity.mergeEntranceAndPath(entrance, path))
|
||||
jumpActivity(context, bundle)
|
||||
}
|
||||
|
||||
/**
|
||||
* 跳转新分类2.0
|
||||
*/
|
||||
|
||||
@ -37,10 +37,10 @@ import com.gh.gamecenter.core.utils.*
|
||||
import com.gh.gamecenter.feature.entity.GameEntity
|
||||
import com.gh.gamecenter.feature.entity.PluginLocation
|
||||
import com.gh.gamecenter.feature.exposure.ExposureEvent
|
||||
import com.gh.gamecenter.feature.minigame.MiniGameItemHelper
|
||||
import com.gh.gamecenter.feature.view.DownloadButton
|
||||
import com.gh.gamecenter.gamedetail.dialog.GamePermissionDialogFragment
|
||||
import com.gh.gamecenter.manager.PackagesManager
|
||||
import com.gh.gamecenter.feature.minigame.MiniGameItemHelper
|
||||
import com.gh.gamecenter.teenagermode.TeenagerModeActivity
|
||||
import com.gh.vspace.VHelper
|
||||
import com.lightgame.download.DownloadConfig
|
||||
@ -697,7 +697,7 @@ object DownloadItemUtils {
|
||||
// 为 downloadButton 添加游戏实体,供点击的时候上报用
|
||||
downloadBtn.putObject(gameEntity)
|
||||
|
||||
val gamePermissionDialogFragment = (context as AppCompatActivity).supportFragmentManager.findFragmentByTag(
|
||||
val gamePermissionDialogFragment = (context as? AppCompatActivity)?.supportFragmentManager?.findFragmentByTag(
|
||||
GamePermissionDialogFragment::class.java.name
|
||||
) as GamePermissionDialogFragment?
|
||||
gamePermissionDialogFragment?.dismissAllowingStateLoss()
|
||||
@ -1162,7 +1162,11 @@ object DownloadItemUtils {
|
||||
isSubscribe,
|
||||
traceEvent
|
||||
)
|
||||
ToastUtils.toast(gameEntity.name + "已加入下载队列")
|
||||
if (asVGame) {
|
||||
ToastUtils.toast(gameEntity.name + "已加入加载队列")
|
||||
} else {
|
||||
ToastUtils.toast(gameEntity.name + "已加入下载队列")
|
||||
}
|
||||
if (BrowserInstallHelper.shouldAutoSwitchAssistantInstall(gameEntity)) {
|
||||
val toast = context.getString(R.string.unsupported_browser_install_hint)
|
||||
AppExecutor.uiExecutor.executeWithDelay({
|
||||
|
||||
@ -499,7 +499,7 @@ object DownloadObserver {
|
||||
"game_name", downloadEntity.name,
|
||||
"game_id", downloadEntity.gameId,
|
||||
"game_type", downloadEntity.categoryChinese,
|
||||
"game_schema_type", if (downloadEntity.getMetaExtra(VHelper.KEY_BIT) == "32") "32位" else "64位",
|
||||
"game_schema_type", if (downloadEntity.getMetaExtra(Constants.KEY_BIT) == "32") "32位" else "64位",
|
||||
*kvs
|
||||
)
|
||||
} else if (downloadEntity.gameId == Constants.HALO_FUN_GAME_ID) {
|
||||
@ -534,7 +534,7 @@ object DownloadObserver {
|
||||
"game_name", downloadEntity.meta[Constants.GAME_NAME] ?: "",
|
||||
"game_type", downloadEntity.meta[Constants.GAME_CATEGORY_IN_CHINESE] ?: "",
|
||||
"game_label", downloadEntity.tags.joinToString(","),
|
||||
"game_schema_type", if (downloadEntity.getMetaExtra(VHelper.KEY_BIT) == "32") "32位" else "64位",
|
||||
"game_schema_type", if (downloadEntity.getMetaExtra(Constants.KEY_BIT) == "32") "32位" else "64位",
|
||||
"page_name", getCurrentPageEntity().pageName,
|
||||
"page_id", getCurrentPageEntity().pageId,
|
||||
"page_business_id", getCurrentPageEntity().pageBusinessId,
|
||||
|
||||
@ -105,9 +105,14 @@ public class EntranceUtils {
|
||||
//TODO:添加FLAG_ACTIVITY_NEW_TASK会导致一跳转页面callback就被调用
|
||||
//intent1.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
intent1.putExtras(bundle);
|
||||
if (context instanceof AppCompatActivity) {
|
||||
AvoidOnResultManager.Companion.getInstance((AppCompatActivity) context)
|
||||
.startForResult(intent1, callback);
|
||||
} else {
|
||||
// 不要回调,正常跳转
|
||||
context.startActivity(intent1);
|
||||
}
|
||||
|
||||
AvoidOnResultManager.Companion.getInstance((AppCompatActivity) context)
|
||||
.startForResult(intent1, callback);
|
||||
}
|
||||
} else {
|
||||
// 应用未在运行
|
||||
|
||||
@ -7,6 +7,7 @@ import com.gh.gamecenter.common.utils.toObject
|
||||
import com.gh.gamecenter.feature.entity.GameEntity
|
||||
import com.gh.gamecenter.entity.SubjectEntity
|
||||
import com.gh.gamecenter.common.retrofit.Response
|
||||
import com.gh.gamecenter.manager.PackagesManager
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager
|
||||
import com.halo.assistant.HaloApp
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
@ -111,6 +112,14 @@ object GameSubstituteRepositoryHelper {
|
||||
}
|
||||
}
|
||||
|
||||
// 检查是否已安装该游戏 id
|
||||
if (PackagesManager.getInstalledDataByGameId(game.id) != null) {
|
||||
// 将该位置的游戏标记为需要替换
|
||||
positionOfGameToBeReplacedList.add(index)
|
||||
thisPositionNeedToBeReplaced = true
|
||||
break
|
||||
}
|
||||
|
||||
// 若此游戏所包含的 apk 没有已安装,那么再检查是否已安装有预设相关包名
|
||||
if (!thisPositionNeedToBeReplaced) {
|
||||
var relatedPackageList = arrayListOf<String>()
|
||||
|
||||
@ -308,7 +308,7 @@ object GameUtils {
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否以畅玩游戏的形式来处理
|
||||
* 是否默认以畅玩游戏的形式来处理
|
||||
*/
|
||||
@JvmStatic
|
||||
fun shouldPerformAsVGame(gameEntity: GameEntity): Boolean {
|
||||
|
||||
@ -57,6 +57,10 @@ object HomeBottomBarHelper {
|
||||
return BottomTab(name = "我的光环", jsCode = animationCode, iconSelector = R.drawable.selector_ic_user, link = LinkEntity(type = TYPE_MY_HALO))
|
||||
}
|
||||
|
||||
fun isDefaultHomeBottomTabDataExist(): Boolean {
|
||||
return SPUtils.getString(KEY_HOME_BOTTOM_TAB).isNotEmpty()
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun getDefaultHomeBottomTabData(): List<BottomTab> {
|
||||
try {
|
||||
|
||||
@ -734,18 +734,6 @@ public class LogUtils {
|
||||
LoghubUtils.log(object, LOG_STORE_EVENT, false);
|
||||
}
|
||||
|
||||
public static void logNewCatalogAppearanceEvent(String entrance, String key) {
|
||||
logCatalogEvent("access_to_classification", entrance, key, -1, -1, -1, -1);
|
||||
}
|
||||
|
||||
public static void logSubCatalogClickEvent(String entrance, String key, int seq1) {
|
||||
logCatalogEvent("click_first_classification", entrance, key, seq1, -1, -1, -1);
|
||||
}
|
||||
|
||||
public static void logSubCatalogContentClickEvent(String entrance, String key, int seq1, int seq2) {
|
||||
logCatalogEvent("click_secondary_classification", entrance, key, seq1, seq2, -1, -1);
|
||||
}
|
||||
|
||||
public static void logSpecialCatalogContentClickEvent(String entrance, String key, int seq1, int seqContent) {
|
||||
logCatalogEvent("click_content", entrance, key, seq1, -1, seqContent, -1);
|
||||
}
|
||||
|
||||
@ -4,12 +4,18 @@ import androidx.lifecycle.DefaultLifecycleObserver
|
||||
import androidx.lifecycle.LifecycleOwner
|
||||
import com.gh.download.DownloadManager
|
||||
import com.gh.download.PackageObserver
|
||||
import com.gh.gamecenter.DownloadManagerActivity
|
||||
import com.gh.gamecenter.common.utils.NewFlatLogUtils
|
||||
import com.gh.gamecenter.common.utils.SensorsBridge
|
||||
import com.gh.gamecenter.core.utils.CurrentActivityHolder
|
||||
import com.gh.gamecenter.eventbus.EBPackage
|
||||
import com.gh.gamecenter.feature.entity.GameEntity
|
||||
import com.gh.gamecenter.hud.HeadUpDisplayHelper
|
||||
import com.gh.gamecenter.manager.PackagesManager
|
||||
import com.gh.gamecenter.packagehelper.PackageRepository
|
||||
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.hud.HeadUpDisplayLogHelper
|
||||
import com.lightgame.utils.Utils
|
||||
import org.greenrobot.eventbus.EventBus
|
||||
|
||||
@ -22,8 +28,10 @@ object PackageChangeHelper : DefaultLifecycleObserver {
|
||||
private const val UPDATE_PENDING = 3
|
||||
|
||||
// <包名,pending 类型,应用版本> Triple
|
||||
private var pendingPackagePair: Triple<String, Int, String>? = null
|
||||
private var pendingGhId: String ? = null
|
||||
private var pendingPackageTriple: Triple<String, Int, String>? = null
|
||||
private var pendingGhId: String? = null
|
||||
|
||||
private var pendingHUDShowed: Boolean = false
|
||||
|
||||
/**
|
||||
* 添加一个等待中,待确定是否已成功安装的应用
|
||||
@ -33,7 +41,9 @@ object PackageChangeHelper : DefaultLifecycleObserver {
|
||||
|
||||
if (installData == null) {
|
||||
Utils.log(TAG, "添加了: $packageName 包名等待安装成功")
|
||||
pendingPackagePair = Triple(packageName, INSTALL_PENDING, "")
|
||||
|
||||
pendingHUDShowed = false
|
||||
pendingPackageTriple = Triple(packageName, INSTALL_PENDING, "")
|
||||
} else {
|
||||
Utils.log(TAG, "添加了: $packageName 包名等待安装更新成功")
|
||||
|
||||
@ -44,44 +54,58 @@ object PackageChangeHelper : DefaultLifecycleObserver {
|
||||
pendingGhId = ghId.toString()
|
||||
}
|
||||
|
||||
pendingPackagePair = Triple(packageName, UPDATE_PENDING, installData.version)
|
||||
pendingHUDShowed = false
|
||||
pendingPackageTriple = Triple(packageName, UPDATE_PENDING, installData.version)
|
||||
}
|
||||
}
|
||||
|
||||
fun isInstallPendingPackage(packageName: String): Boolean {
|
||||
return pendingPackageTriple?.first == packageName
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加一个等待中,待确定是否已成功卸载的应用
|
||||
*/
|
||||
fun addUninstallPendingPackage(packageName: String) {
|
||||
Utils.log(TAG, "添加了: $packageName 包名等待卸载成功")
|
||||
pendingPackagePair = Triple(packageName, UNINSTALL_PENDING, "")
|
||||
pendingPackageTriple = Triple(packageName, UNINSTALL_PENDING, "")
|
||||
}
|
||||
|
||||
override fun onResume(owner: LifecycleOwner) {
|
||||
super.onResume(owner)
|
||||
|
||||
if (pendingPackagePair != null) {
|
||||
val packageName = pendingPackagePair?.first ?: return
|
||||
val isInstallPending = pendingPackagePair?.second == INSTALL_PENDING
|
||||
val isUninstallPending = pendingPackagePair?.second == UNINSTALL_PENDING
|
||||
val isUpdatePending = pendingPackagePair?.second == UPDATE_PENDING
|
||||
if (pendingPackageTriple != null) {
|
||||
val packageName = pendingPackageTriple?.first ?: return
|
||||
val isInstallPending = pendingPackageTriple?.second == INSTALL_PENDING
|
||||
val isUninstallPending = pendingPackageTriple?.second == UNINSTALL_PENDING
|
||||
val isUpdatePending = pendingPackageTriple?.second == UPDATE_PENDING
|
||||
|
||||
val pendingVersion = pendingPackagePair?.third ?: ""
|
||||
val pendingVersion = pendingPackageTriple?.third ?: ""
|
||||
|
||||
val installedVersionName = PackageUtils.getVersionNameByPackageName(packageName)
|
||||
val isInstalled = installedVersionName != null
|
||||
|
||||
if (isInstallPending && isInstalled) {
|
||||
pendingPackagePair = null
|
||||
pendingGhId = null
|
||||
if (isInstallPending) {
|
||||
if (isInstalled) {
|
||||
pendingPackageTriple = null
|
||||
pendingGhId = null
|
||||
|
||||
PackageRepository.addInstalledGame(packageName)
|
||||
PackageRepository.addInstalledGame(PackageRepository.packageFilterManager, packageName)
|
||||
|
||||
// 添加到额外的包名白名单,下次启动同时查询此包的安装情况
|
||||
PackageHelper.updateAdditionalWhiteListPackageName(packageName = packageName, isAdd = true)
|
||||
// 添加到额外的包名白名单,下次启动同时查询此包的安装情况
|
||||
PackageHelper.updateAdditionalWhiteListPackageName(packageName = packageName, isAdd = true)
|
||||
|
||||
performInstallSuccessAction(packageName)
|
||||
performInstallSuccessAction(packageName)
|
||||
} else {
|
||||
// 任务不存在了,将等待更新安装结果的 triple 置为 null
|
||||
if (DownloadManager.getInstance().getDownloadEntitySnapshotByPackageName(packageName) == null) {
|
||||
pendingPackageTriple = null
|
||||
} else {
|
||||
showHUDIfNeeded(packageName)
|
||||
}
|
||||
}
|
||||
} else if (isUninstallPending && !isInstalled) {
|
||||
pendingPackagePair = null
|
||||
pendingPackageTriple = null
|
||||
pendingGhId = null
|
||||
|
||||
// 从额外的包名白名单移除,下次启动时不再查询此包的安装情况
|
||||
@ -95,12 +119,19 @@ object PackageChangeHelper : DefaultLifecycleObserver {
|
||||
!pendingGhId.isNullOrEmpty() && pendingGhId != PackageUtils.getGhId(packageName).toString()
|
||||
}
|
||||
|
||||
pendingPackagePair = null
|
||||
pendingPackageTriple = null
|
||||
pendingGhId = null
|
||||
|
||||
if (isUpdateValid) {
|
||||
performUninstallSuccessAction(packageName)
|
||||
performInstallSuccessAction(packageName)
|
||||
} else {
|
||||
// 任务不存在了,将等待更新安装结果的 triple 置为 null
|
||||
if (DownloadManager.getInstance().getDownloadEntitySnapshotByPackageName(packageName) == null) {
|
||||
pendingPackageTriple = null
|
||||
} else {
|
||||
showHUDIfNeeded(packageName)
|
||||
}
|
||||
}
|
||||
|
||||
// 添加到额外的包名白名单,下次启动同时查询此包的安装情况
|
||||
@ -109,6 +140,27 @@ object PackageChangeHelper : DefaultLifecycleObserver {
|
||||
}
|
||||
}
|
||||
|
||||
private fun showHUDIfNeeded(packageName: String) {
|
||||
if (pendingHUDShowed) return
|
||||
|
||||
val downloadEntity = DownloadManager.getInstance().getDownloadEntitySnapshotByPackageName(packageName) ?: return
|
||||
val activity = CurrentActivityHolder.getCurrentActivity() ?: return
|
||||
if (activity is DownloadManagerActivity) return
|
||||
|
||||
pendingHUDShowed = true
|
||||
HeadUpDisplayHelper.showHUD(activity,
|
||||
downloadEntity.icon ?: "",
|
||||
activity.getString(R.string.hud_has_pending_install_game),
|
||||
activity.getString(R.string.hud_head_to_download_manager),
|
||||
showingCallback = {
|
||||
HeadUpDisplayLogHelper.trackInstallationShow(downloadEntity, "游戏下载")
|
||||
},
|
||||
clickedCallback = {
|
||||
DirectUtils.directToDownloadManager(activity, "HUD")
|
||||
HeadUpDisplayLogHelper.trackInstallationClick(downloadEntity, "游戏下载")
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 对外暴露的方法,用于添加一个安装成功的应用
|
||||
* @param packageName 包名
|
||||
@ -134,9 +186,11 @@ object PackageChangeHelper : DefaultLifecycleObserver {
|
||||
* @param cachedGameEntity 缓存的 GameEntity,用于快速更新状态
|
||||
* @param withLog 是否需要记录日志
|
||||
*/
|
||||
private fun performInstallSuccessAction(packageName: String,
|
||||
cachedGameEntity: GameEntity? = null,
|
||||
withLog: Boolean = true) {
|
||||
private fun performInstallSuccessAction(
|
||||
packageName: String,
|
||||
cachedGameEntity: GameEntity? = null,
|
||||
withLog: Boolean = true
|
||||
) {
|
||||
Utils.log(TAG, "安装了: $packageName 包名的程序")
|
||||
val downloadEntity = DownloadManager.getInstance().getDownloadEntitySnapshotByPackageName(packageName)
|
||||
val gameId = if (downloadEntity != null && downloadEntity.gameId != null) downloadEntity.gameId else ""
|
||||
|
||||
@ -6,6 +6,7 @@ import android.content.pm.PackageInfo
|
||||
import android.content.pm.PackageManager
|
||||
import android.content.pm.PermissionInfo
|
||||
import android.os.Build
|
||||
import android.os.Process
|
||||
import android.provider.Settings
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
import androidx.lifecycle.LiveData
|
||||
@ -75,25 +76,33 @@ object PackageHelper {
|
||||
|
||||
private var uploadUIDGapLog = true
|
||||
|
||||
// 光环运行的环境是否为默认的 UID (0)
|
||||
private val isRunningOnDefaultUid by lazy { Process.myUid() / 100000 == 0 }
|
||||
|
||||
// 评论黑名单包名列表,避免用户安装了 Xposed Installer 这样的工具,也能在包含该安装包的游戏详情页评论
|
||||
private var _commentPackageNameBlackList = arrayListOf<String>()
|
||||
val commentPackageNameBlackList: ArrayList<String> = _commentPackageNameBlackList
|
||||
val commentPackageNameBlackList: ArrayList<String>
|
||||
get() = _commentPackageNameBlackList
|
||||
|
||||
// 关闭下载的包列表
|
||||
private var _downloadPackageNameBlackList = arrayListOf<String>()
|
||||
val downloadPackageNameBlackList: ArrayList<String> = _downloadPackageNameBlackList
|
||||
val downloadPackageNameBlackList: ArrayList<String>
|
||||
get() = _downloadPackageNameBlackList
|
||||
|
||||
// 本地已安装的包去掉关闭下载的包后的列表
|
||||
private var _validLocalPackageNameSet = hashSetOf<String>()
|
||||
val validLocalPackageNameSet: HashSet<String> = _validLocalPackageNameSet
|
||||
val validLocalPackageNameSet: HashSet<String>
|
||||
get() = _validLocalPackageNameSet
|
||||
|
||||
// 游戏包名匹配列表
|
||||
private var _relatedPackageList = arrayListOf<SettingsEntity.GameWithPackages>()
|
||||
val relatedPackageList: ArrayList<SettingsEntity.GameWithPackages> = _relatedPackageList
|
||||
val relatedPackageList: ArrayList<SettingsEntity.GameWithPackages>
|
||||
get() = _relatedPackageList
|
||||
|
||||
// 接口控制的已安装应用列表获取开关状态 (UI 显示)
|
||||
private var _installedPackageApiSwitchStatusLiveData = MutableLiveData<Boolean>()
|
||||
val installedPackageApiSwitchStatusLiveData: LiveData<Boolean> = _installedPackageApiSwitchStatusLiveData
|
||||
val installedPackageApiSwitchStatusLiveData: LiveData<Boolean>
|
||||
get() = _installedPackageApiSwitchStatusLiveData
|
||||
|
||||
// 本地已安装包的列表
|
||||
var localPackageNameSet = hashSetOf<String>()
|
||||
@ -117,12 +126,16 @@ object PackageHelper {
|
||||
val isSupportGetInstalledAppsPermission = isSupportGetInstalledAppsPermission(context)
|
||||
|
||||
if (!isSupportGetInstalledAppsPermission) {
|
||||
// 设备不支持动态管理获取已安装应用列表,忽略接口控制,使用另类方式获取已安装应用列表
|
||||
updateUseAlternativeWayToGetInstalledPackages()
|
||||
if (isRunningOnDefaultUid) {
|
||||
// 设备不支持动态管理获取已安装应用列表,忽略接口控制,使用另类方式获取已安装应用列表
|
||||
updateUseAlternativeWayToGetInstalledPackages()
|
||||
}
|
||||
onGetInstalledPackagesAgreed()
|
||||
} else if (!PermissionHelper.isGetInstalledListPermissionDisabled(context)) {
|
||||
// 设备支持动态管理获取已安装应用列表但已经授权,忽略接口控制,使用另类方式获取已安装应用列表
|
||||
updateUseAlternativeWayToGetInstalledPackages()
|
||||
if (isRunningOnDefaultUid) {
|
||||
// 设备支持动态管理获取已安装应用列表但已经授权,忽略接口控制,使用另类方式获取已安装应用列表
|
||||
updateUseAlternativeWayToGetInstalledPackages()
|
||||
}
|
||||
onGetInstalledPackagesAgreed()
|
||||
}
|
||||
|
||||
@ -258,8 +271,10 @@ object PackageHelper {
|
||||
|
||||
isGetInstalledPackagesAgreedRequired = DISABLED
|
||||
|
||||
// 启用另类获取已安装应用列表的 API
|
||||
updateUseAlternativeWayToGetInstalledPackages()
|
||||
if (isRunningOnDefaultUid) {
|
||||
// 启用另类获取已安装应用列表的 API
|
||||
updateUseAlternativeWayToGetInstalledPackages()
|
||||
}
|
||||
|
||||
onGetInstalledPackagesAgreed()
|
||||
}
|
||||
@ -531,6 +546,7 @@ object PackageHelper {
|
||||
Utils.log(TAG, "addInstalledButMissingPackages 需要请求接口获取的包数量为 ${installedPackageNameSet.size}")
|
||||
|
||||
PackageRepository.addInstalledGames(
|
||||
packageFilterManager = PackageRepository.packageFilterManager,
|
||||
pkgNameList = ArrayList(installedPackageNameSet),
|
||||
updateInstallStatus = true
|
||||
)
|
||||
|
||||
@ -22,12 +22,15 @@ import com.gh.gamecenter.install.InstallService
|
||||
import com.gh.vspace.VHelper
|
||||
import com.halo.assistant.HaloApp
|
||||
import com.lightgame.download.DownloadEntity
|
||||
import com.lightgame.utils.AppManager
|
||||
import com.lightgame.utils.Utils
|
||||
import java.io.File
|
||||
|
||||
// TODO 将弹窗改成以责任链模式来处理
|
||||
object PackageInstaller {
|
||||
|
||||
private val listeners = mutableListOf<OnInstallListener>()
|
||||
|
||||
/**
|
||||
* 为了兼容java代码
|
||||
*/
|
||||
@ -58,7 +61,7 @@ object PackageInstaller {
|
||||
val isDownloadAsVGame = downloadEntity.getMetaExtra(Constants.EXTRA_DOWNLOAD_TYPE) == Constants.VGAME
|
||||
|| downloadEntity.getMetaExtra(Constants.EXTRA_DOWNLOAD_TYPE) == Constants.DUAL_DOWNLOAD_VGAME
|
||||
|
||||
val currentActivity = CurrentActivityHolder.getCurrentActivity() ?: return
|
||||
val currentActivity = AppManager.getInstance().currentActivity() ?: return
|
||||
|
||||
if (!ignoreAsVGame && isDownloadAsVGame) {
|
||||
VHelper.install(currentActivity, downloadEntity)
|
||||
@ -126,6 +129,7 @@ object PackageInstaller {
|
||||
installWithPureModeHandled(
|
||||
context,
|
||||
pkgPath,
|
||||
downloadEntity?.packageName,
|
||||
downloadEntity?.gameId ?: "unknown",
|
||||
downloadEntity?.name ?: "unknown",
|
||||
downloadEntity?.categoryChinese ?: "unknown"
|
||||
@ -165,19 +169,20 @@ object PackageInstaller {
|
||||
private fun installWithPureModeHandled(
|
||||
context: Context,
|
||||
pkgPath: String,
|
||||
pkgName: String?,
|
||||
gameId: String,
|
||||
gameName: String,
|
||||
gameType: String,
|
||||
) {
|
||||
PureModeHelper.handlePureModeIfNeeded(context, gameId, gameName, gameType) {
|
||||
install(context, pkgPath)
|
||||
install(context, pkgPath, pkgName)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 最终执行安装的方法
|
||||
*/
|
||||
private fun install(context: Context, pkgPath: String) {
|
||||
private fun install(context: Context, pkgPath: String, pkgName: String?) {
|
||||
HaloApp.put(Constants.LAST_INSTALL_GAME, pkgPath)
|
||||
|
||||
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.TIRAMISU && Build.MANUFACTURER.lowercase().contains("xiaomi")) {
|
||||
@ -188,10 +193,13 @@ object PackageInstaller {
|
||||
|
||||
val installIntent = getInstallIntent(context, pkgPath)
|
||||
context.startActivity(installIntent)
|
||||
|
||||
dispatchOnInstallListener(pkgPath, pkgName)
|
||||
}
|
||||
|
||||
fun installMultiple(
|
||||
context: Context,
|
||||
pkgName: String,
|
||||
pkgPath: String,
|
||||
sessionId: Int = -1
|
||||
) {
|
||||
@ -214,6 +222,24 @@ object PackageInstaller {
|
||||
val pendingIntent = PendingIntent.getActivity(context, sessionId, intent, flags)
|
||||
// 提交数据流并执行安装
|
||||
session.commit(pendingIntent.intentSender)
|
||||
|
||||
dispatchOnInstallListener(pkgName, pkgPath)
|
||||
}
|
||||
|
||||
fun registerOnInstallListener(listener: OnInstallListener) {
|
||||
if (!listeners.contains(listener)) {
|
||||
listeners.add(listener)
|
||||
}
|
||||
}
|
||||
|
||||
fun unregisterOnInstallListener(listener: OnInstallListener) {
|
||||
listeners.remove(listener)
|
||||
}
|
||||
|
||||
private fun dispatchOnInstallListener(pkgPath: String, pkgName: String?) {
|
||||
for (listener in listeners) {
|
||||
listener.onInstalling(pkgName, pkgPath)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -305,4 +331,8 @@ object PackageInstaller {
|
||||
return MD5Utils.getContentMD5(gameName + "_" + System.currentTimeMillis())
|
||||
}
|
||||
|
||||
interface OnInstallListener {
|
||||
fun onInstalling(packageName: String?, packagePath: String)
|
||||
}
|
||||
|
||||
}
|
||||
@ -14,6 +14,7 @@ import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.PowerManager;
|
||||
import android.text.TextUtils;
|
||||
import android.util.AndroidException;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
@ -222,8 +223,19 @@ public class PackageUtils {
|
||||
if (metaDate != null) {
|
||||
return metaDate.get(name);
|
||||
}
|
||||
} catch (NameNotFoundException e) {
|
||||
// e.printStackTrace();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
|
||||
if (e instanceof AndroidException) {
|
||||
// 有些设备会出现 DeadSystemException
|
||||
SentryHelper.INSTANCE.onEvent(
|
||||
"GET_META_DATA_ERROR",
|
||||
"packageName",
|
||||
packageName,
|
||||
"exception_digest",
|
||||
e.getLocalizedMessage()
|
||||
);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@ -627,8 +639,19 @@ public class PackageUtils {
|
||||
try {
|
||||
return HaloApp.getInstance().getApplication().getPackageManager().getPackageInfo(packageName,
|
||||
PackageManager.COMPONENT_ENABLED_STATE_DEFAULT).versionName;
|
||||
} catch (NameNotFoundException e) {
|
||||
// do nothing
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
|
||||
if (e instanceof AndroidException) {
|
||||
// 有些设备会出现 DeadSystemException
|
||||
SentryHelper.INSTANCE.onEvent(
|
||||
"GET_VERSION_NAME_ERROR",
|
||||
"packageName",
|
||||
packageName,
|
||||
"exception_digest",
|
||||
e.getLocalizedMessage()
|
||||
);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@ -640,8 +663,18 @@ public class PackageUtils {
|
||||
try {
|
||||
return HaloApp.getInstance().getApplication().getPackageManager().getPackageInfo(packageName,
|
||||
PackageManager.COMPONENT_ENABLED_STATE_DEFAULT).versionCode;
|
||||
} catch (NameNotFoundException e) {
|
||||
// do nothing
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
if (e instanceof AndroidException) {
|
||||
// 有些设备会出现 DeadSystemException
|
||||
SentryHelper.INSTANCE.onEvent(
|
||||
"GET_VERSION_CODE_ERROR",
|
||||
"packageName",
|
||||
packageName,
|
||||
"exception_digest",
|
||||
e.getLocalizedMessage()
|
||||
);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -654,8 +687,18 @@ public class PackageUtils {
|
||||
try {
|
||||
PackageManager packageManager = context.getApplicationContext().getPackageManager();
|
||||
return packageManager.getApplicationIcon(packageName);
|
||||
} catch (NameNotFoundException e) {
|
||||
// do nothing
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
if (e instanceof AndroidException) {
|
||||
// 有些设备会出现 DeadSystemException
|
||||
SentryHelper.INSTANCE.onEvent(
|
||||
"GET_ICON_ERROR",
|
||||
"packageName",
|
||||
packageName,
|
||||
"exception_digest",
|
||||
e.getLocalizedMessage()
|
||||
);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@ -706,8 +749,19 @@ public class PackageUtils {
|
||||
jsonObject.put("version", packageInfo.versionName);
|
||||
}
|
||||
return jsonObject;
|
||||
} catch (JSONException | NameNotFoundException e) {
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
if (e instanceof AndroidException) {
|
||||
// 有些设备会出现 DeadSystemException
|
||||
SentryHelper.INSTANCE.onEvent(
|
||||
"GET_APP_BASIC_INFO_BY_PACKAGE_NAME",
|
||||
"packageName",
|
||||
packageName,
|
||||
"exception_digest",
|
||||
e.getLocalizedMessage()
|
||||
);
|
||||
}
|
||||
|
||||
return jsonObject;
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,12 +3,12 @@ package com.gh.common.util
|
||||
import android.annotation.SuppressLint
|
||||
import com.gh.gamecenter.common.entity.SignatureEntity
|
||||
import com.gh.gamecenter.common.retrofit.BiResponse
|
||||
import com.gh.gamecenter.common.utils.singleToMain
|
||||
import com.gh.gamecenter.common.utils.toJson
|
||||
import com.gh.gamecenter.common.utils.toObject
|
||||
import com.gh.gamecenter.core.utils.MD5Utils
|
||||
import com.gh.gamecenter.core.utils.SPUtils
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
|
||||
/**
|
||||
* 存储光环网游使用的签名
|
||||
@ -24,7 +24,7 @@ object SignatureRepository {
|
||||
RetrofitManager.getInstance()
|
||||
.newApi
|
||||
.ghSignature
|
||||
.compose(singleToMain())
|
||||
.subscribeOn(Schedulers.io())
|
||||
.subscribe(object : BiResponse<ArrayList<SignatureEntity>>() {
|
||||
override fun onSuccess(data: ArrayList<SignatureEntity>) {
|
||||
signDigestList = ArrayList()
|
||||
|
||||
@ -190,6 +190,8 @@ object ViewPagerFragmentHelper {
|
||||
// 新游开测
|
||||
TYPE_COLUMN_TEST -> {
|
||||
className = GameServerTestV2Fragment::class.java.name
|
||||
bundle.putString(EntranceConsts.KEY_ID, entity.link)
|
||||
bundle.putString(EntranceConsts.KEY_NAME, entity.text)
|
||||
}
|
||||
// 分类2.0
|
||||
TYPE_CATEGORY_V2 -> {
|
||||
|
||||
@ -1,331 +0,0 @@
|
||||
package com.gh.common.view
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.Color
|
||||
import android.util.AttributeSet
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.ImageView
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.PopupWindow
|
||||
import android.widget.TextView
|
||||
import androidx.annotation.ColorInt
|
||||
import androidx.core.content.ContextCompat
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.utils.setDrawableEnd
|
||||
import com.gh.gamecenter.common.utils.toColor
|
||||
import com.gh.gamecenter.common.utils.visibleIf
|
||||
import com.gh.gamecenter.entity.CatalogEntity
|
||||
import com.gh.gamecenter.entity.SubjectSettingEntity
|
||||
import com.google.android.flexbox.FlexboxLayout
|
||||
|
||||
class CatalogFilterView @JvmOverloads constructor(
|
||||
context: Context,
|
||||
attrs: AttributeSet? = null,
|
||||
defStyleAttr: Int = 0
|
||||
) : LinearLayout(context, attrs, defStyleAttr) {
|
||||
|
||||
private var mTypeTv: TextView
|
||||
private var mCatalogTv: TextView
|
||||
private var mSizeTv: TextView
|
||||
private var mTypeContainer: View
|
||||
private var mCatalogContainer: View
|
||||
private var mSizeContainer: View
|
||||
|
||||
private var mTypeFilterArray = ArrayList<SortType>()
|
||||
private var mCatalogFilterArray = ArrayList<CatalogEntity.SubCatalogEntity>()
|
||||
private var sizeFilterArray: ArrayList<SubjectSettingEntity.Size>? = null
|
||||
|
||||
private var mOnCatalogFilterSetupListener: OnCatalogFilterSetupListener? = null
|
||||
|
||||
private var mTypePopupWindow: PopupWindow? = null
|
||||
private var mCatalogPopupWindow: PopupWindow? = null
|
||||
private var mSizePopupWindow: PopupWindow? = null
|
||||
|
||||
init {
|
||||
View.inflate(context, R.layout.layout_catalog_filter, this)
|
||||
|
||||
mTypeTv = findViewById(R.id.type_tv)
|
||||
mCatalogTv = findViewById(R.id.catalog_tv)
|
||||
mSizeTv = findViewById(R.id.size_tv)
|
||||
mTypeContainer = findViewById(R.id.container_type)
|
||||
mCatalogContainer = findViewById(R.id.container_catalog)
|
||||
mSizeContainer = findViewById(R.id.container_size)
|
||||
|
||||
mTypeContainer.setOnClickListener {
|
||||
showSelectTypePopupWindow(this, mTypeTv, mTypeTv.text.toString())
|
||||
}
|
||||
|
||||
mCatalogContainer.setOnClickListener {
|
||||
showSelectCatalogPopupWindow(this, mCatalogTv, mCatalogTv.text.toString())
|
||||
}
|
||||
|
||||
mSizeContainer.setOnClickListener {
|
||||
showSelectSizePopupWindow(this, mSizeTv, mSizeTv.text.toString())
|
||||
}
|
||||
}
|
||||
|
||||
fun setTypeList(switch: CatalogEntity.CatalogSwitch) {
|
||||
switch.run {
|
||||
if ("on" == hotSort) mTypeFilterArray.add(SortType.RECOMMENDED)
|
||||
if ("on" == newSort) mTypeFilterArray.add(SortType.NEWEST)
|
||||
if ("on" == starSort) mTypeFilterArray.add(SortType.RATING)
|
||||
}
|
||||
if (mTypeFilterArray.isNotEmpty()) mTypeTv.text = mTypeFilterArray[0].value
|
||||
}
|
||||
|
||||
fun setCatalogList(subCatalogList: List<CatalogEntity.SubCatalogEntity>, initCatalogName: String) {
|
||||
mCatalogFilterArray = ArrayList(subCatalogList)
|
||||
mCatalogTv.text = initCatalogName
|
||||
}
|
||||
|
||||
fun setOnConfigSetupListener(onCatalogFilterSetupListener: OnCatalogFilterSetupListener) {
|
||||
mOnCatalogFilterSetupListener = onCatalogFilterSetupListener
|
||||
}
|
||||
|
||||
private fun toggleHighlightedTextView(targetTextView: TextView, highlightIt: Boolean) {
|
||||
if (highlightIt) {
|
||||
targetTextView.background = ContextCompat.getDrawable(targetTextView.context, R.drawable.bg_tag_text)
|
||||
targetTextView.setTextColor(Color.WHITE)
|
||||
} else {
|
||||
targetTextView.background = null
|
||||
targetTextView.setTextColor(R.color.text_757575.toColor(context))
|
||||
}
|
||||
}
|
||||
|
||||
private fun showSelectTypePopupWindow(containerView: View, typeTv: TextView, typeText: String) {
|
||||
typeTv.setTextColor(R.color.text_theme.toColor(context))
|
||||
typeTv.setDrawableEnd(R.drawable.ic_filter_arrow_up)
|
||||
|
||||
val inflater = LayoutInflater.from(typeTv.context)
|
||||
val layout = inflater.inflate(R.layout.layout_filter_size, null)
|
||||
val popupWindow = PopupWindow(
|
||||
layout,
|
||||
LayoutParams.MATCH_PARENT,
|
||||
LayoutParams.WRAP_CONTENT
|
||||
).apply { mTypePopupWindow = this }
|
||||
|
||||
val flexboxLayout = layout.findViewById<FlexboxLayout>(R.id.flexbox)
|
||||
val backgroundView = layout.findViewById<View>(R.id.background)
|
||||
|
||||
backgroundView.setOnClickListener {
|
||||
popupWindow.dismiss()
|
||||
}
|
||||
|
||||
for (type in mTypeFilterArray) {
|
||||
val item = inflater.inflate(R.layout.item_filter_size, flexboxLayout, false)
|
||||
|
||||
// 单列 3 个,强行设置宽度为屏幕的 1/3
|
||||
val width = typeTv.context.resources.displayMetrics.widthPixels / 3
|
||||
val height = item.layoutParams.height
|
||||
|
||||
item.layoutParams = ViewGroup.LayoutParams(width, height)
|
||||
flexboxLayout.addView(item)
|
||||
|
||||
val tv = item.findViewById<TextView>(R.id.size_tv)
|
||||
tv.text = type.value
|
||||
|
||||
toggleHighlightedTextView(tv, typeText == type.value)
|
||||
|
||||
tv.tag = type.value
|
||||
|
||||
item.setOnClickListener {
|
||||
toggleHighlightedTextView(tv, true)
|
||||
popupWindow.dismiss()
|
||||
typeTv.text = type.value
|
||||
|
||||
mOnCatalogFilterSetupListener?.onSetupSortType(type)
|
||||
}
|
||||
}
|
||||
|
||||
popupWindow.setOnDismissListener {
|
||||
typeTv.setTextColor(R.color.text_757575.toColor(context))
|
||||
typeTv.setDrawableEnd(R.drawable.ic_filter_arrow_down)
|
||||
mTypePopupWindow = null
|
||||
}
|
||||
|
||||
popupWindow.isTouchable = true
|
||||
popupWindow.isFocusable = true
|
||||
popupWindow.animationStyle = 0
|
||||
popupWindow.showAsDropDown(containerView, 0, 0)
|
||||
}
|
||||
|
||||
private fun showSelectCatalogPopupWindow(containerView: View, catalogTv: TextView, catalogText: String) {
|
||||
catalogTv.setTextColor(R.color.text_theme.toColor(context))
|
||||
catalogTv.setDrawableEnd(R.drawable.ic_filter_arrow_up)
|
||||
|
||||
val inflater = LayoutInflater.from(catalogTv.context)
|
||||
val layout = inflater.inflate(R.layout.layout_filter_size, null)
|
||||
val popupWindow = PopupWindow(
|
||||
layout,
|
||||
LayoutParams.MATCH_PARENT,
|
||||
LayoutParams.WRAP_CONTENT
|
||||
).apply { mCatalogPopupWindow = this }
|
||||
|
||||
val flexboxLayout = layout.findViewById<FlexboxLayout>(R.id.flexbox)
|
||||
val backgroundView = layout.findViewById<View>(R.id.background)
|
||||
|
||||
backgroundView.setOnClickListener {
|
||||
popupWindow.dismiss()
|
||||
}
|
||||
|
||||
for (entity in mCatalogFilterArray) {
|
||||
val item = inflater.inflate(R.layout.item_filter_size, flexboxLayout, false)
|
||||
|
||||
// 单列 3 个,强行设置宽度为屏幕的 1/3
|
||||
val width = catalogTv.context.resources.displayMetrics.widthPixels / 3
|
||||
val height = item.layoutParams.height
|
||||
|
||||
item.layoutParams = ViewGroup.LayoutParams(width, height)
|
||||
flexboxLayout.addView(item)
|
||||
|
||||
val tv = item.findViewById<TextView>(R.id.size_tv)
|
||||
val iv = item.findViewById<ImageView>(R.id.recommend_iv)
|
||||
tv.text = entity.name
|
||||
iv.visibleIf(entity.recommended)
|
||||
|
||||
toggleHighlightedTextView(tv, catalogText == entity.name)
|
||||
|
||||
tv.tag = entity.name
|
||||
|
||||
item.setOnClickListener {
|
||||
toggleHighlightedTextView(tv, true)
|
||||
popupWindow.dismiss()
|
||||
catalogTv.text = entity.name
|
||||
|
||||
mOnCatalogFilterSetupListener?.onSetupSortCatalog(entity)
|
||||
}
|
||||
}
|
||||
|
||||
popupWindow.setOnDismissListener {
|
||||
catalogTv.setTextColor(R.color.text_757575.toColor(context))
|
||||
catalogTv.setDrawableEnd(R.drawable.ic_filter_arrow_down)
|
||||
mCatalogPopupWindow = null
|
||||
}
|
||||
|
||||
popupWindow.isTouchable = true
|
||||
popupWindow.isFocusable = true
|
||||
popupWindow.animationStyle = 0
|
||||
popupWindow.showAsDropDown(containerView, 0, 0)
|
||||
}
|
||||
|
||||
private fun showSelectSizePopupWindow(containerView: View, sizeTv: TextView, sizeText: String) {
|
||||
sizeTv.setTextColor(R.color.text_theme.toColor(context))
|
||||
sizeTv.setDrawableEnd(R.drawable.ic_filter_arrow_up)
|
||||
|
||||
val inflater = LayoutInflater.from(sizeTv.context)
|
||||
val layout = inflater.inflate(R.layout.layout_filter_size, null)
|
||||
val popupWindow = PopupWindow(
|
||||
layout,
|
||||
LayoutParams.MATCH_PARENT,
|
||||
LayoutParams.WRAP_CONTENT
|
||||
).apply { mSizePopupWindow = this }
|
||||
|
||||
val flexboxLayout = layout.findViewById<FlexboxLayout>(R.id.flexbox)
|
||||
val backgroundView = layout.findViewById<View>(R.id.background)
|
||||
|
||||
sizeFilterArray = if (sizeFilterArray == null) {
|
||||
getDefaultSizeFilterArray()
|
||||
} else {
|
||||
sizeFilterArray?.apply {
|
||||
if (firstOrNull()?.text != "全部大小") {
|
||||
add(0, SubjectSettingEntity.Size(min = -1, max = -1, text = "全部大小"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
backgroundView.setOnClickListener {
|
||||
popupWindow.dismiss()
|
||||
}
|
||||
|
||||
for (size in sizeFilterArray!!) {
|
||||
val item = inflater.inflate(R.layout.item_filter_size, flexboxLayout, false)
|
||||
|
||||
// 单列 3 个,强行设置宽度为屏幕的 1/3
|
||||
val width = sizeTv.context.resources.displayMetrics.widthPixels / 3
|
||||
val height = item.layoutParams.height
|
||||
|
||||
item.layoutParams = ViewGroup.LayoutParams(width, height)
|
||||
flexboxLayout.addView(item)
|
||||
|
||||
val tv = item.findViewById<TextView>(R.id.size_tv)
|
||||
tv.text = size.text
|
||||
|
||||
toggleHighlightedTextView(tv, sizeText == size.text)
|
||||
|
||||
tv.tag = size.text
|
||||
|
||||
item.setOnClickListener {
|
||||
toggleHighlightedTextView(tv, true)
|
||||
popupWindow.dismiss()
|
||||
sizeTv.text = size.text
|
||||
|
||||
mOnCatalogFilterSetupListener?.onSetupSortSize(size)
|
||||
}
|
||||
}
|
||||
|
||||
popupWindow.setOnDismissListener {
|
||||
sizeTv.setTextColor(R.color.text_757575.toColor(context))
|
||||
sizeTv.setDrawableEnd(R.drawable.ic_filter_arrow_down)
|
||||
mSizePopupWindow = null
|
||||
}
|
||||
|
||||
popupWindow.isTouchable = true
|
||||
popupWindow.isFocusable = true
|
||||
popupWindow.animationStyle = 0
|
||||
popupWindow.showAsDropDown(containerView, 0, 0)
|
||||
}
|
||||
|
||||
private fun getDefaultSizeFilterArray(): ArrayList<SubjectSettingEntity.Size> {
|
||||
return arrayListOf<SubjectSettingEntity.Size>().apply {
|
||||
add(SubjectSettingEntity.Size(min = -1, max = -1, text = "全部大小"))
|
||||
add(SubjectSettingEntity.Size(min = -1, max = 100, text = "100M以下"))
|
||||
add(SubjectSettingEntity.Size(min = 100, max = 300, text = "100-300M"))
|
||||
add(SubjectSettingEntity.Size(min = 300, max = 500, text = "300-500M"))
|
||||
add(SubjectSettingEntity.Size(min = 500, max = 1000, text = "500M-1G"))
|
||||
add(SubjectSettingEntity.Size(min = 1000, max = -1, text = "1G以上"))
|
||||
}
|
||||
}
|
||||
|
||||
fun setRootBackgroundColor(@ColorInt color: Int) {
|
||||
findViewById<View>(R.id.config_controller).setBackgroundColor(color)
|
||||
}
|
||||
|
||||
fun setItemTextColor(@ColorInt color: Int) {
|
||||
mTypeTv.setTextColor(color)
|
||||
mCatalogTv.setTextColor(color)
|
||||
mSizeTv.setTextColor(color)
|
||||
}
|
||||
|
||||
fun updatePopupWindow() {
|
||||
when {
|
||||
mTypePopupWindow != null && mTypePopupWindow!!.isShowing -> {
|
||||
mTypePopupWindow?.dismiss()
|
||||
showSelectTypePopupWindow(this, mTypeTv, mTypeTv.text.toString())
|
||||
}
|
||||
|
||||
mCatalogPopupWindow != null && mCatalogPopupWindow!!.isShowing -> {
|
||||
mCatalogPopupWindow?.dismiss()
|
||||
showSelectCatalogPopupWindow(this, mCatalogTv, mCatalogTv.text.toString())
|
||||
}
|
||||
|
||||
mSizePopupWindow != null && mSizePopupWindow!!.isShowing -> {
|
||||
mSizePopupWindow?.dismiss()
|
||||
showSelectSizePopupWindow(this, mSizeTv, mSizeTv.text.toString())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
interface OnCatalogFilterSetupListener {
|
||||
fun onSetupSortSize(sortSize: SubjectSettingEntity.Size)
|
||||
fun onSetupSortType(sortType: SortType)
|
||||
fun onSetupSortCatalog(sortCatalog: CatalogEntity.SubCatalogEntity)
|
||||
}
|
||||
|
||||
enum class SortType(val value: String) {
|
||||
RECOMMENDED("热门推荐"),
|
||||
NEWEST("最新上线"),
|
||||
RATING("最高评分")
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,18 @@
|
||||
package com.gh.common.view
|
||||
|
||||
import android.content.Context
|
||||
import android.util.AttributeSet
|
||||
import android.view.MotionEvent
|
||||
import android.widget.FrameLayout
|
||||
import androidx.constraintlayout.widget.ConstraintLayout
|
||||
|
||||
class InterceptTouchContainView @JvmOverloads constructor(
|
||||
context: Context,
|
||||
attrs: AttributeSet? = null,
|
||||
defStyleAttr: Int = 0,
|
||||
) : FrameLayout(context, attrs, defStyleAttr) {
|
||||
|
||||
override fun onInterceptTouchEvent(ev: MotionEvent?): Boolean {
|
||||
return true
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,65 @@
|
||||
package com.gh.common.view
|
||||
|
||||
import android.content.Context
|
||||
import android.os.Build
|
||||
import android.util.AttributeSet
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.TextView
|
||||
import androidx.core.view.children
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.utils.toColor
|
||||
import com.gh.gamecenter.common.utils.visibleIf
|
||||
|
||||
/**
|
||||
* 单游戏卡片标签样式专用
|
||||
* 根据宽度展示标签个数,最多展示三个标签
|
||||
*/
|
||||
class SingleCardTagContainerView @JvmOverloads constructor(
|
||||
context: Context,
|
||||
attrs: AttributeSet? = null,
|
||||
) : LinearLayout(context, attrs) {
|
||||
|
||||
private val childViews = arrayListOf<TextView>()
|
||||
|
||||
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
|
||||
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
|
||||
children.forEach {
|
||||
// 父容器不限制子View的宽度
|
||||
it.measure(MeasureSpec.UNSPECIFIED, heightMeasureSpec)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) {
|
||||
super.onLayout(changed, l, t, r, b)
|
||||
// 如果有显示不完整的标签,直接隐藏
|
||||
children.forEach {
|
||||
it.visibleIf(it.right <= width)
|
||||
}
|
||||
}
|
||||
|
||||
fun setData(tags: List<String>) {
|
||||
removeAllViews()
|
||||
tags.forEachIndexed { index, tag ->
|
||||
if (index < 3) {
|
||||
// 缓存子View 避免频繁创建新View
|
||||
val tvTag = childViews.getOrNull(index) ?: TextView(context).also { childViews.add(it) }
|
||||
if (index == 0) {
|
||||
tvTag.text = tag
|
||||
} else {
|
||||
tvTag.text = "$DELIMITER$tag"
|
||||
}
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
tvTag.setTextAppearance(R.style.TextCaption2)
|
||||
} else {
|
||||
tvTag.setTextAppearance(context, R.style.TextCaption2)
|
||||
}
|
||||
tvTag.setTextColor(R.color.text_tertiary.toColor(context))
|
||||
addView(tvTag)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val DELIMITER = "·"
|
||||
}
|
||||
}
|
||||
@ -1,64 +0,0 @@
|
||||
package com.gh.common.view
|
||||
|
||||
import android.content.Context
|
||||
import android.util.AttributeSet
|
||||
import android.view.View
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.TextView
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.category.CategoryListActivity
|
||||
import com.gh.gamecenter.entity.CategoryEntity
|
||||
|
||||
class SubCategoryView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0) :
|
||||
LinearLayout(context, attrs, defStyleAttr) {
|
||||
|
||||
var leftTv: TextView
|
||||
var centerTv: TextView
|
||||
var rightTv: TextView
|
||||
|
||||
var leftDivider: View
|
||||
var rightDivider: View
|
||||
|
||||
var primeCategory: CategoryEntity? = null
|
||||
var categoryTitle: String? = ""
|
||||
|
||||
init {
|
||||
View.inflate(context, R.layout.layout_sub_category, this)
|
||||
|
||||
leftTv = findViewById(R.id.tv_left_sub_category)
|
||||
centerTv = findViewById(R.id.tv_center_sub_category)
|
||||
rightTv = findViewById(R.id.tv_right_sub_category)
|
||||
|
||||
leftDivider = findViewById(R.id.divider_left)
|
||||
rightDivider = findViewById(R.id.divider_right)
|
||||
}
|
||||
|
||||
fun setLeftCategory(category: CategoryEntity) {
|
||||
setCategory(leftTv, category)
|
||||
}
|
||||
|
||||
fun setCenterCategory(category: CategoryEntity) {
|
||||
setCategory(centerTv, category)
|
||||
leftDivider.visibility = View.VISIBLE
|
||||
}
|
||||
|
||||
fun setRightCategory(category: CategoryEntity) {
|
||||
setCategory(rightTv, category)
|
||||
rightDivider.visibility = View.VISIBLE
|
||||
}
|
||||
|
||||
private fun setCategory(tv: TextView, category: CategoryEntity) {
|
||||
tv.text = category.name
|
||||
tv.setOnClickListener {
|
||||
tv.context.startActivity(
|
||||
CategoryListActivity.getIntent(
|
||||
tv.context,
|
||||
categoryTitle!!,
|
||||
primeCategory!!,
|
||||
category.name!!
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -207,7 +207,7 @@ object XapkDialogHelper {
|
||||
SuggestType.GAME,
|
||||
null,
|
||||
hint,
|
||||
SimpleGameEntity(downloadEntity.gameId, downloadEntity.name, downloadEntity.icon)
|
||||
SimpleGameEntity(downloadEntity.gameId, downloadEntity.name, downloadEntity.icon?: "")
|
||||
)
|
||||
NewFlatLogUtils.logXApkUnzipFailedDialogClick(
|
||||
"提交反馈",
|
||||
|
||||
@ -4,6 +4,7 @@ import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Build
|
||||
import android.os.Environment
|
||||
import android.provider.Settings
|
||||
import com.gh.common.constant.Config
|
||||
import com.gh.common.util.DirectUtils
|
||||
@ -46,8 +47,6 @@ import java.util.*
|
||||
@SuppressLint("StaticFieldLeak")
|
||||
object XapkInstaller : XApkUnZipCallback, XApkUnZipOutputFactory {
|
||||
|
||||
private const val XAPK_PACKAGE_PATH_TAG = "xapk_package_path"
|
||||
|
||||
const val XAPK_EXTENSION_NAME = "xapk"
|
||||
|
||||
// 通过解压过程存放于 DownloadEntity meta
|
||||
@ -57,12 +56,21 @@ object XapkInstaller : XApkUnZipCallback, XApkUnZipOutputFactory {
|
||||
const val XAPK_DATA_EXTENSION_NAME = "obb"
|
||||
const val PACKAGE_EXTENSION_NAME = "apk"
|
||||
|
||||
// 系统是否有 obb 访问漏洞
|
||||
val systemHasFlaw by lazy {
|
||||
val systemMatched = Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE
|
||||
val rootPath = Environment.getExternalStorageDirectory().path
|
||||
val fileListMatched = File(rootPath, "Android").list().contentEquals(File(rootPath, "\u200bAndroid").list())
|
||||
|
||||
systemMatched && fileListMatched
|
||||
}
|
||||
|
||||
private const val GUIDE_TYPE_MIUI_OPTIMIZATION = "miui_optimization"
|
||||
private const val MIUI_OPTIMIZATION_WARNING_DIALOG_ENTRANCE = "MIUI优化关闭提示弹窗"
|
||||
|
||||
private var mContext = HaloApp.getInstance().application.applicationContext
|
||||
|
||||
private val mXApkUnZipper = XApkUnZipper(this)
|
||||
private val mXApkUnZipper = XApkUnZipper(this, useFlawToUnzip = systemHasFlaw)
|
||||
.also {
|
||||
it.registerCallback(this)
|
||||
}
|
||||
@ -343,7 +351,7 @@ object XapkInstaller : XApkUnZipCallback, XApkUnZipOutputFactory {
|
||||
|
||||
mPendingSessionInfoMap[downloadEntity.path] = XapkPendingSessionInfo(downloadEntity.path, sessionId)
|
||||
AppExecutor.ioExecutor.execute {// 有可能卡顿造成anr
|
||||
PackageInstaller.installMultiple(applicationContext, downloadEntity.path, sessionId)
|
||||
PackageInstaller.installMultiple(applicationContext, downloadEntity.packageName, downloadEntity.path, sessionId)
|
||||
NDataChanger.notifyDataChanged(downloadEntity)
|
||||
}
|
||||
}
|
||||
|
||||
@ -356,9 +356,10 @@ public class DownloadManager implements DownloadStatusListener {
|
||||
ExtensionsKt.addMetaExtra(downloadEntity, Constants.EXTRA_DOWNLOAD_TYPE, Constants.VGAME);
|
||||
ExtensionsKt.addMetaExtra(downloadEntity, DownloadConfig.KEY_PROGRESS_CALLBACK_INTERVAL, "200");
|
||||
ExtensionsKt.addMetaExtra(downloadEntity, VHelper.KEY_REQUIRED_G_APPS, gameEntity.getGAppsSwitch());
|
||||
ExtensionsKt.addMetaExtra(downloadEntity, VHelper.KEY_BIT, apkEntity.getBit());
|
||||
}
|
||||
|
||||
ExtensionsKt.addMetaExtra(downloadEntity, Constants.KEY_BIT, apkEntity.getBit());
|
||||
|
||||
// 记录是否为双下载按钮模式
|
||||
if (isDualDownloadTypeEnabled) {
|
||||
if (asVGame) {
|
||||
@ -541,6 +542,7 @@ public class DownloadManager implements DownloadStatusListener {
|
||||
checkDownloadEntryRecordValidate(url);
|
||||
if (isDownloadCompleted(url)) {
|
||||
downloadEntity.setStatus(DownloadStatus.done);
|
||||
mDownloadDao.newOrUpdate(downloadEntity);
|
||||
NDataChanger.INSTANCE.notifyDataChanged(downloadEntity);
|
||||
} else if (!isTaskDownloading(url)) {
|
||||
DownloadEntity daoEntity = mDownloadDao.get(downloadEntity.getUrl());
|
||||
@ -994,19 +996,21 @@ public class DownloadManager implements DownloadStatusListener {
|
||||
* 3.检查是否显示下载通知栏
|
||||
*/
|
||||
public void initDownloadService() {
|
||||
final Set<String> urlSet = NDataChanger.INSTANCE.getDownloadingTaskUrlSet();
|
||||
for (DownloadEntity downloadEntity : getAllDownloadEntity()) {
|
||||
if (!urlSet.contains(downloadEntity.getUrl())
|
||||
&& (downloadEntity.getStatus().equals(DownloadStatus.downloading)
|
||||
|| downloadEntity.getStatus().equals(DownloadStatus.waiting))) {
|
||||
downloadEntity.setStatus(DownloadStatus.subscribe);
|
||||
mDownloadDao.newOrUpdate(downloadEntity);
|
||||
NDataChanger.INSTANCE.notifyDataChanged(downloadEntity);
|
||||
packageExecutor.execute(() -> {
|
||||
final Set<String> urlSet = NDataChanger.INSTANCE.getDownloadingTaskUrlSet();
|
||||
for (DownloadEntity downloadEntity : getAllDownloadEntity()) {
|
||||
if (!urlSet.contains(downloadEntity.getUrl())
|
||||
&& (downloadEntity.getStatus().equals(DownloadStatus.downloading)
|
||||
|| downloadEntity.getStatus().equals(DownloadStatus.waiting))) {
|
||||
downloadEntity.setStatus(DownloadStatus.subscribe);
|
||||
mDownloadDao.newOrUpdate(downloadEntity);
|
||||
NDataChanger.INSTANCE.notifyDataChanged(downloadEntity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
startDownloadService();
|
||||
checkAndRetryDownload();
|
||||
startDownloadService();
|
||||
checkAndRetryDownload(true);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1097,13 +1101,15 @@ public class DownloadManager implements DownloadStatusListener {
|
||||
/**
|
||||
* 检查并尝试重试下载
|
||||
*/
|
||||
public void checkAndRetryDownload() {
|
||||
public void checkAndRetryDownload(boolean includePausedTask) {
|
||||
if (!NetworkUtils.isWifiConnected(mContext)) return;
|
||||
|
||||
for (DownloadEntity downloadEntity : DownloadManager.getInstance().getAllDownloadEntityExcludeDoneTask()) {
|
||||
if (DownloadStatus.neterror.equals(downloadEntity.getStatus())
|
||||
|| DownloadStatus.timeout.equals(downloadEntity.getStatus())
|
||||
|| DownloadStatus.subscribe.equals(downloadEntity.getStatus())) {
|
||||
|| DownloadStatus.subscribe.equals(downloadEntity.getStatus())
|
||||
|| (includePausedTask && DownloadStatus.pause.equals(downloadEntity.getStatus()))
|
||||
) {
|
||||
DownloadManager.getInstance().put(downloadEntity.getUrl(), System.currentTimeMillis());
|
||||
Message msg = Message.obtain();
|
||||
msg.what = DownloadConfig.CONTINUE_DOWNLOAD_AUTO_TASK;
|
||||
|
||||
@ -59,8 +59,8 @@ class GameDetailActivity : DownloadToolbarActivity() {
|
||||
}
|
||||
|
||||
override fun getBusinessId(): Pair<String, String> {
|
||||
val fragment = targetFragment as GameDetailFragment
|
||||
return if (fragment.arguments != null) {
|
||||
val fragment = targetFragment as? GameDetailFragment?
|
||||
return if (fragment?.arguments != null) {
|
||||
Pair(fragment.requireArguments().getString(EntranceConsts.KEY_GAMEID) ?: "", "")
|
||||
} else {
|
||||
super.getBusinessId()
|
||||
|
||||
@ -847,6 +847,8 @@ class ImageViewerActivity : BaseActivity(), OnPageChangeListener {
|
||||
mFinalUrl = finalUrl ?: ""
|
||||
|
||||
imageView.setImageLoaderCallback(object : SimpleImageLoader() {
|
||||
var tryCount = 0
|
||||
|
||||
override fun onSuccess(image: File) {
|
||||
if (finalUrl != mUrlList!![position]) {
|
||||
val options = BitmapFactory.Options()
|
||||
@ -867,6 +869,15 @@ class ImageViewerActivity : BaseActivity(), OnPageChangeListener {
|
||||
onBackPressed()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onFail(error: java.lang.Exception?) {
|
||||
super.onFail(error)
|
||||
// 加载压缩图片失败时尝试加载原图
|
||||
if (finalUrl != rawUrl && tryCount == 0) {
|
||||
loadImage(thumbnailImageUrl, rawUrl, imageView)
|
||||
tryCount ++
|
||||
}
|
||||
}
|
||||
})
|
||||
loadImage(thumbnailImageUrl, compressedStandardImageUrl, imageView)
|
||||
|
||||
|
||||
@ -43,6 +43,7 @@ import androidx.lifecycle.ViewModelProvider;
|
||||
import androidx.lifecycle.ViewModelProviders;
|
||||
|
||||
import com.gh.ad.AdDelegateHelper;
|
||||
import com.gh.ad.SplashAdVideoView;
|
||||
import com.gh.common.constant.Config;
|
||||
import com.gh.common.filter.RegionSettingHelper;
|
||||
import com.gh.common.history.HistoryDatabase;
|
||||
@ -98,6 +99,7 @@ import com.gh.gamecenter.feature.utils.SentryHelper;
|
||||
import com.gh.gamecenter.home.custom.model.CustomPageShareRepository;
|
||||
import com.gh.gamecenter.home.skip.PackageSkipActivity;
|
||||
import com.gh.gamecenter.login.user.UserManager;
|
||||
import com.gh.gamecenter.login.utils.QuickLoginHelper;
|
||||
import com.gh.gamecenter.packagehelper.PackageViewModel;
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager;
|
||||
import com.gh.gamecenter.room.AppDatabase;
|
||||
@ -128,7 +130,6 @@ import java.lang.reflect.Field;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
import io.reactivex.SingleSource;
|
||||
@ -147,7 +148,7 @@ public class MainActivity extends BaseActivity {
|
||||
|
||||
public static final String SHOW_AD = "show_ad";
|
||||
public static final int COUNTDOWN_AD = 100;
|
||||
public static final int COUNTDOWN_MAX_COUNT = 3;
|
||||
private int mCountdownMaxCount = 3;
|
||||
private int mCountdownCount = 0;
|
||||
|
||||
private static final String CURRENT_PAGE = "current_page";
|
||||
@ -254,9 +255,6 @@ public class MainActivity extends BaseActivity {
|
||||
}
|
||||
}
|
||||
|
||||
// 必须放在这里,否则会导致获取 baseActivity 不是本应用包名
|
||||
DownloadManager.getInstance().initDownloadService();
|
||||
|
||||
ReservationRepository.refreshReservations();
|
||||
|
||||
// 跳转至其它页面
|
||||
@ -319,7 +317,7 @@ public class MainActivity extends BaseActivity {
|
||||
|
||||
mMainWrapperViewModel.requestAllDialogData();
|
||||
|
||||
// QuickLoginHelper.getPhoneInfo();
|
||||
QuickLoginHelper.preLogin(this);
|
||||
|
||||
// TODO 搞清楚为什么这里要获取微信相关配置
|
||||
WechatBindHelper.getWechatConfig(null);
|
||||
@ -507,6 +505,11 @@ public class MainActivity extends BaseActivity {
|
||||
float screenHeightInDp = DisplayUtils.px2dip(this, screenHeightInPx);
|
||||
|
||||
if (startAdContainer != null && sdkStartAdContainer != null && adsFl != null) {
|
||||
mCountdownMaxCount = AdDelegateHelper.INSTANCE.getSplashAdDisplayInterval();
|
||||
TextView jumpBtn = findViewById(R.id.jumpBtn);
|
||||
if (jumpBtn != null) {
|
||||
jumpBtn.setText(getString(R.string.splash_jump, mCountdownMaxCount));
|
||||
}
|
||||
AdDelegateHelper.requestSplashAd(
|
||||
this,
|
||||
screenWidthInPx,
|
||||
@ -536,7 +539,7 @@ public class MainActivity extends BaseActivity {
|
||||
super.handleMessage(msg);
|
||||
if (msg.what == COUNTDOWN_AD) {
|
||||
mCountdownCount++;
|
||||
if (COUNTDOWN_MAX_COUNT < mCountdownCount) {
|
||||
if (mCountdownMaxCount < mCountdownCount) {
|
||||
AdDelegateHelper.INSTANCE.setShowingSplashAd(false);
|
||||
hideSplashAd();
|
||||
|
||||
@ -556,7 +559,7 @@ public class MainActivity extends BaseActivity {
|
||||
}
|
||||
} else {
|
||||
TextView jumpBtn = findViewById(R.id.jumpBtn);
|
||||
jumpBtn.setText(String.format(Locale.CHINA, "跳过 %d", COUNTDOWN_MAX_COUNT - mCountdownCount));
|
||||
jumpBtn.setText(getString(R.string.splash_jump, mCountdownMaxCount - mCountdownCount));
|
||||
Message newMsg = Message.obtain();
|
||||
newMsg.what = COUNTDOWN_AD;
|
||||
newMsg.obj = msg.obj;
|
||||
@ -584,6 +587,11 @@ public class MainActivity extends BaseActivity {
|
||||
getIntent().putExtra(SHOW_AD, false);
|
||||
View startAdContainer = findViewById(R.id.startAdContainer);
|
||||
if (startAdContainer != null) {
|
||||
// 如果有播放开屏视频广告,需要及时释放
|
||||
SplashAdVideoView adVideoView = startAdContainer.findViewById(R.id.ad_video);
|
||||
if (adVideoView != null) {
|
||||
adVideoView.clearAll();
|
||||
}
|
||||
startAdContainer.setVisibility(View.GONE);
|
||||
ExtensionsKt.removeFromParent(startAdContainer, true);
|
||||
}
|
||||
@ -739,7 +747,7 @@ public class MainActivity extends BaseActivity {
|
||||
|
||||
ToastUtils.showToast("游戏启动中,请稍后~");
|
||||
handler.postDelayed(() -> {
|
||||
if(VHelper.isInnerInstalled(gamePackageName)) {
|
||||
if (VHelper.isInnerInstalled(gamePackageName)) {
|
||||
launchGame(gamePackageName).invoke();
|
||||
} else {
|
||||
VHelper.postOnInitialized(launchGame(gamePackageName));
|
||||
@ -799,7 +807,7 @@ public class MainActivity extends BaseActivity {
|
||||
public void onFailure(@Nullable HttpException e) {
|
||||
super.onFailure(e);
|
||||
try {
|
||||
ErrorHelper.handleErrorWithCustomizedHandler(MainActivity.this, e.response().errorBody().string(), false, "", "", "内容实名", null, null, code -> {
|
||||
ErrorHelper.handleErrorWithCustomizedHandler(MainActivity.this, e.response().errorBody().string(), false, "", "", "内容实名", null, null, code -> {
|
||||
if (code == 404001) {
|
||||
if (mShouldShowAd) {
|
||||
AppExecutor.getUiExecutor().executeWithDelay(() -> {
|
||||
@ -938,7 +946,7 @@ public class MainActivity extends BaseActivity {
|
||||
Config.getNewSetting();
|
||||
}
|
||||
|
||||
// mPackageViewModel.checkData();
|
||||
mPackageViewModel.checkData();
|
||||
deleteSimulatorGame();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,21 +0,0 @@
|
||||
package com.gh.gamecenter;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.gh.gamecenter.common.base.activity.ToolBarActivity;
|
||||
import com.halo.assistant.fragment.user.SelectPortraitFragment;
|
||||
|
||||
/**
|
||||
* Created by khy on 2017/2/10.
|
||||
*/
|
||||
public class SelectUserIconActivity extends ToolBarActivity {
|
||||
|
||||
@NonNull
|
||||
public static Intent getIntent(Context context) {
|
||||
return getTargetIntent(context, SelectUserIconActivity.class, SelectPortraitFragment.class);
|
||||
}
|
||||
|
||||
}
|
||||
@ -9,6 +9,7 @@ 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.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
|
||||
@ -29,12 +30,14 @@ class ShellActivity : ToolBarActivity() {
|
||||
private fun handleIntent(bundle: Bundle?) {
|
||||
// We parse the bundle to fragment to let fragment get data from bundle itself to survive configuration changes.
|
||||
val intentType = Type.fromString(bundle?.getString(INTENT_TYPE) ?: "")
|
||||
val extraData = bundle?.getBundle(EntranceConsts.KEY_DATA)
|
||||
|
||||
when (intentType) {
|
||||
Type.AMWAY_SUCCESS -> startFragment(AmwaySuccessFragment().with(bundle))
|
||||
Type.SWITCH_INSTALL_METHOD -> startFragment(SwitchInstallMethodFragment())
|
||||
Type.REAL_NAME_INFO -> startFragment(RealNameInfoFragment().with(bundle))
|
||||
Type.MANUALLY_REAL_NAME -> startFragment(ManuallyRealNameFragment().with(bundle?.getBundle(EntranceConsts.KEY_DATA)))
|
||||
Type.MANUALLY_REAL_NAME -> startFragment(ManuallyRealNameFragment().with(extraData))
|
||||
Type.SIMPLE_LIBAO_LIST -> startFragment(LibaoListFragment.newInstance(extraData))
|
||||
}
|
||||
}
|
||||
|
||||
@ -68,7 +71,8 @@ class ShellActivity : ToolBarActivity() {
|
||||
AMWAY_SUCCESS("amway_success"),
|
||||
SWITCH_INSTALL_METHOD("switch_install_method"),
|
||||
REAL_NAME_INFO("real_name_info"),
|
||||
MANUALLY_REAL_NAME("manually_real_name");
|
||||
MANUALLY_REAL_NAME("manually_real_name"),
|
||||
SIMPLE_LIBAO_LIST("simple_libao_list");
|
||||
|
||||
companion object {
|
||||
fun fromString(typeString: String): Type {
|
||||
|
||||
@ -5,7 +5,6 @@ import static com.gh.gamecenter.common.constant.EntranceConsts.ENTRANCE_PUSH;
|
||||
import static com.gh.gamecenter.common.constant.EntranceConsts.HOST_ANSWER;
|
||||
import static com.gh.gamecenter.common.constant.EntranceConsts.HOST_ARCHIVE_LOGIN;
|
||||
import static com.gh.gamecenter.common.constant.EntranceConsts.HOST_ARTICLE;
|
||||
import static com.gh.gamecenter.common.constant.EntranceConsts.HOST_CATEGORY;
|
||||
import static com.gh.gamecenter.common.constant.EntranceConsts.HOST_COLUMN;
|
||||
import static com.gh.gamecenter.common.constant.EntranceConsts.HOST_COLUMN_COLLECTION;
|
||||
import static com.gh.gamecenter.common.constant.EntranceConsts.HOST_COMMUNITY;
|
||||
@ -15,6 +14,7 @@ import static com.gh.gamecenter.common.constant.EntranceConsts.HOST_DOWNLOAD;
|
||||
import static com.gh.gamecenter.common.constant.EntranceConsts.HOST_GAME;
|
||||
import static com.gh.gamecenter.common.constant.EntranceConsts.HOST_GAME_COLLECTION_DETAIL;
|
||||
import static com.gh.gamecenter.common.constant.EntranceConsts.HOST_GAME_COLLECTION_SQUARE;
|
||||
import static com.gh.gamecenter.common.constant.EntranceConsts.HOST_INSTALL;
|
||||
import static com.gh.gamecenter.common.constant.EntranceConsts.HOST_INVOKE_ONLY;
|
||||
import static com.gh.gamecenter.common.constant.EntranceConsts.HOST_LIBAO;
|
||||
import static com.gh.gamecenter.common.constant.EntranceConsts.HOST_QQ;
|
||||
@ -56,6 +56,8 @@ import androidx.annotation.Nullable;
|
||||
import com.gh.common.util.CheckLoginUtils;
|
||||
import com.gh.common.util.DirectUtils;
|
||||
import com.gh.common.util.EntranceUtils;
|
||||
import com.gh.common.util.PackageInstaller;
|
||||
import com.gh.download.DownloadManager;
|
||||
import com.gh.gamecenter.common.base.activity.BaseActivity;
|
||||
import com.gh.gamecenter.common.constant.Constants;
|
||||
import com.gh.gamecenter.common.constant.EntranceConsts;
|
||||
@ -77,6 +79,7 @@ import com.gh.vspace.shortcut.OnCreateShortcutResult;
|
||||
import com.gh.vspace.shortcut.ShortcutManager;
|
||||
import com.gh.vspace.shortcut.ShortcutPermissionTipsDialog;
|
||||
import com.lightgame.config.CommonDebug;
|
||||
import com.lightgame.download.DownloadEntity;
|
||||
import com.lightgame.utils.Utils;
|
||||
import com.muugi.shortcut.core.Executor;
|
||||
|
||||
@ -311,10 +314,6 @@ public class SkipActivity extends BaseActivity {
|
||||
DirectUtils.directToCommunityColumn(this, community, columnId, entrance, "");
|
||||
break;
|
||||
|
||||
case HOST_CATEGORY:
|
||||
title = uri.getQueryParameter("title");
|
||||
DirectUtils.directCategoryDirectory(this, path, title, entrance, pathName);
|
||||
break;
|
||||
case HOST_COLUMN_COLLECTION:
|
||||
DirectUtils.directToColumnCollection(this, path, -1, entrance, "", "", "", "", null,false);
|
||||
break;
|
||||
@ -434,6 +433,13 @@ public class SkipActivity extends BaseActivity {
|
||||
String restartGamePkg = uri.getQueryParameter(EntranceConsts.KEY_GAME_PKG);
|
||||
VHelper.launch(this, restartGamePkg, false, true);
|
||||
break;
|
||||
case HOST_INSTALL:
|
||||
String packageName = uri.getQueryParameter("package_name");
|
||||
DownloadEntity downloadEntity = DownloadManager
|
||||
.getInstance()
|
||||
.getDownloadEntitySnapshotByPackageName(packageName);
|
||||
PackageInstaller.install(this, downloadEntity);
|
||||
break;
|
||||
default:
|
||||
EntranceUtils.jumpActivity(this, new Bundle()); // 跳转至首页
|
||||
return;
|
||||
|
||||
@ -83,19 +83,20 @@ class SplashAdActivity : BaseActivity() {
|
||||
super.handleMessage(msg)
|
||||
if (msg.what == MainActivity.COUNTDOWN_AD) {
|
||||
mCountdownCount++
|
||||
if (MainActivity.COUNTDOWN_MAX_COUNT < mCountdownCount) {
|
||||
if (COUNTDOWN_MAX_COUNT < mCountdownCount) {
|
||||
AdDelegateHelper.isShowingSplashAd = false
|
||||
finishActivity()
|
||||
} else {
|
||||
val jumpBtn = findViewById<TextView>(R.id.jumpBtn)
|
||||
jumpBtn.text =
|
||||
String.format(Locale.CHINA, "跳过 %d", MainActivity.COUNTDOWN_MAX_COUNT - mCountdownCount)
|
||||
jumpBtn.text = getString(R.string.splash_jump, COUNTDOWN_MAX_COUNT - mCountdownCount)
|
||||
mBaseHandler.sendEmptyMessageDelayed(MainActivity.COUNTDOWN_AD, 1000)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val COUNTDOWN_MAX_COUNT = 3
|
||||
|
||||
@JvmStatic
|
||||
fun getIntent(context: Context): Intent {
|
||||
return Intent(context, SplashAdActivity::class.java)
|
||||
|
||||
@ -14,6 +14,7 @@ import com.gh.common.util.DialogUtils;
|
||||
import com.gh.common.util.DirectUtils;
|
||||
import com.gh.gamecenter.R;
|
||||
import com.gh.gamecenter.adapter.viewholder.CommentViewHolder;
|
||||
import com.gh.gamecenter.common.constant.Constants;
|
||||
import com.gh.gamecenter.common.constant.ItemViewType;
|
||||
import com.gh.gamecenter.common.retrofit.Response;
|
||||
import com.gh.gamecenter.common.utils.ImageUtils;
|
||||
@ -178,7 +179,12 @@ public class CommentDetailAdapter extends BaseRecyclerAdapter<ViewHolder> {
|
||||
holder.commentTimeTv.setText(holder.commentTimeTv.getText() + " · " + commentEntity.getSource().getRegion());
|
||||
}
|
||||
|
||||
TextHelper.highlightTextThatIsWrappedInsideWrapperByDefault(holder.commentContentTv, commentEntity.getContent());
|
||||
TextHelper.highlightTextThatIsWrappedInsideWrapperByDefault(
|
||||
holder.commentContentTv,
|
||||
commentEntity.getContent(),
|
||||
Constants.DEFAULT_TEXT_WRAPPER,
|
||||
new TextHelper.DirectToWebViewHighlightedTextClick(mContext, "评论详情")
|
||||
);
|
||||
ArticleCommentParent parent = commentEntity.getParent();
|
||||
if (parent != null && !TextUtils.isEmpty(parent.getUser().getName())) {
|
||||
holder.quoteContainer.setVisibility(View.VISIBLE);
|
||||
@ -197,7 +203,12 @@ public class CommentDetailAdapter extends BaseRecyclerAdapter<ViewHolder> {
|
||||
content = mContext.getString(R.string.comment_hide_hint);
|
||||
holder.quoteContentTv.setTextColor(mContext.getResources().getColor(R.color.text_d5d5d5));
|
||||
}
|
||||
TextHelper.highlightTextThatIsWrappedInsideWrapperByDefault(holder.quoteContentTv, content);
|
||||
TextHelper.highlightTextThatIsWrappedInsideWrapperByDefault(
|
||||
holder.quoteContentTv,
|
||||
content,
|
||||
Constants.DEFAULT_TEXT_WRAPPER,
|
||||
new TextHelper.DirectToWebViewHighlightedTextClick(mContext, "评论详情")
|
||||
);
|
||||
} else {
|
||||
holder.quoteContainer.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
@ -25,6 +25,7 @@ import com.gh.gamecenter.ShareCardPicActivity;
|
||||
import com.gh.gamecenter.WebActivity;
|
||||
import com.gh.gamecenter.adapter.viewholder.CommentHeadViewHolder;
|
||||
import com.gh.gamecenter.adapter.viewholder.CommentViewHolder;
|
||||
import com.gh.gamecenter.common.constant.Constants;
|
||||
import com.gh.gamecenter.common.constant.EntranceConsts;
|
||||
import com.gh.gamecenter.common.retrofit.JSONObjectResponse;
|
||||
import com.gh.gamecenter.common.retrofit.OkHttpCache;
|
||||
@ -393,7 +394,12 @@ public class MessageDetailAdapter extends BaseRecyclerAdapter<ViewHolder> {
|
||||
return;
|
||||
}
|
||||
|
||||
TextHelper.highlightTextThatIsWrappedInsideWrapperByDefault(holder.commentContentTv, commentEntity.getContent());
|
||||
TextHelper.highlightTextThatIsWrappedInsideWrapperByDefault(
|
||||
holder.commentContentTv,
|
||||
commentEntity.getContent(),
|
||||
Constants.DEFAULT_TEXT_WRAPPER,
|
||||
new TextHelper.DirectToWebViewHighlightedTextClick(holder.commentContentTv.getContext(), "消息详情")
|
||||
);
|
||||
ArticleCommentParent parent = commentEntity.getParent();
|
||||
if (parent != null && !TextUtils.isEmpty(parent.getUser().getName())) {
|
||||
holder.quoteContainer.setVisibility(View.VISIBLE);
|
||||
@ -412,7 +418,12 @@ public class MessageDetailAdapter extends BaseRecyclerAdapter<ViewHolder> {
|
||||
content = mContext.getString(R.string.comment_hide_hint);
|
||||
holder.quoteContentTv.setTextColor(mContext.getResources().getColor(R.color.text_d5d5d5));
|
||||
}
|
||||
TextHelper.highlightTextThatIsWrappedInsideWrapperByDefault(holder.quoteContentTv, content);
|
||||
TextHelper.highlightTextThatIsWrappedInsideWrapperByDefault(
|
||||
holder.quoteContentTv,
|
||||
content,
|
||||
Constants.DEFAULT_TEXT_WRAPPER,
|
||||
new TextHelper.DirectToWebViewHighlightedTextClick(holder.quoteContentTv.getContext(), "消息详情")
|
||||
);
|
||||
} else {
|
||||
holder.quoteContainer.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
@ -33,6 +33,7 @@ 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
|
||||
import com.gh.gamecenter.core.runOnUiThread
|
||||
import com.gh.gamecenter.core.utils.PageSwitchDataHelper
|
||||
import com.gh.gamecenter.core.utils.StringUtils
|
||||
import com.gh.gamecenter.core.utils.ToastUtils
|
||||
@ -78,6 +79,9 @@ class DetailViewHolder(
|
||||
|
||||
// 额外的文字 (用于一些含图片的情况)
|
||||
val overlayTv: TextView?
|
||||
val overlayContainer: View?
|
||||
val extraOverlayTv: TextView?
|
||||
|
||||
var downloadPb: DownloadButton
|
||||
var downloadTips: LottieAnimationView
|
||||
|
||||
@ -90,6 +94,8 @@ class DetailViewHolder(
|
||||
downloadPb = view.findViewById(R.id.detail_progressbar)
|
||||
downloadTips = view.findViewById(R.id.downloadTipsLottie)
|
||||
overlayTv = view.findViewById(R.id.overlayTv)
|
||||
overlayContainer = view.findViewById(R.id.overlayContainer)
|
||||
extraOverlayTv = view.findViewById(R.id.extraOverlayTv)
|
||||
multiVersionDownloadTv = view.findViewById(R.id.multiVersionDownloadTv)
|
||||
localDownloadContainer = view.findViewById(R.id.localDownloadContainer)
|
||||
localDownloadSizeTv = view.findViewById(R.id.localDownloadSizeTv)
|
||||
@ -102,7 +108,7 @@ class DetailViewHolder(
|
||||
|
||||
val localDownloadListener = OnDetailDownloadClickListener(
|
||||
mViewHolder = this,
|
||||
mEntrance = entrance,
|
||||
mEntrance = entrance,
|
||||
mName = name ?: "",
|
||||
mTitle = title ?: "",
|
||||
mAsVGame = false,
|
||||
@ -152,6 +158,9 @@ class DetailViewHolder(
|
||||
}
|
||||
}
|
||||
downloadPb.putWidgetBusinessName("游戏详情页")
|
||||
// "DownLoadbuttonClick" 埋点需要上报traceEvent信息
|
||||
|
||||
gameEntity.exposureEvent = traceEvent
|
||||
downloadPb.putObject(gameEntity)
|
||||
restoreDialogFragment()
|
||||
}
|
||||
@ -175,6 +184,7 @@ class DetailViewHolder(
|
||||
|
||||
private val mGameEntity: GameEntity = mViewHolder.gameEntity
|
||||
private var mDownloadEntity: DownloadEntity? = null
|
||||
private val mPausedText = mViewHolder.context.getString(R.string.paused)
|
||||
|
||||
private fun showLandPageAddressDialogIfNeeded() {
|
||||
if (mGameEntity.isLandPageAddressDialog() && !mGameEntity.isLandPageAddressDialogShowOnly()) {
|
||||
@ -196,7 +206,11 @@ class DetailViewHolder(
|
||||
mViewHolder.downloadPb
|
||||
}
|
||||
|
||||
if (downloadButton.buttonStyle !== ButtonStyle.INSTALL_NORMAL && downloadButton.buttonStyle !== ButtonStyle.INSTALL_PLUGIN && downloadButton.buttonStyle !== ButtonStyle.LAUNCH_OR_OPEN && downloadButton.buttonStyle !== ButtonStyle.NONE && downloadButton.buttonStyle !== ButtonStyle.NONE_WITH_HINT) {
|
||||
if (downloadButton.buttonStyle !== ButtonStyle.INSTALL_NORMAL
|
||||
&& downloadButton.buttonStyle !== ButtonStyle.INSTALL_PLUGIN
|
||||
&& downloadButton.buttonStyle !== ButtonStyle.LAUNCH_OR_OPEN
|
||||
&& downloadButton.buttonStyle !== ButtonStyle.NONE
|
||||
&& downloadButton.buttonStyle !== ButtonStyle.NONE_WITH_HINT) {
|
||||
// 畅玩游戏的非真实点击下载按钮下载不需要滚动到特定地方
|
||||
if (!mAsVGame || VHelper.shouldLaunchGameAfterInstallation()) {
|
||||
EventBus.getDefault().post(EBScroll(Constants.EB_GAME_DETAIL, mGameEntity.id))
|
||||
@ -526,11 +540,11 @@ class DetailViewHolder(
|
||||
mDownloadEntity = DownloadManager.getInstance().getDownloadEntitySnapshot(mGameEntity)
|
||||
}
|
||||
if (mDownloadEntity != null) {
|
||||
if (downloadButton.text.contains("继续加载")) {
|
||||
if (downloadButton.text.contains(mPausedText)) {
|
||||
DownloadManager.getInstance().resume(mDownloadEntity, false)
|
||||
} else {
|
||||
DownloadManager.getInstance().pause(mDownloadEntity!!.url)
|
||||
downloadButton.text = "继续加载 " + mDownloadEntity!!.percent + "%"
|
||||
downloadButton.text = "${DetailDownloadUtils.getValidProgress(mDownloadEntity)}% $mPausedText"
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -614,14 +628,18 @@ class DetailViewHolder(
|
||||
// 由于不想执行上面的 builder 相关的判断,所以这里还是丑陋的修改 downloadEntity 实体并保存到数据库中
|
||||
downloadEntity.setVGameDownloadModeInDualDownloadMode()
|
||||
DownloadManager.getInstance().updateDownloadEntity(downloadEntity)
|
||||
PackageInstaller.install(mViewHolder.context, downloadEntity)
|
||||
runOnUiThread {
|
||||
PackageInstaller.install(mViewHolder.context, downloadEntity)
|
||||
}
|
||||
}
|
||||
return
|
||||
} else if (!mAsVGame && downloadEntity.isVGameDownloadInDualDownloadMode()) {
|
||||
runOnIoThread {
|
||||
downloadEntity.setLocalDownloadModeInDualDownloadMode()
|
||||
DownloadManager.getInstance().updateDownloadEntity(downloadEntity)
|
||||
PackageInstaller.install(mViewHolder.context, downloadEntity)
|
||||
runOnUiThread {
|
||||
PackageInstaller.install(mViewHolder.context, downloadEntity)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@ -1,7 +1,14 @@
|
||||
package com.gh.gamecenter.adapter.viewholder
|
||||
|
||||
import android.graphics.Paint
|
||||
import android.widget.TextView
|
||||
import androidx.core.view.marginStart
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.base.BaseRecyclerViewHolder
|
||||
import com.gh.gamecenter.common.utils.ImageUtils
|
||||
import com.gh.gamecenter.common.utils.goneIf
|
||||
import com.gh.gamecenter.databinding.*
|
||||
import com.gh.gamecenter.home.custom.model.CustomPageData
|
||||
|
||||
class SearchGameFooterViewHolder(val binding: SearchGameFooterBinding) : BaseRecyclerViewHolder<Any>(binding.root)
|
||||
class PersonalHomeRatingViewHolder(val binding: PersonalHomeRatingBinding) : BaseRecyclerViewHolder<Any>(binding.root)
|
||||
@ -22,4 +29,62 @@ class CommonCollectionImageTextItemViewHolder(val binding: CommonCollectionImage
|
||||
BaseRecyclerViewHolder<Any>(binding.root)
|
||||
|
||||
class CommonCollectionDetailTwoItemHorizontalViewHolder(val binding: CommonCollectionDetailTwoItemHorizontalCustomBinding) :
|
||||
BaseRecyclerViewHolder<Any>(binding.root)
|
||||
BaseRecyclerViewHolder<Any>(binding.root)
|
||||
|
||||
class CustomCollectionDetailRecommendCardViewHolder(
|
||||
val binding: RecyclerRecommendCardCommonContentCollectionDetailCustomBinding
|
||||
) : BaseRecyclerViewHolder<Any>(binding.root) {
|
||||
|
||||
fun bind(item: CustomPageData.RecommendCard) {
|
||||
ImageUtils.display(binding.ivCover, item.image)
|
||||
binding.tvTitle.text = item.title
|
||||
binding.tvLabel.text = item.tag
|
||||
binding.tvPrice.text = item.highlight.text
|
||||
binding.tvOriginalPrice.text = if (item.deletion.isShowCurrencySymbol) {
|
||||
itemView.context.getString(R.string.price_with_symbol, item.deletion.text)
|
||||
} else {
|
||||
item.deletion.text
|
||||
}
|
||||
binding.tvOriginalPrice.paint.flags = Paint.STRIKE_THRU_TEXT_FLAG
|
||||
binding.tvCopy.text = item.addedContent
|
||||
binding.tvPriceSymbol.goneIf(!item.highlight.isShowCurrencySymbol)
|
||||
|
||||
binding.root.post {
|
||||
val views = mutableListOf(
|
||||
binding.tvPrice,
|
||||
binding.tvOriginalPrice,
|
||||
binding.tvCopy,
|
||||
)
|
||||
if (item.highlight.isShowCurrencySymbol) {
|
||||
views.add(0, binding.tvPriceSymbol)
|
||||
}
|
||||
|
||||
binding.tvLabel.goneIf(item.tag.isBlank()) {
|
||||
views.add(binding.tvLabel)
|
||||
}
|
||||
views.forEach {
|
||||
it.goneIf(false)
|
||||
}
|
||||
|
||||
hideOutOfBoundViewsIfNeed(views)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算统一排的view能否完整显示在 itemView 内,如果显示不下,则根据优先级依次隐藏优先级较低的
|
||||
* 数据中的View优先级由高到低排列,最后一个优先级最低
|
||||
*/
|
||||
private fun hideOutOfBoundViewsIfNeed(views: MutableList<TextView>) {
|
||||
if (views.isEmpty()) {
|
||||
return
|
||||
}
|
||||
val totalWidth = views.sumOf {
|
||||
it.width + it.marginStart
|
||||
}
|
||||
if (totalWidth > itemView.width) {
|
||||
views.removeLast().goneIf(true)
|
||||
hideOutOfBoundViewsIfNeed(views)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -234,11 +234,14 @@ class AmwayAdapter(
|
||||
if (m.find()) {
|
||||
val contents =
|
||||
TextHelper.getCommentLabelSpannableStringBuilder(amway.comment.content, R.color.text_theme)
|
||||
binding.amwayContentTv.setTextWithHighlightedTextWrappedInsideWrapper(contents, copyClickedText = true)
|
||||
binding.amwayContentTv.setTextWithHighlightedTextWrappedInsideWrapper(
|
||||
contents,
|
||||
highlightedTextClickListener = TextHelper.DirectToWebViewHighlightedTextClick(context, "安利墙")
|
||||
)
|
||||
} else {
|
||||
binding.amwayContentTv.setTextWithHighlightedTextWrappedInsideWrapper(
|
||||
amway.comment.content,
|
||||
copyClickedText = true
|
||||
highlightedTextClickListener = TextHelper.DirectToWebViewHighlightedTextClick(context, "安利墙")
|
||||
)
|
||||
}
|
||||
|
||||
@ -333,7 +336,11 @@ class AmwayAdapter(
|
||||
binding.sdvUserBadge.setOnClickListener {
|
||||
DialogUtils.showViewBadgeDialog(context, amway.comment.user.badge, object : ConfirmListener {
|
||||
override fun onConfirm() {
|
||||
MtaHelper.onEvent("进入徽章墙_用户记录", "安利墙", "${amway.comment.user.name}(${amway.comment.user.id})")
|
||||
MtaHelper.onEvent(
|
||||
"进入徽章墙_用户记录",
|
||||
"安利墙",
|
||||
"${amway.comment.user.name}(${amway.comment.user.id})"
|
||||
)
|
||||
MtaHelper.onEvent("徽章中心", "进入徽章中心", "安利墙")
|
||||
DirectUtils.directToBadgeWall(
|
||||
context,
|
||||
|
||||
@ -1,43 +0,0 @@
|
||||
package com.gh.gamecenter.catalog
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import com.gh.base.DownloadToolbarActivity
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.constant.EntranceConsts
|
||||
import com.gh.gamecenter.common.utils.updateStatusBarColor
|
||||
|
||||
class CatalogActivity : DownloadToolbarActivity() {
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setToolbarMenu(R.menu.menu_download)
|
||||
updateStatusBarColor(R.color.ui_surface, R.color.ui_surface)
|
||||
}
|
||||
|
||||
override fun showDownloadMenu(): Boolean {
|
||||
return true
|
||||
}
|
||||
|
||||
override fun provideNormalIntent(): Intent {
|
||||
return getTargetIntent(this, CatalogActivity::class.java, CatalogFragment::class.java)
|
||||
}
|
||||
|
||||
override fun onDarkModeChanged() {
|
||||
super.onDarkModeChanged()
|
||||
updateStatusBarColor(R.color.ui_surface, R.color.ui_surface)
|
||||
}
|
||||
|
||||
override fun isAutoResetViewBackgroundEnabled() = true
|
||||
|
||||
companion object {
|
||||
fun getIntent(context: Context, catalogId: String, catalogTitle: String, entrance: String): Intent {
|
||||
val bundle = Bundle()
|
||||
bundle.putString(EntranceConsts.KEY_CATALOG_ID, catalogId)
|
||||
bundle.putString(EntranceConsts.KEY_CATALOG_TITLE, catalogTitle)
|
||||
bundle.putString(EntranceConsts.KEY_ENTRANCE, entrance)
|
||||
return getTargetIntent(context, CatalogActivity::class.java, CatalogFragment::class.java, bundle)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,53 +0,0 @@
|
||||
package com.gh.gamecenter.catalog
|
||||
|
||||
import android.content.Context
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import com.gh.gamecenter.common.base.BaseRecyclerViewHolder
|
||||
import com.gh.gamecenter.common.utils.goneIf
|
||||
import com.gh.gamecenter.common.utils.toBinding
|
||||
import com.gh.gamecenter.common.utils.toColor
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.databinding.CatalogItemBinding
|
||||
import com.gh.gamecenter.entity.CatalogEntity
|
||||
import com.lightgame.adapter.BaseRecyclerAdapter
|
||||
|
||||
class CatalogAdapter(
|
||||
context: Context,
|
||||
private val mFragment: CatalogFragment,
|
||||
private val mViewModel: CatalogViewModel,
|
||||
private val mList: List<CatalogEntity.SubCatalogEntity>
|
||||
) : BaseRecyclerAdapter<CatalogAdapter.CatalogItemViewHolder>(context) {
|
||||
|
||||
override fun getItemCount() = mList.size
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) =
|
||||
CatalogItemViewHolder(parent.toBinding())
|
||||
|
||||
override fun onBindViewHolder(holder: CatalogItemViewHolder, position: Int) {
|
||||
holder.binding.run {
|
||||
val catalogEntity = mList[position]
|
||||
catalogName.text = catalogEntity.name
|
||||
recommendTag.goneIf(!catalogEntity.recommended)
|
||||
if (catalogEntity.name == mViewModel.selectedCatalogName) {
|
||||
selectedTag.visibility = View.VISIBLE
|
||||
catalogName.setTextColor(R.color.text_theme.toColor(mContext))
|
||||
root.setBackgroundColor(R.color.ui_surface.toColor(mContext))
|
||||
} else {
|
||||
selectedTag.visibility = View.GONE
|
||||
catalogName.setTextColor(R.color.text_primary.toColor(mContext))
|
||||
root.background = null
|
||||
}
|
||||
root.setOnClickListener {
|
||||
if (catalogEntity.name != mViewModel.selectedCatalogName) {
|
||||
mViewModel.selectedCatalogName = catalogEntity.name
|
||||
mViewModel.logSubCatalogClick(position)
|
||||
mFragment.changeCatalog(position)
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class CatalogItemViewHolder(val binding: CatalogItemBinding) : BaseRecyclerViewHolder<Any>(binding.root)
|
||||
}
|
||||
@ -1,240 +0,0 @@
|
||||
package com.gh.gamecenter.catalog
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import androidx.core.os.bundleOf
|
||||
import androidx.lifecycle.Observer
|
||||
import com.gh.gamecenter.common.base.fragment.LazyFragment
|
||||
import com.gh.gamecenter.common.constant.EntranceConsts
|
||||
import com.gh.gamecenter.common.utils.dip2px
|
||||
import com.gh.gamecenter.common.utils.toColor
|
||||
import com.gh.gamecenter.common.utils.viewModelProviderFromParent
|
||||
import com.gh.gamecenter.common.view.FixLinearLayoutManager
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.databinding.FragmentCatalogBinding
|
||||
import com.gh.gamecenter.entity.CatalogEntity
|
||||
|
||||
class CatalogFragment : LazyFragment() {
|
||||
|
||||
private var mBinding: FragmentCatalogBinding? = null
|
||||
private var mViewModel: CatalogViewModel? = null
|
||||
private var mEntity: CatalogEntity? = null
|
||||
private var mSpecialCatalogFragment: SpecialCatalogFragment? = null
|
||||
private var mSubCatalogFragment: SubCatalogFragment? = null
|
||||
|
||||
private var mCatalogId: String = ""
|
||||
private var mCatalogTitle: String = ""
|
||||
private var mLastSelectedPosition = -1
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
savedInstanceState?.run {
|
||||
mLastSelectedPosition = getInt(EntranceConsts.KEY_LAST_SELECTED_POSITION)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onSaveInstanceState(outState: Bundle) {
|
||||
mViewModel?.run {
|
||||
outState.putInt(EntranceConsts.KEY_LAST_SELECTED_POSITION, selectedCatalogPosition)
|
||||
}
|
||||
super.onSaveInstanceState(outState)
|
||||
}
|
||||
|
||||
override fun getRealLayoutId() = R.layout.fragment_catalog
|
||||
|
||||
override fun onRealLayoutInflated(inflatedView: View) {
|
||||
mBinding = FragmentCatalogBinding.bind(inflatedView)
|
||||
}
|
||||
|
||||
override fun onFragmentFirstVisible() {
|
||||
mCatalogId = arguments?.getString(EntranceConsts.KEY_CATALOG_ID) ?: ""
|
||||
mCatalogTitle = arguments?.getString(EntranceConsts.KEY_CATALOG_TITLE) ?: ""
|
||||
mViewModel = viewModelProviderFromParent(CatalogViewModel.Factory(mCatalogId, mCatalogTitle), mCatalogId)
|
||||
|
||||
mViewModel?.validEntranceName = if (mEntrance.contains("首页")) "首页" else "板块"
|
||||
if (arguments?.getBoolean(EntranceConsts.KEY_IS_HOME) == true) {
|
||||
mViewModel?.validEntranceName = "首页Tab栏"
|
||||
}
|
||||
mViewModel?.logAppearance()
|
||||
|
||||
super.onFragmentFirstVisible()
|
||||
}
|
||||
|
||||
override fun initRealView() {
|
||||
super.initRealView()
|
||||
|
||||
setNavigationTitle(mCatalogTitle)
|
||||
mViewModel?.catalogs?.observe(viewLifecycleOwner, Observer {
|
||||
mBinding?.run {
|
||||
reuseLoading.root.visibility = View.GONE
|
||||
if (it != null) {
|
||||
reuseNoConnection.root.visibility = View.GONE
|
||||
if (it.subCatalog.isNotEmpty()) {
|
||||
containerCatalog.visibility = View.VISIBLE
|
||||
reuseNoneData.root.visibility = View.GONE
|
||||
mEntity = it
|
||||
if (mEntity!!.hasSpecial) {
|
||||
val specialEntity = CatalogEntity.SubCatalogEntity(name = "精选")
|
||||
(mEntity!!.subCatalog as ArrayList).add(0, specialEntity)
|
||||
}
|
||||
initView()
|
||||
} else {
|
||||
containerCatalog.visibility = View.GONE
|
||||
reuseNoneData.root.visibility = View.VISIBLE
|
||||
}
|
||||
} else {
|
||||
containerCatalog.visibility = View.GONE
|
||||
reuseNoneData.root.visibility = View.GONE
|
||||
reuseNoConnection.root.visibility = View.VISIBLE
|
||||
reuseNoConnection.root.setOnClickListener {
|
||||
reuseNoConnection.root.visibility = View.GONE
|
||||
reuseLoading.root.visibility = View.VISIBLE
|
||||
mViewModel?.getCatalogs()
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
// 嵌入在首页时特殊处理
|
||||
if (arguments?.getBoolean(EntranceConsts.KEY_IS_HOME) == true) {
|
||||
mBinding?.divider?.visibility = View.GONE
|
||||
mBinding?.root?.setBackgroundColor(R.color.ui_surface.toColor(requireContext()))
|
||||
mBinding?.root?.setPadding(0, 8F.dip2px(), 0, 0)
|
||||
mBinding?.rvCatalog?.setBackgroundColor(R.color.ui_background.toColor(requireContext()))
|
||||
}
|
||||
}
|
||||
|
||||
private fun initView() {
|
||||
mEntity?.run {
|
||||
mViewModel?.run {
|
||||
if (subCatalog.isNotEmpty()) {
|
||||
if (mLastSelectedPosition != -1) {
|
||||
selectedCatalogPosition = mLastSelectedPosition
|
||||
selectedCatalogName = subCatalog[mLastSelectedPosition].name
|
||||
} else {
|
||||
selectedCatalogPosition = 0
|
||||
selectedCatalogName = subCatalog[0].name
|
||||
}
|
||||
mBinding?.rvCatalog?.layoutManager = FixLinearLayoutManager(requireContext())
|
||||
mBinding?.rvCatalog?.adapter =
|
||||
CatalogAdapter(requireContext(), this@CatalogFragment, this, subCatalog)
|
||||
|
||||
if (hasSpecial && selectedCatalogPosition == 0) {
|
||||
mSpecialCatalogFragment =
|
||||
childFragmentManager.findFragmentByTag(SpecialCatalogFragment::class.java.name) as? SpecialCatalogFragment
|
||||
?: SpecialCatalogFragment()
|
||||
mSpecialCatalogFragment?.arguments = bundleOf(
|
||||
EntranceConsts.KEY_IS_CATEGORY_V2 to false,
|
||||
EntranceConsts.KEY_CATALOG_ID to id,
|
||||
EntranceConsts.KEY_CATALOG_TITLE to mCatalogTitle,
|
||||
EntranceConsts.KEY_EXPOSURE_SOURCE to arguments?.getParcelable(
|
||||
EntranceConsts.KEY_EXPOSURE_SOURCE
|
||||
)
|
||||
)
|
||||
childFragmentManager.beginTransaction().replace(
|
||||
R.id.container_sub_catalog,
|
||||
mSpecialCatalogFragment!!,
|
||||
SpecialCatalogFragment::class.java.name
|
||||
).commitAllowingStateLoss()
|
||||
} else {
|
||||
mSubCatalogFragment =
|
||||
childFragmentManager.findFragmentByTag(SubCatalogFragment::class.java.name) as? SubCatalogFragment
|
||||
?: SubCatalogFragment()
|
||||
mSubCatalogFragment?.arguments = bundleOf(
|
||||
EntranceConsts.KEY_CATALOG_ID to id,
|
||||
EntranceConsts.KEY_PRIMARY_CATALOG_ID to subCatalog[selectedCatalogPosition].id,
|
||||
EntranceConsts.KEY_CATALOG_TITLE to mCatalogTitle
|
||||
)
|
||||
childFragmentManager.beginTransaction().replace(
|
||||
R.id.container_sub_catalog,
|
||||
mSubCatalogFragment!!,
|
||||
SubCatalogFragment::class.java.name
|
||||
).commitAllowingStateLoss()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun changeCatalog(position: Int) {
|
||||
mEntity?.run {
|
||||
mViewModel?.run {
|
||||
if (hasSpecial) {
|
||||
changeCatalogIfHasSpecial(position)
|
||||
} else {
|
||||
changeSubCatalogInSubCatalogFragment(position)
|
||||
}
|
||||
selectedCatalogPosition = position
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun changeCatalogIfHasSpecial(position: Int) {
|
||||
mViewModel?.run {
|
||||
when {
|
||||
selectedCatalogPosition == 0 -> changeToSubCatalogFragment(position)
|
||||
position == 0 -> changeToSpecialCatalogFragment()
|
||||
else -> changeSubCatalogInSubCatalogFragment(position)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun changeToSubCatalogFragment(position: Int) {
|
||||
mEntity?.run {
|
||||
mSubCatalogFragment =
|
||||
childFragmentManager.findFragmentByTag(SubCatalogFragment::class.java.name) as? SubCatalogFragment
|
||||
?: SubCatalogFragment()
|
||||
mSubCatalogFragment?.arguments = bundleOf(
|
||||
EntranceConsts.KEY_CATALOG_ID to id,
|
||||
EntranceConsts.KEY_PRIMARY_CATALOG_ID to subCatalog[position].id,
|
||||
EntranceConsts.KEY_CATALOG_TITLE to mCatalogTitle
|
||||
)
|
||||
childFragmentManager.beginTransaction().replace(
|
||||
R.id.container_sub_catalog,
|
||||
mSubCatalogFragment!!,
|
||||
SubCatalogFragment::class.java.name
|
||||
).commitAllowingStateLoss()
|
||||
}
|
||||
}
|
||||
|
||||
private fun changeToSpecialCatalogFragment() {
|
||||
mEntity?.run {
|
||||
mSpecialCatalogFragment =
|
||||
childFragmentManager.findFragmentByTag(SpecialCatalogFragment::class.java.name) as? SpecialCatalogFragment
|
||||
?: SpecialCatalogFragment()
|
||||
mSpecialCatalogFragment?.arguments = bundleOf(
|
||||
EntranceConsts.KEY_IS_CATEGORY_V2 to false,
|
||||
EntranceConsts.KEY_CATALOG_ID to id,
|
||||
EntranceConsts.KEY_CATALOG_TITLE to mCatalogTitle,
|
||||
EntranceConsts.KEY_EXPOSURE_SOURCE to arguments?.getParcelable(
|
||||
EntranceConsts.KEY_EXPOSURE_SOURCE
|
||||
)
|
||||
)
|
||||
childFragmentManager.beginTransaction().replace(
|
||||
R.id.container_sub_catalog,
|
||||
mSpecialCatalogFragment!!,
|
||||
SpecialCatalogFragment::class.java.name
|
||||
).commitAllowingStateLoss()
|
||||
}
|
||||
}
|
||||
|
||||
private fun changeSubCatalogInSubCatalogFragment(position: Int) {
|
||||
mEntity?.run {
|
||||
if (mSubCatalogFragment?.isStateSaved == false) {
|
||||
mSubCatalogFragment?.arguments = bundleOf(
|
||||
EntranceConsts.KEY_CATALOG_ID to id,
|
||||
EntranceConsts.KEY_PRIMARY_CATALOG_ID to subCatalog[position].id,
|
||||
EntranceConsts.KEY_CATALOG_TITLE to mCatalogTitle
|
||||
)
|
||||
}
|
||||
mSubCatalogFragment?.changeSubCatalog(subCatalog[position].id)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDarkModeChanged() {
|
||||
super.onDarkModeChanged()
|
||||
mBinding?.rvCatalog?.adapter?.run {
|
||||
notifyItemRangeChanged(0, itemCount)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,72 +0,0 @@
|
||||
package com.gh.gamecenter.catalog
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.Application
|
||||
import androidx.lifecycle.AndroidViewModel
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import com.gh.common.util.LogUtils
|
||||
import com.gh.gamecenter.entity.CatalogEntity
|
||||
import com.gh.gamecenter.common.retrofit.BiResponse
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager
|
||||
import com.halo.assistant.HaloApp
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
|
||||
class CatalogViewModel(application: Application, val catalogId: String, val catalogTitle: String) :
|
||||
AndroidViewModel(application) {
|
||||
|
||||
private val api = RetrofitManager.getInstance().api
|
||||
var catalogs = MutableLiveData<CatalogEntity>()
|
||||
|
||||
var selectedCatalogName: String = ""
|
||||
var selectedCatalogPosition: Int = 0
|
||||
|
||||
var validEntranceName: String = ""
|
||||
|
||||
init {
|
||||
getCatalogs()
|
||||
}
|
||||
|
||||
@SuppressLint("CheckResult")
|
||||
fun getCatalogs() {
|
||||
api.getCatalogs(catalogId)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(object : BiResponse<CatalogEntity>() {
|
||||
override fun onSuccess(data: CatalogEntity) {
|
||||
catalogs.postValue(data)
|
||||
}
|
||||
|
||||
override fun onFailure(exception: Exception) {
|
||||
super.onFailure(exception)
|
||||
catalogs.postValue(null)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fun logAppearance() {
|
||||
LogUtils.logNewCatalogAppearanceEvent(validEntranceName, catalogTitle)
|
||||
}
|
||||
|
||||
fun logSubCatalogClick(position: Int) {
|
||||
LogUtils.logSubCatalogClickEvent(validEntranceName, "${catalogTitle}_${selectedCatalogName}", position)
|
||||
}
|
||||
|
||||
fun logSubCatalogContentClick(itemName: String, listPosition: Int) {
|
||||
LogUtils.logSubCatalogContentClickEvent(
|
||||
validEntranceName,
|
||||
"${catalogTitle}_${selectedCatalogName}_${itemName}",
|
||||
selectedCatalogPosition,
|
||||
listPosition
|
||||
)
|
||||
}
|
||||
|
||||
class Factory(private val catalogId: String, private val catalogTitle: String) :
|
||||
ViewModelProvider.NewInstanceFactory() {
|
||||
override fun <T : ViewModel> create(modelClass: Class<T>): T {
|
||||
return CatalogViewModel(HaloApp.getInstance().application, catalogId, catalogTitle) as T
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,56 +0,0 @@
|
||||
package com.gh.gamecenter.catalog
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import com.gh.base.DownloadToolbarActivity
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.constant.EntranceConsts
|
||||
import com.gh.gamecenter.common.utils.updateStatusBarColor
|
||||
import com.gh.gamecenter.entity.CatalogEntity
|
||||
|
||||
class NewCatalogListActivity : DownloadToolbarActivity() {
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setToolbarMenu(R.menu.menu_download)
|
||||
updateStatusBarColor(R.color.ui_surface, R.color.ui_surface)
|
||||
}
|
||||
|
||||
override fun showDownloadMenu(): Boolean {
|
||||
return true
|
||||
}
|
||||
|
||||
override fun onDarkModeChanged() {
|
||||
super.onDarkModeChanged()
|
||||
updateStatusBarColor(R.color.ui_surface, R.color.ui_surface)
|
||||
}
|
||||
|
||||
override fun isAutoResetViewBackgroundEnabled() = true
|
||||
|
||||
companion object {
|
||||
fun getIntent(
|
||||
context: Context,
|
||||
primaryCatalogId: String, // 一级分类 id
|
||||
primaryCatalogName: String, // 一级分类名
|
||||
catalogTitle: String,
|
||||
catalog: CatalogEntity,
|
||||
initTitle: String
|
||||
): Intent {
|
||||
val bundle = Bundle()
|
||||
bundle.putParcelable(EntranceConsts.KEY_DATA, catalog)
|
||||
bundle.putString(EntranceConsts.KEY_PRIMARY_CATALOG_ID, primaryCatalogId)
|
||||
bundle.putString(EntranceConsts.KEY_PRIMARY_CATALOG_NAME, primaryCatalogName)
|
||||
bundle.putString(EntranceConsts.KEY_NAME, catalog.name)
|
||||
bundle.putString(EntranceConsts.KEY_CATALOG_TITLE, catalogTitle)
|
||||
bundle.putString(EntranceConsts.KEY_CATALOG_INIT_TITLE, initTitle)
|
||||
return getTargetIntent(
|
||||
context,
|
||||
NewCatalogListActivity::class.java,
|
||||
NewCatalogListFragment::class.java,
|
||||
bundle
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,192 +0,0 @@
|
||||
package com.gh.gamecenter.catalog
|
||||
|
||||
import android.content.Context
|
||||
import android.util.SparseArray
|
||||
import android.view.ViewGroup
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.gh.common.exposure.IExposable
|
||||
import com.gh.common.util.DownloadItemUtils
|
||||
import com.gh.gamecenter.GameDetailActivity
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.adapter.viewholder.GameViewHolder
|
||||
import com.gh.gamecenter.common.baselist.ListAdapter
|
||||
import com.gh.gamecenter.common.constant.ItemViewType
|
||||
import com.gh.gamecenter.common.exposure.ExposureSource
|
||||
import com.gh.gamecenter.common.utils.dip2px
|
||||
import com.gh.gamecenter.common.utils.toBinding
|
||||
import com.gh.gamecenter.common.viewholder.FooterViewHolder
|
||||
import com.gh.gamecenter.core.utils.StringUtils
|
||||
import com.gh.gamecenter.eventbus.EBDownloadStatus
|
||||
import com.gh.gamecenter.feature.entity.GameEntity
|
||||
import com.gh.gamecenter.feature.exposure.ExposureEvent
|
||||
import com.gh.gamecenter.feature.exposure.ExposureType
|
||||
import com.gh.gamecenter.feature.game.GameItemViewHolder
|
||||
import com.lightgame.download.DownloadEntity
|
||||
|
||||
class NewCatalogListAdapter(
|
||||
context: Context,
|
||||
private val mBaseExposureSource: ExposureSource,
|
||||
private val mViewModel: NewCatalogListViewModel,
|
||||
private val mEntrance: String?
|
||||
) : ListAdapter<GameEntity>(context), IExposable {
|
||||
|
||||
private val mExposureEventSparseArray: SparseArray<ExposureEvent> = SparseArray()
|
||||
|
||||
val positionAndPackageMap = HashMap<String, Int>()
|
||||
|
||||
override fun setListData(updateData: MutableList<GameEntity>?) {
|
||||
// 记录游戏位置
|
||||
if (updateData != null) {
|
||||
for (i in 0 until updateData.size) {
|
||||
val gameEntity = updateData[i]
|
||||
var packages = gameEntity.id
|
||||
for (apkEntity in gameEntity.getApk()) {
|
||||
packages += apkEntity.packageName
|
||||
}
|
||||
positionAndPackageMap[packages + i] = i
|
||||
}
|
||||
}
|
||||
super.setListData(updateData)
|
||||
}
|
||||
|
||||
fun clearPositionAndPackageMap() {
|
||||
positionAndPackageMap.clear()
|
||||
}
|
||||
|
||||
override fun areItemsTheSame(oldItem: GameEntity?, newItem: GameEntity?): Boolean {
|
||||
return oldItem?.id == newItem?.id
|
||||
}
|
||||
|
||||
override fun getItemViewType(position: Int): Int {
|
||||
if (position == itemCount - 1) {
|
||||
return ItemViewType.ITEM_FOOTER
|
||||
}
|
||||
return ItemViewType.GAME_NORMAL
|
||||
}
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
|
||||
return when (viewType) {
|
||||
ItemViewType.GAME_NORMAL -> {
|
||||
GameItemViewHolder(parent.toBinding())
|
||||
}
|
||||
else -> {
|
||||
FooterViewHolder(mLayoutInflater.inflate(R.layout.refresh_footerview, parent, false))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int {
|
||||
return if (mEntityList == null || mEntityList.isEmpty()) return 0 else mEntityList.size + 1
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
|
||||
if (holder is GameItemViewHolder) {
|
||||
val padTop = if (position == 0) 16F.dip2px() else 8F.dip2px()
|
||||
holder.itemView.setPadding(16F.dip2px(), padTop, 16F.dip2px(), 8F.dip2px())
|
||||
|
||||
val gameEntity = mEntityList[position]
|
||||
|
||||
holder.bindGameItem(gameEntity)
|
||||
holder.initServerType(gameEntity)
|
||||
|
||||
val sortType = mViewModel.sortType.value
|
||||
val sortSize = mViewModel.sortSize.text
|
||||
val toolbarTitle = mViewModel.title
|
||||
val selectedCatalogName = mViewModel.selectedCatalog.name
|
||||
|
||||
val exposureSources = ArrayList<ExposureSource>()
|
||||
exposureSources.add(mBaseExposureSource)
|
||||
exposureSources.add(ExposureSource(toolbarTitle))
|
||||
exposureSources.add(ExposureSource("二级分类详情", "$selectedCatalogName+$sortType+$sortSize"))
|
||||
|
||||
val event = ExposureEvent.createEvent(gameEntity, exposureSources, null, ExposureType.EXPOSURE)
|
||||
mExposureEventSparseArray.put(position, event)
|
||||
|
||||
holder.itemView.setOnClickListener {
|
||||
GameDetailActivity.startGameDetailActivity(
|
||||
mContext,
|
||||
gameEntity,
|
||||
StringUtils.buildString(
|
||||
mEntrance,
|
||||
"+(",
|
||||
toolbarTitle,
|
||||
":列表[",
|
||||
selectedCatalogName,
|
||||
"=",
|
||||
sortType,
|
||||
"=",
|
||||
(position + 1).toString(),
|
||||
"])"
|
||||
),
|
||||
traceEvent = event
|
||||
)
|
||||
}
|
||||
DownloadItemUtils.setOnClickListener(
|
||||
mContext,
|
||||
holder.binding.downloadBtn,
|
||||
gameEntity,
|
||||
position,
|
||||
this,
|
||||
StringUtils.buildString(
|
||||
StringUtils.buildString(
|
||||
mEntrance,
|
||||
"+(",
|
||||
toolbarTitle,
|
||||
":列表[",
|
||||
selectedCatalogName,
|
||||
"=",
|
||||
sortType,
|
||||
"=",
|
||||
(position + 1).toString(),
|
||||
"])"
|
||||
)
|
||||
),
|
||||
location = StringUtils.buildString(selectedCatalogName, ":", gameEntity.name),
|
||||
traceEvent = event
|
||||
)
|
||||
|
||||
DownloadItemUtils.updateItem(mContext, gameEntity, GameViewHolder(holder.binding), "star&brief")
|
||||
} else if (holder is FooterViewHolder) {
|
||||
holder.initItemPadding()
|
||||
holder.initFooterViewHolder(mViewModel, mIsLoading, mIsNetworkError, mIsOver)
|
||||
}
|
||||
}
|
||||
|
||||
fun notifyItemByDownload(download: DownloadEntity) {
|
||||
for (key in positionAndPackageMap.keys) {
|
||||
// sentry上报download.packageName可能为空
|
||||
if (download.packageName != null
|
||||
&& download.gameId != null
|
||||
&& key.contains(download.packageName)
|
||||
&& key.contains(download.gameId)
|
||||
) {
|
||||
val position = positionAndPackageMap[key]
|
||||
if (position != null && mEntityList != null && position < mEntityList.size) {
|
||||
mEntityList[position].getEntryMap()[download.platform] = download
|
||||
notifyItemChanged(position)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun notifyItemAndRemoveDownload(status: EBDownloadStatus) {
|
||||
for (key in positionAndPackageMap.keys) {
|
||||
if (key.contains(status.packageName) && key.contains(status.gameId)) {
|
||||
val position = positionAndPackageMap[key]
|
||||
if (position != null && mEntityList != null && position < mEntityList.size) {
|
||||
mEntityList[position].getEntryMap().remove(status.platform)
|
||||
notifyItemChanged(position)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun getEventByPosition(pos: Int): ExposureEvent? {
|
||||
return mExposureEventSparseArray.get(pos)
|
||||
}
|
||||
|
||||
override fun getEventListByPosition(pos: Int): List<ExposureEvent>? {
|
||||
return null
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,209 +0,0 @@
|
||||
package com.gh.gamecenter.catalog
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import com.ethanhua.skeleton.Skeleton
|
||||
import com.gh.common.exposure.ExposureListener
|
||||
import com.gh.common.util.DialogUtils
|
||||
import com.gh.common.view.CatalogFilterView
|
||||
import com.gh.common.xapk.XapkInstaller
|
||||
import com.gh.common.xapk.XapkUnzipStatus
|
||||
import com.gh.download.DownloadManager
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.constant.Constants
|
||||
import com.gh.gamecenter.common.constant.EntranceConsts
|
||||
import com.gh.gamecenter.common.utils.observeNonNull
|
||||
import com.gh.gamecenter.common.baselist.ListFragment
|
||||
import com.gh.gamecenter.common.exposure.ExposureSource
|
||||
import com.gh.gamecenter.common.utils.toColor
|
||||
import com.gh.gamecenter.common.utils.viewModelProvider
|
||||
import com.gh.gamecenter.databinding.FragmentCatalogListBinding
|
||||
import com.gh.gamecenter.entity.CatalogEntity
|
||||
import com.gh.gamecenter.feature.entity.GameEntity
|
||||
import com.gh.gamecenter.entity.SubjectSettingEntity
|
||||
import com.gh.gamecenter.eventbus.EBDownloadStatus
|
||||
import com.gh.gamecenter.eventbus.EBPackage
|
||||
import com.lightgame.download.DataWatcher
|
||||
import com.lightgame.download.DownloadEntity
|
||||
import org.greenrobot.eventbus.Subscribe
|
||||
import org.greenrobot.eventbus.ThreadMode
|
||||
|
||||
class NewCatalogListFragment : ListFragment<GameEntity, NewCatalogListViewModel>() {
|
||||
|
||||
private var mPrimaryCatalogName: String = "" // 一级分类名
|
||||
private var mPrimaryCatalogId: String = "" // 一级分类 id
|
||||
private var mPrimeCatalog: CatalogEntity? = null
|
||||
private var mSubCatalogList = arrayListOf<CatalogEntity.SubCatalogEntity>()
|
||||
private var mInitCatalogName = ""
|
||||
private var mAdapter: NewCatalogListAdapter? = null
|
||||
private val mDataWatcher = object : DataWatcher() {
|
||||
override fun onDataChanged(downloadEntity: DownloadEntity) {
|
||||
mAdapter?.notifyItemByDownload(downloadEntity)
|
||||
|
||||
if (downloadEntity.meta[XapkInstaller.XAPK_UNZIP_STATUS] == XapkUnzipStatus.FAILURE.name) {
|
||||
showUnzipFailureDialog(downloadEntity)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDataInit(downloadEntity: DownloadEntity) {
|
||||
mAdapter?.notifyItemByDownload(downloadEntity)
|
||||
}
|
||||
}
|
||||
|
||||
private var mBinding: FragmentCatalogListBinding? = null
|
||||
private lateinit var mExposureListener: ExposureListener
|
||||
private lateinit var mViewModel: NewCatalogListViewModel
|
||||
|
||||
override fun getLayoutId() = 0
|
||||
|
||||
override fun getInflatedLayout() = FragmentCatalogListBinding.inflate(layoutInflater).apply { mBinding = this }.root
|
||||
|
||||
override fun provideListViewModel() = viewModelProvider<NewCatalogListViewModel>()
|
||||
|
||||
override fun provideListAdapter() = mAdapter
|
||||
?: NewCatalogListAdapter(
|
||||
requireContext(),
|
||||
ExposureSource(mPrimaryCatalogName),
|
||||
mViewModel,
|
||||
mEntrance
|
||||
).apply { mAdapter = this }
|
||||
|
||||
override fun getItemDecoration() = null
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
mViewModel = provideListViewModel()
|
||||
|
||||
mViewModel.title = arguments?.getString(EntranceConsts.KEY_NAME) ?: ""
|
||||
mViewModel.categoryTitle = arguments?.getString(EntranceConsts.KEY_CATALOG_TITLE) ?: ""
|
||||
mEntrance = arguments?.getString(EntranceConsts.KEY_ENTRANCE) ?: Constants.ENTRANCE_UNKNOWN
|
||||
mPrimeCatalog = arguments?.getParcelable(EntranceConsts.KEY_DATA)
|
||||
mSubCatalogList = mPrimeCatalog?.subCatalog as? ArrayList<CatalogEntity.SubCatalogEntity> ?: arrayListOf()
|
||||
|
||||
mInitCatalogName = arguments?.getString(EntranceConsts.KEY_CATALOG_INIT_TITLE) ?: ""
|
||||
mPrimaryCatalogName = arguments?.getString(EntranceConsts.KEY_PRIMARY_CATALOG_NAME) ?: ""
|
||||
mPrimaryCatalogId = arguments?.getString(EntranceConsts.KEY_PRIMARY_CATALOG_ID) ?: ""
|
||||
|
||||
mViewModel.selectedCatalog = mSubCatalogList.find { entity -> entity.name == mInitCatalogName }
|
||||
?: CatalogEntity.SubCatalogEntity()
|
||||
mViewModel.primaryCatalogId = mPrimaryCatalogId
|
||||
initSortType()
|
||||
|
||||
super.onCreate(savedInstanceState)
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
setNavigationTitle(mViewModel.title)
|
||||
|
||||
initFilterView()
|
||||
|
||||
mViewModel.refresh.observeNonNull(this) { onRefresh() }
|
||||
|
||||
mExposureListener = ExposureListener(this, mAdapter!!)
|
||||
mListRv.addOnScrollListener(mExposureListener)
|
||||
|
||||
mSkeletonScreen = Skeleton.bind(mBinding?.listSkeleton)
|
||||
.shimmer(true)
|
||||
.angle(Constants.SHIMMER_ANGLE)
|
||||
.color(R.color.ui_skeleton_highlight)
|
||||
.duration(Constants.SHIMMER_DURATION)
|
||||
.maskWidth(Constants.MASK_WIDTH)
|
||||
.gradientCenterColorWidth(Constants.GRADIENT_CENTER_COLOR_WIDTH)
|
||||
.load(R.layout.fragment_tags_skeleton)
|
||||
.show()
|
||||
}
|
||||
|
||||
private fun initSortType() {
|
||||
mPrimeCatalog?.switch?.run {
|
||||
if (hotSort == "on") {
|
||||
mViewModel.sortType = CatalogFilterView.SortType.RECOMMENDED
|
||||
return@run
|
||||
}
|
||||
if (newSort == "on") {
|
||||
mViewModel.sortType = CatalogFilterView.SortType.NEWEST
|
||||
return@run
|
||||
}
|
||||
if (starSort == "on") {
|
||||
mViewModel.sortType = CatalogFilterView.SortType.RATING
|
||||
return@run
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun initFilterView() {
|
||||
mBinding?.filterContainer?.run {
|
||||
visibility = View.VISIBLE
|
||||
setTypeList(mPrimeCatalog?.switch ?: CatalogEntity.CatalogSwitch())
|
||||
setCatalogList(mSubCatalogList, mInitCatalogName)
|
||||
setOnConfigSetupListener(object : CatalogFilterView.OnCatalogFilterSetupListener {
|
||||
override fun onSetupSortSize(sortSize: SubjectSettingEntity.Size) {
|
||||
mViewModel.updateSortConfig(sortSize = sortSize)
|
||||
}
|
||||
|
||||
override fun onSetupSortType(sortType: CatalogFilterView.SortType) {
|
||||
mViewModel.updateSortConfig(sortType = sortType)
|
||||
}
|
||||
|
||||
override fun onSetupSortCatalog(sortCatalog: CatalogEntity.SubCatalogEntity) {
|
||||
mViewModel.updateSortConfig(sortCatalog = sortCatalog)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
DownloadManager.getInstance().addObserver(mDataWatcher)
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
DownloadManager.getInstance().removeObserver(mDataWatcher)
|
||||
}
|
||||
|
||||
override fun onRefresh() {
|
||||
mAdapter?.clearPositionAndPackageMap()
|
||||
|
||||
super.onRefresh()
|
||||
}
|
||||
|
||||
// 下载被删除事件
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
fun onEventMainThread(status: EBDownloadStatus) {
|
||||
if ("delete" == status.status) {
|
||||
mAdapter?.notifyItemAndRemoveDownload(status)
|
||||
}
|
||||
}
|
||||
|
||||
// 安装/卸载 事件
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
fun onEventMainThread(busFour: EBPackage) {
|
||||
if (busFour.isInstalledOrUninstalled()) {
|
||||
mAdapter?.notifyDataSetChanged()
|
||||
}
|
||||
}
|
||||
|
||||
fun showUnzipFailureDialog(downloadEntity: DownloadEntity) {
|
||||
val data = mAdapter?.positionAndPackageMap ?: return
|
||||
for (gameAndPosition in data) {
|
||||
if (gameAndPosition.key.contains(downloadEntity.packageName)) {
|
||||
val targetView = mLayoutManager.findViewByPosition(gameAndPosition.value)
|
||||
if (targetView != null) {
|
||||
DialogUtils.showUnzipFailureDialog(requireContext(), downloadEntity)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDarkModeChanged() {
|
||||
super.onDarkModeChanged()
|
||||
mBinding?.filterContainer?.run {
|
||||
setRootBackgroundColor(R.color.ui_surface.toColor(requireContext()))
|
||||
setItemTextColor(R.color.text_secondary.toColor(requireContext()))
|
||||
updatePopupWindow()
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,98 +0,0 @@
|
||||
package com.gh.gamecenter.catalog
|
||||
|
||||
import android.app.Application
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import com.gh.gamecenter.common.entity.ExposureEntity
|
||||
import com.gh.common.exposure.ExposureUtils
|
||||
import com.gh.gamecenter.core.utils.UrlFilterUtils
|
||||
import com.gh.common.view.CatalogFilterView
|
||||
import com.gh.gamecenter.common.baselist.ListViewModel
|
||||
import com.gh.gamecenter.entity.CatalogEntity
|
||||
import com.gh.gamecenter.feature.entity.GameEntity
|
||||
import com.gh.gamecenter.entity.SubjectSettingEntity
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager
|
||||
import io.reactivex.Observable
|
||||
import io.reactivex.Single
|
||||
|
||||
class NewCatalogListViewModel(application: Application) : ListViewModel<GameEntity, GameEntity>(application) {
|
||||
|
||||
var title = "" // 显示在 Toolbar 的标题
|
||||
var categoryTitle = "" // 跳转进来的分类的标题
|
||||
|
||||
val refresh = MutableLiveData<Boolean>()
|
||||
|
||||
var selectedCatalog = CatalogEntity.SubCatalogEntity()
|
||||
var sortType = CatalogFilterView.SortType.RECOMMENDED
|
||||
var sortSize = SubjectSettingEntity.Size()
|
||||
|
||||
var primaryCatalogId = "" // 一级分类 id
|
||||
private val sensitiveApi = RetrofitManager.getInstance().api
|
||||
|
||||
override fun provideDataObservable(page: Int): Observable<List<GameEntity>>? = null
|
||||
|
||||
override fun provideDataSingle(page: Int): Single<List<GameEntity>> {
|
||||
return if (selectedCatalog.link.type == "column") { // column(专题)/tag(标签)
|
||||
sensitiveApi.getColumn(selectedCatalog.link.link, getSortType(), getSortSize(), page) // 专题
|
||||
} else {
|
||||
sensitiveApi.getGamesWithSpecificTag(getSortSize(), getSortType(), page) // 标签
|
||||
}
|
||||
}
|
||||
|
||||
override fun mergeResultLiveData() {
|
||||
mResultLiveData.addSource(mListLiveData) {
|
||||
it.forEach { game -> game.hideSizeInsideDes = true }
|
||||
ExposureUtils.updateExposureInfo(
|
||||
gameList = it,
|
||||
containerId = primaryCatalogId,
|
||||
containerType = ExposureEntity.CATEGORY_ID
|
||||
)
|
||||
mResultLiveData.postValue(it)
|
||||
}
|
||||
}
|
||||
|
||||
fun updateSortConfig(
|
||||
sortSize: SubjectSettingEntity.Size? = null,
|
||||
sortType: CatalogFilterView.SortType? = null,
|
||||
sortCatalog: CatalogEntity.SubCatalogEntity? = null
|
||||
) {
|
||||
when {
|
||||
sortSize != null && sortSize != this.sortSize -> {
|
||||
this.sortSize = sortSize
|
||||
refresh.postValue(true)
|
||||
}
|
||||
|
||||
sortType != null && sortType != this.sortType -> {
|
||||
this.sortType = sortType
|
||||
refresh.postValue(true)
|
||||
}
|
||||
|
||||
sortCatalog != null && sortCatalog != selectedCatalog -> {
|
||||
selectedCatalog = sortCatalog
|
||||
refresh.postValue(true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun getSortSize(): String? {
|
||||
return if (selectedCatalog.link.type == "column") {
|
||||
UrlFilterUtils.getFilterQuery(
|
||||
"min_size", sortSize.min.toString(),
|
||||
"max_size", sortSize.max.toString()
|
||||
)
|
||||
} else {
|
||||
UrlFilterUtils.getFilterQuery(
|
||||
"tag_id", selectedCatalog.link.link,
|
||||
"min_size", sortSize.min.toString(),
|
||||
"max_size", sortSize.max.toString()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun getSortType(): String? {
|
||||
return when (sortType) {
|
||||
CatalogFilterView.SortType.RECOMMENDED -> if (selectedCatalog.link.type == "column") "position:1" else "download:-1"
|
||||
CatalogFilterView.SortType.NEWEST -> "publish:-1"
|
||||
CatalogFilterView.SortType.RATING -> "star:-1"
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,54 +0,0 @@
|
||||
package com.gh.gamecenter.catalog
|
||||
|
||||
import android.content.Context
|
||||
import android.view.ViewGroup
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.base.BaseRecyclerViewHolder
|
||||
import com.gh.gamecenter.common.utils.*
|
||||
import com.gh.gamecenter.databinding.SubCatalogItemBinding
|
||||
import com.gh.gamecenter.entity.CatalogEntity
|
||||
import com.lightgame.adapter.BaseRecyclerAdapter
|
||||
|
||||
class SubCatalogAdapter(
|
||||
context: Context,
|
||||
private val mCatalogViewModel: CatalogViewModel,
|
||||
private val mPrimaryCatalog: CatalogEntity,
|
||||
private var mList: List<CatalogEntity.SubCatalogEntity>
|
||||
) : BaseRecyclerAdapter<SubCatalogAdapter.SubCatalogItemViewHolder>(context) {
|
||||
|
||||
private val mTypes = listOf("专题", "标签")
|
||||
|
||||
override fun getItemCount() = mList.size
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) =
|
||||
SubCatalogItemViewHolder(parent.toBinding())
|
||||
|
||||
override fun onBindViewHolder(holder: SubCatalogItemViewHolder, position: Int) {
|
||||
holder.binding.run {
|
||||
val catalogEntity = mList[position]
|
||||
ImageUtils.display(catalogIcon, catalogEntity.icon)
|
||||
catalogName.text = catalogEntity.name
|
||||
catalogName.setTextColor(R.color.text_primary.toColor(mContext))
|
||||
recommendTag.goneIf(!catalogEntity.recommended)
|
||||
root.setOnClickListener {
|
||||
mCatalogViewModel.logSubCatalogContentClick(catalogEntity.name, position)
|
||||
if (mTypes.contains(catalogEntity.type)) {
|
||||
root.context.startActivity(
|
||||
NewCatalogListActivity.getIntent(
|
||||
mContext,
|
||||
mCatalogViewModel.catalogId,
|
||||
mCatalogViewModel.catalogTitle,
|
||||
catalogEntity.name,
|
||||
mPrimaryCatalog,
|
||||
catalogEntity.name
|
||||
)
|
||||
)
|
||||
} else {
|
||||
DialogHelper.showUpgradeDialog(mContext)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class SubCatalogItemViewHolder(val binding: SubCatalogItemBinding) : BaseRecyclerViewHolder<Any>(binding.root)
|
||||
}
|
||||
@ -1,94 +0,0 @@
|
||||
package com.gh.gamecenter.catalog
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import androidx.lifecycle.Observer
|
||||
import androidx.recyclerview.widget.GridLayoutManager
|
||||
import com.gh.gamecenter.common.constant.EntranceConsts
|
||||
import com.gh.gamecenter.common.utils.viewModelProvider
|
||||
import com.gh.gamecenter.common.utils.viewModelProviderFromParent
|
||||
import com.gh.gamecenter.databinding.FragmentSubCatalogBinding
|
||||
import com.gh.gamecenter.entity.CatalogEntity
|
||||
import com.gh.gamecenter.common.base.fragment.ToolbarFragment
|
||||
|
||||
class SubCatalogFragment : ToolbarFragment() {
|
||||
|
||||
private var mBinding: FragmentSubCatalogBinding? = null
|
||||
private var mViewModel: SubCatalogViewModel? = null
|
||||
private var mCatalogViewModel: CatalogViewModel? = null
|
||||
private var mEntity: CatalogEntity? = null
|
||||
private var mCatalogId: String = ""
|
||||
private var mCatalogTitle: String = ""
|
||||
private var mPrimaryCatalogId: String = ""
|
||||
|
||||
override fun getLayoutId() = 0
|
||||
|
||||
override fun getInflatedLayout() = FragmentSubCatalogBinding.inflate(layoutInflater).apply { mBinding = this }.root
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
mCatalogId = arguments?.getString(EntranceConsts.KEY_CATALOG_ID) ?: ""
|
||||
mCatalogTitle = arguments?.getString(EntranceConsts.KEY_CATALOG_TITLE) ?: ""
|
||||
mPrimaryCatalogId = arguments?.getString(EntranceConsts.KEY_PRIMARY_CATALOG_ID) ?: ""
|
||||
mViewModel = viewModelProvider(SubCatalogViewModel.Factory(mCatalogId))
|
||||
mCatalogViewModel = viewModelProviderFromParent(CatalogViewModel.Factory(mCatalogId, mCatalogTitle), mCatalogId)
|
||||
mViewModel?.getSubCatalogs(mPrimaryCatalogId)
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
mViewModel?.catalogs?.observe(viewLifecycleOwner, Observer {
|
||||
mBinding?.run {
|
||||
reuseLoading.root.visibility = View.GONE
|
||||
if (it != null) {
|
||||
reuseNoConnection.root.visibility = View.GONE
|
||||
if (it.subCatalog.isNotEmpty()) {
|
||||
rvSubCatalog.visibility = View.VISIBLE
|
||||
reuseNoneData.root.visibility = View.GONE
|
||||
mEntity = it
|
||||
initView()
|
||||
} else {
|
||||
rvSubCatalog.visibility = View.GONE
|
||||
reuseNoneData.root.visibility = View.VISIBLE
|
||||
}
|
||||
} else {
|
||||
rvSubCatalog.visibility = View.GONE
|
||||
reuseNoneData.root.visibility = View.GONE
|
||||
reuseNoConnection.root.visibility = View.VISIBLE
|
||||
reuseNoConnection.root.setOnClickListener {
|
||||
reuseLoading.root.visibility = View.VISIBLE
|
||||
mViewModel?.getSubCatalogs(mPrimaryCatalogId)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private fun initView() {
|
||||
mEntity?.takeIf { mCatalogViewModel != null }?.run {
|
||||
mBinding?.rvSubCatalog?.layoutManager = GridLayoutManager(requireContext(), 3)
|
||||
mBinding?.rvSubCatalog?.adapter = SubCatalogAdapter(requireContext(), mCatalogViewModel!!, this, subCatalog)
|
||||
}
|
||||
}
|
||||
|
||||
fun changeSubCatalog(primaryCatalogId: String) {
|
||||
mBinding?.run {
|
||||
mPrimaryCatalogId = primaryCatalogId
|
||||
rvSubCatalog.visibility = View.GONE
|
||||
reuseNoneData.root.visibility = View.GONE
|
||||
reuseNoConnection.root.visibility = View.GONE
|
||||
reuseLoading.root.visibility = View.VISIBLE
|
||||
mViewModel?.getSubCatalogs(mPrimaryCatalogId)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDarkModeChanged() {
|
||||
super.onDarkModeChanged()
|
||||
mBinding?.rvSubCatalog?.adapter?.run {
|
||||
mBinding?.rvSubCatalog?.recycledViewPool?.clear()
|
||||
notifyItemRangeChanged(0, itemCount)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,44 +0,0 @@
|
||||
package com.gh.gamecenter.catalog
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.Application
|
||||
import androidx.lifecycle.AndroidViewModel
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import com.gh.gamecenter.entity.CatalogEntity
|
||||
import com.gh.gamecenter.common.retrofit.BiResponse
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager
|
||||
import com.halo.assistant.HaloApp
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
|
||||
class SubCatalogViewModel(application: Application, private val catalogId: String) : AndroidViewModel(application) {
|
||||
|
||||
private val api = RetrofitManager.getInstance().api
|
||||
var catalogs = MutableLiveData<CatalogEntity>()
|
||||
|
||||
|
||||
@SuppressLint("CheckResult")
|
||||
fun getSubCatalogs(primaryCatalogId: String) {
|
||||
api.getSubCatalogs(catalogId, primaryCatalogId)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(object : BiResponse<CatalogEntity>() {
|
||||
override fun onSuccess(data: CatalogEntity) {
|
||||
catalogs.postValue(data)
|
||||
}
|
||||
|
||||
override fun onFailure(exception: Exception) {
|
||||
super.onFailure(exception)
|
||||
catalogs.postValue(null)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
class Factory(private val catalogId: String) : ViewModelProvider.NewInstanceFactory() {
|
||||
override fun <T : ViewModel> create(modelClass: Class<T>): T {
|
||||
return SubCatalogViewModel(HaloApp.getInstance().application, catalogId) as T
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,51 +0,0 @@
|
||||
package com.gh.gamecenter.category
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import com.gh.base.DownloadToolbarActivity
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.constant.EntranceConsts
|
||||
import com.gh.gamecenter.common.utils.updateStatusBarColor
|
||||
|
||||
class CategoryDirectoryActivity : DownloadToolbarActivity() {
|
||||
|
||||
companion object {
|
||||
fun getIntent(context: Context, categoryId: String, categoryTitle: String): Intent {
|
||||
val bundle = Bundle()
|
||||
bundle.putString(EntranceConsts.KEY_CATEGORY_ID, categoryId)
|
||||
bundle.putString(EntranceConsts.KEY_CATEGORY_TITLE, categoryTitle)
|
||||
return getTargetIntent(
|
||||
context,
|
||||
CategoryDirectoryActivity::class.java,
|
||||
CategoryDirectoryFragment::class.java,
|
||||
bundle
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setToolbarMenu(R.menu.menu_download)
|
||||
updateStatusBarColor(R.color.ui_surface, R.color.ui_surface)
|
||||
}
|
||||
|
||||
override fun showDownloadMenu(): Boolean {
|
||||
return true
|
||||
}
|
||||
|
||||
override fun getActivityNameInChinese(): String {
|
||||
return "游戏分类"
|
||||
}
|
||||
|
||||
override fun provideNormalIntent(): Intent {
|
||||
return getTargetIntent(this, CategoryDirectoryActivity::class.java, CategoryDirectoryFragment::class.java)
|
||||
}
|
||||
|
||||
override fun isAutoResetViewBackgroundEnabled() = true
|
||||
|
||||
override fun onDarkModeChanged() {
|
||||
super.onDarkModeChanged()
|
||||
updateStatusBarColor(R.color.ui_surface, R.color.ui_surface)
|
||||
}
|
||||
}
|
||||
@ -1,157 +0,0 @@
|
||||
package com.gh.gamecenter.category
|
||||
|
||||
import android.content.Context
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.LinearLayout
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.gh.common.view.SubCategoryView
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.baselist.ListAdapter
|
||||
import com.gh.gamecenter.category.CategoryListActivity.Companion.getIntent
|
||||
import com.gh.gamecenter.common.utils.ImageUtils
|
||||
import com.gh.gamecenter.common.utils.toBinding
|
||||
import com.gh.gamecenter.common.utils.toColor
|
||||
import com.gh.gamecenter.core.utils.DisplayUtils
|
||||
import com.gh.gamecenter.databinding.ItemCategoryBinding
|
||||
import com.gh.gamecenter.entity.CategoryEntity
|
||||
import net.cachapa.expandablelayout.ExpandableLayout
|
||||
|
||||
class CategoryDirectoryAdapter(context: Context, var categoryTitle: String) : ListAdapter<CategoryEntity>(context) {
|
||||
|
||||
var recyclerView: RecyclerView? = null
|
||||
var expandStatusMap: HashMap<Int, Boolean> = HashMap()
|
||||
|
||||
private var sixteenDp: Int = 0
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
|
||||
if (sixteenDp == 0) sixteenDp = DisplayUtils.dip2px(parent.context, 16f)
|
||||
return CategoryViewHolder(parent.toBinding())
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int {
|
||||
return mEntityList.size
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
|
||||
when (holder) {
|
||||
is CategoryViewHolder -> {
|
||||
val category = mEntityList[position]
|
||||
holder.binding.run {
|
||||
divider.setBackgroundColor(R.color.ui_background.toColor(mContext))
|
||||
containerPrimaryCategory.setOnClickListener {
|
||||
root.context.startActivity(getIntent(root.context, categoryTitle, category, "全部"))
|
||||
}
|
||||
ImageUtils.display(iconIv, category.icon)
|
||||
categoryName.text = category.name
|
||||
}
|
||||
holder.bindCategory(
|
||||
category = mEntityList[position],
|
||||
expandableStatusMap = expandStatusMap,
|
||||
isExpended = expandStatusMap[position] != null && expandStatusMap[position] == true,
|
||||
marginTop = sixteenDp,
|
||||
categoryTitle = categoryTitle,
|
||||
expandedAction = { recyclerView?.smoothScrollToPosition(position) })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal class CategoryViewHolder(var binding: ItemCategoryBinding) : RecyclerView.ViewHolder(binding.root) {
|
||||
fun bindCategory(
|
||||
category: CategoryEntity,
|
||||
expandableStatusMap: HashMap<Int, Boolean>,
|
||||
isExpended: Boolean,
|
||||
marginTop: Int,
|
||||
categoryTitle: String,
|
||||
expandedAction: () -> Unit
|
||||
) {
|
||||
category.data?.let {
|
||||
var subCategoryView: SubCategoryView? = null
|
||||
|
||||
binding.containerUnexpandable.removeAllViews()
|
||||
val unexpandableSize = if (it.size > 6) 6 else it.size
|
||||
val unexpandableCategoryList = it.subList(0, unexpandableSize)
|
||||
unexpandableCategoryList.forEachIndexed { index, c ->
|
||||
when (index % 3) {
|
||||
0 -> {
|
||||
val params = LinearLayout.LayoutParams(
|
||||
LinearLayout.LayoutParams.MATCH_PARENT,
|
||||
LinearLayout.LayoutParams.MATCH_PARENT
|
||||
)
|
||||
if (subCategoryView != null) params.setMargins(0, marginTop, 0, 0)
|
||||
|
||||
subCategoryView = SubCategoryView(binding.root.context)
|
||||
|
||||
subCategoryView?.categoryTitle = categoryTitle
|
||||
subCategoryView?.primeCategory = category
|
||||
subCategoryView?.layoutParams = params
|
||||
|
||||
binding.containerUnexpandable.addView(subCategoryView)
|
||||
subCategoryView?.setLeftCategory(c)
|
||||
}
|
||||
1 -> subCategoryView?.setCenterCategory(c)
|
||||
2 -> subCategoryView?.setRightCategory(c)
|
||||
}
|
||||
}
|
||||
|
||||
if (it.size >= 7) {
|
||||
val extraCategoryList = it.subList(6, it.size)
|
||||
|
||||
binding.ivToggle.visibility = View.VISIBLE
|
||||
binding.ivToggle.setOnClickListener { binding.containerExpandable.toggle() }
|
||||
when {
|
||||
isExpended -> binding.ivToggle.setImageResource(R.drawable.ic_category_arrow_up)
|
||||
else -> binding.ivToggle.setImageResource(R.drawable.ic_category_arrow_down)
|
||||
}
|
||||
|
||||
val subCategoryViewLinearLayout = LinearLayout(binding.root.context)
|
||||
subCategoryViewLinearLayout.orientation = LinearLayout.VERTICAL
|
||||
subCategoryView = SubCategoryView(binding.root.context)
|
||||
|
||||
binding.containerExpandable.removeAllViews()
|
||||
binding.containerExpandable.addView(subCategoryViewLinearLayout)
|
||||
binding.containerExpandable.setExpanded(isExpended, false)
|
||||
binding.containerExpandable.setOnExpansionUpdateListener { _, state ->
|
||||
when (state) {
|
||||
ExpandableLayout.State.COLLAPSED -> {
|
||||
binding.ivToggle.setImageResource(R.drawable.ic_category_arrow_down)
|
||||
expandableStatusMap[adapterPosition] = false
|
||||
}
|
||||
ExpandableLayout.State.EXPANDED -> {
|
||||
binding.ivToggle.setImageResource(R.drawable.ic_category_arrow_up)
|
||||
expandableStatusMap[adapterPosition] = true
|
||||
expandedAction.invoke()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extraCategoryList.forEachIndexed { index, c ->
|
||||
when (index % 3) {
|
||||
0 -> {
|
||||
subCategoryView = SubCategoryView(binding.root.context)
|
||||
|
||||
val params = LinearLayout.LayoutParams(
|
||||
LinearLayout.LayoutParams.MATCH_PARENT,
|
||||
LinearLayout.LayoutParams.MATCH_PARENT
|
||||
)
|
||||
params.setMargins(0, marginTop, 0, 0)
|
||||
|
||||
subCategoryView?.categoryTitle = categoryTitle
|
||||
subCategoryView?.primeCategory = category
|
||||
subCategoryView?.layoutParams = params
|
||||
|
||||
subCategoryViewLinearLayout.addView(subCategoryView)
|
||||
subCategoryView?.setLeftCategory(c)
|
||||
}
|
||||
1 -> subCategoryView?.setCenterCategory(c)
|
||||
2 -> subCategoryView?.setRightCategory(c)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
binding.ivToggle.visibility = View.GONE
|
||||
binding.containerExpandable.removeAllViews()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,104 +0,0 @@
|
||||
package com.gh.gamecenter.category
|
||||
|
||||
import android.graphics.Color
|
||||
import android.view.View
|
||||
import androidx.lifecycle.ViewModelProviders
|
||||
import com.ethanhua.skeleton.Skeleton
|
||||
import com.gh.gamecenter.common.constant.Constants
|
||||
import com.gh.gamecenter.common.constant.EntranceConsts
|
||||
import com.gh.gamecenter.common.utils.toColor
|
||||
import com.gh.gamecenter.common.view.VerticalItemDecoration
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.baselist.LazyListFragment
|
||||
import com.gh.gamecenter.databinding.FragmentListBaseSkeletonBinding
|
||||
import com.gh.gamecenter.entity.CategoryEntity
|
||||
|
||||
class CategoryDirectoryFragment : LazyListFragment<CategoryEntity, CategoryDirectoryListViewModel>() {
|
||||
|
||||
private lateinit var mViewModel: CategoryDirectoryListViewModel
|
||||
private lateinit var mAdapter: CategoryDirectoryAdapter
|
||||
private var mBinding: FragmentListBaseSkeletonBinding? = null
|
||||
|
||||
override fun getRealLayoutId() = R.layout.fragment_list_base_skeleton
|
||||
|
||||
override fun onRealLayoutInflated(inflatedView: View) {
|
||||
super.onRealLayoutInflated(inflatedView)
|
||||
mBinding = FragmentListBaseSkeletonBinding.bind(inflatedView)
|
||||
}
|
||||
|
||||
override fun onFragmentFirstVisible() {
|
||||
mViewModel = ViewModelProviders.of(this).get(CategoryDirectoryListViewModel::class.java)
|
||||
mViewModel.categoryId = arguments?.getString(EntranceConsts.KEY_CATEGORY_ID) ?: ""
|
||||
mAdapter =
|
||||
CategoryDirectoryAdapter(requireContext(), arguments?.getString(EntranceConsts.KEY_CATEGORY_TITLE) ?: "")
|
||||
super.onFragmentFirstVisible()
|
||||
}
|
||||
|
||||
override fun initRealView() {
|
||||
super.initRealView()
|
||||
|
||||
setNavigationTitle(arguments?.getString(EntranceConsts.KEY_CATEGORY_TITLE))
|
||||
|
||||
mSkeletonScreen = Skeleton.bind(mBinding?.listSkeleton)
|
||||
.shimmer(true)
|
||||
.angle(Constants.SHIMMER_ANGLE)
|
||||
.color(R.color.ui_skeleton_highlight)
|
||||
.duration(Constants.SHIMMER_DURATION)
|
||||
.maskWidth(Constants.MASK_WIDTH)
|
||||
.gradientCenterColorWidth(Constants.GRADIENT_CENTER_COLOR_WIDTH)
|
||||
.load(R.layout.fragment_category_skeleton)
|
||||
.show()
|
||||
onLoadRefresh()
|
||||
|
||||
if (arguments?.getBoolean(EntranceConsts.KEY_IS_HOME) == true) {
|
||||
mListRv?.setPadding(
|
||||
0,
|
||||
context?.resources?.getDimension(R.dimen.home_recyclerview_padding_top)?.toInt() ?: 0,
|
||||
0,
|
||||
0
|
||||
)
|
||||
mListRv?.clipToPadding = false
|
||||
}
|
||||
|
||||
mListRv?.setBackgroundColor(R.color.ui_surface.toColor(requireContext()))
|
||||
mAdapter.recyclerView = mListRv
|
||||
mListRefresh?.isEnabled = false
|
||||
}
|
||||
|
||||
override fun isAutomaticLoad() = false
|
||||
|
||||
override fun provideListAdapter() = mAdapter
|
||||
|
||||
override fun provideListViewModel() = mViewModel
|
||||
|
||||
override fun getItemDecoration() = VerticalItemDecoration(context, 0F, false)
|
||||
|
||||
override fun onLoadRefresh() {
|
||||
mCachedView?.setBackgroundColor(R.color.ui_surface.toColor(requireContext()))
|
||||
super.onLoadRefresh()
|
||||
}
|
||||
|
||||
override fun onLoadDone() {
|
||||
mCachedView?.setBackgroundColor(Color.TRANSPARENT)
|
||||
super.onLoadDone()
|
||||
}
|
||||
|
||||
override fun onLoadEmpty() {
|
||||
mCachedView?.setBackgroundColor(Color.TRANSPARENT)
|
||||
super.onLoadEmpty()
|
||||
}
|
||||
|
||||
override fun onLoadError() {
|
||||
mCachedView?.setBackgroundColor(Color.TRANSPARENT)
|
||||
super.onLoadError()
|
||||
}
|
||||
|
||||
override fun onDarkModeChanged() {
|
||||
super.onDarkModeChanged()
|
||||
mListRv?.setBackgroundColor(R.color.ui_surface.toColor(requireContext()))
|
||||
mListRv?.adapter?.run {
|
||||
mListRv?.recycledViewPool?.clear()
|
||||
notifyItemRangeChanged(0, itemCount)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,21 +0,0 @@
|
||||
package com.gh.gamecenter.category
|
||||
|
||||
import android.app.Application
|
||||
import com.gh.gamecenter.common.baselist.ListViewModel
|
||||
import com.gh.gamecenter.entity.CategoryEntity
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager
|
||||
import io.reactivex.Observable
|
||||
|
||||
class CategoryDirectoryListViewModel(application: Application) :
|
||||
ListViewModel<CategoryEntity, CategoryEntity>(application) {
|
||||
|
||||
var categoryId = ""
|
||||
|
||||
override fun mergeResultLiveData() {
|
||||
mResultLiveData.addSource(mListLiveData, mResultLiveData::postValue)
|
||||
}
|
||||
|
||||
override fun provideDataObservable(page: Int): Observable<MutableList<CategoryEntity>> {
|
||||
return RetrofitManager.getInstance().api.getCategories(categoryId, page)
|
||||
}
|
||||
}
|
||||
@ -1,53 +0,0 @@
|
||||
package com.gh.gamecenter.category
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import com.gh.base.DownloadToolbarActivity
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.constant.EntranceConsts
|
||||
import com.gh.gamecenter.common.utils.updateStatusBarColor
|
||||
import com.gh.gamecenter.entity.CategoryEntity
|
||||
|
||||
class CategoryListActivity : DownloadToolbarActivity() {
|
||||
|
||||
companion object {
|
||||
fun getIntent(context: Context, categoryTitle: String, category: CategoryEntity, initTitle: String): Intent {
|
||||
val bundle = Bundle()
|
||||
if (category.data!!.isEmpty() || category.data!![0].name != "全部") {
|
||||
val plainCategory = CategoryEntity(id = category.id, name = "全部")
|
||||
((category.data) as ArrayList).add(0, plainCategory)
|
||||
}
|
||||
bundle.putParcelable(EntranceConsts.KEY_DATA, category)
|
||||
bundle.putString(EntranceConsts.KEY_NAME, category.name)
|
||||
bundle.putString(EntranceConsts.KEY_CATEGORY_TITLE, categoryTitle)
|
||||
bundle.putString(EntranceConsts.KEY_CATEGORY_INIT_TITLE, initTitle)
|
||||
return getTargetIntent(
|
||||
context,
|
||||
CategoryListActivity::class.java,
|
||||
NewCategoryListFragment::class.java,
|
||||
bundle
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setToolbarMenu(R.menu.menu_download)
|
||||
updateStatusBarColor(R.color.ui_surface, R.color.ui_surface)
|
||||
}
|
||||
|
||||
override fun showDownloadMenu(): Boolean {
|
||||
return true
|
||||
}
|
||||
|
||||
override fun getActivityNameInChinese(): String {
|
||||
return "游戏分类详情"
|
||||
}
|
||||
|
||||
override fun onDarkModeChanged() {
|
||||
super.onDarkModeChanged()
|
||||
updateStatusBarColor(R.color.ui_surface, R.color.ui_surface)
|
||||
}
|
||||
}
|
||||
@ -1,51 +0,0 @@
|
||||
package com.gh.gamecenter.category
|
||||
|
||||
import android.content.Context
|
||||
import android.view.ViewGroup
|
||||
import com.gh.gamecenter.common.base.BaseRecyclerViewHolder
|
||||
import com.gh.gamecenter.common.utils.toBinding
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.utils.toColor
|
||||
import com.gh.gamecenter.common.utils.toDrawable
|
||||
import com.gh.gamecenter.databinding.ItemTagBinding
|
||||
import com.gh.gamecenter.entity.CategoryEntity
|
||||
import com.lightgame.adapter.BaseRecyclerAdapter
|
||||
|
||||
class NewCategoryHorizontalAdapter(
|
||||
context: Context,
|
||||
private val mViewModel: NewCategoryListViewModel,
|
||||
private val mCategoryList: List<CategoryEntity>,
|
||||
private val mSmoothScrollAction: (position: Int) -> Unit
|
||||
) : BaseRecyclerAdapter<TagsViewHolder>(context) {
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): TagsViewHolder {
|
||||
return TagsViewHolder(parent.toBinding())
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: TagsViewHolder, position: Int) {
|
||||
val categoryEntity = mCategoryList[position]
|
||||
|
||||
if (mViewModel.selectedCategory.name == categoryEntity.name) {
|
||||
holder.binding.tagTv.background = R.drawable.bg_tag_text.toDrawable()
|
||||
holder.binding.tagTv.setTextColor(R.color.text_white.toColor(mContext))
|
||||
} else {
|
||||
holder.binding.tagTv.background = null
|
||||
holder.binding.tagTv.setTextColor(R.color.text_757575.toColor(mContext))
|
||||
}
|
||||
|
||||
holder.binding.tagTv.text = categoryEntity.name
|
||||
holder.binding.tagTv.setOnClickListener {
|
||||
mViewModel.changeSelectedCategory(categoryEntity)
|
||||
notifyDataSetChanged()
|
||||
|
||||
mSmoothScrollAction.invoke(position)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int {
|
||||
return mCategoryList.size
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class TagsViewHolder(val binding: ItemTagBinding) : BaseRecyclerViewHolder<Any>(binding.root)
|
||||
@ -1,185 +0,0 @@
|
||||
package com.gh.gamecenter.category
|
||||
|
||||
import android.content.Context
|
||||
import android.util.SparseArray
|
||||
import android.view.ViewGroup
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.gh.common.exposure.IExposable
|
||||
import com.gh.common.util.DownloadItemUtils
|
||||
import com.gh.gamecenter.GameDetailActivity
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.adapter.viewholder.GameViewHolder
|
||||
import com.gh.gamecenter.common.baselist.ListAdapter
|
||||
import com.gh.gamecenter.common.constant.ItemViewType
|
||||
import com.gh.gamecenter.common.exposure.ExposureSource
|
||||
import com.gh.gamecenter.common.utils.dip2px
|
||||
import com.gh.gamecenter.common.utils.toBinding
|
||||
import com.gh.gamecenter.common.viewholder.FooterViewHolder
|
||||
import com.gh.gamecenter.core.utils.StringUtils
|
||||
import com.gh.gamecenter.eventbus.EBDownloadStatus
|
||||
import com.gh.gamecenter.feature.entity.GameEntity
|
||||
import com.gh.gamecenter.feature.exposure.ExposureEvent
|
||||
import com.gh.gamecenter.feature.exposure.ExposureType
|
||||
import com.gh.gamecenter.feature.game.GameItemViewHolder
|
||||
import com.lightgame.download.DownloadEntity
|
||||
|
||||
class NewCategoryListAdapter(
|
||||
context: Context,
|
||||
private val mViewModel: NewCategoryListViewModel,
|
||||
private val mEntrance: String?
|
||||
) : ListAdapter<GameEntity>(context), IExposable {
|
||||
|
||||
private val mExposureEventSparseArray: SparseArray<ExposureEvent> = SparseArray()
|
||||
|
||||
val positionAndPackageMap = HashMap<String, Int>()
|
||||
|
||||
override fun setListData(updateData: MutableList<GameEntity>?) {
|
||||
// 记录游戏位置
|
||||
if (updateData != null) {
|
||||
for (i in 0 until updateData.size) {
|
||||
val gameEntity = updateData[i]
|
||||
var packages = gameEntity.id
|
||||
for (apkEntity in gameEntity.getApk()) {
|
||||
packages += apkEntity.packageName
|
||||
}
|
||||
positionAndPackageMap[packages + i] = i
|
||||
}
|
||||
}
|
||||
super.setListData(updateData)
|
||||
}
|
||||
|
||||
fun clearPositionAndPackageMap() {
|
||||
positionAndPackageMap.clear()
|
||||
}
|
||||
|
||||
override fun areItemsTheSame(oldItem: GameEntity?, newItem: GameEntity?): Boolean {
|
||||
return oldItem?.id == newItem?.id
|
||||
}
|
||||
|
||||
override fun getItemViewType(position: Int): Int {
|
||||
if (position == itemCount - 1) {
|
||||
return ItemViewType.ITEM_FOOTER
|
||||
}
|
||||
return ItemViewType.GAME_NORMAL
|
||||
}
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
|
||||
return when (viewType) {
|
||||
ItemViewType.GAME_NORMAL -> {
|
||||
GameItemViewHolder(parent.toBinding())
|
||||
}
|
||||
else -> {
|
||||
FooterViewHolder(mLayoutInflater.inflate(R.layout.refresh_footerview, parent, false))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int {
|
||||
return if (mEntityList == null || mEntityList.isEmpty()) return 0 else mEntityList.size + 1
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
|
||||
if (holder is GameItemViewHolder) {
|
||||
val gameEntity = mEntityList[position]
|
||||
|
||||
holder.bindGameItem(gameEntity)
|
||||
holder.initServerType(gameEntity)
|
||||
|
||||
val padTop = if (position == 0) 16F.dip2px() else 8F.dip2px()
|
||||
holder.itemView.setPadding(16F.dip2px(), padTop, 16F.dip2px(), 8F.dip2px())
|
||||
|
||||
val sortType = if ("download:-1" == mViewModel.getSortType()) "最热" else "最新"
|
||||
val toolbarTitle = mViewModel.title
|
||||
val categoryTitle = mViewModel.categoryTitle
|
||||
val selectedCategoryName = mViewModel.selectedCategory.name ?: ""
|
||||
|
||||
val exposureSources = ArrayList<ExposureSource>()
|
||||
exposureSources.add(ExposureSource(categoryTitle, selectedCategoryName))
|
||||
exposureSources.add(ExposureSource("二级分类", "$selectedCategoryName+$sortType"))
|
||||
|
||||
val event = ExposureEvent.createEvent(gameEntity, exposureSources, null, ExposureType.EXPOSURE)
|
||||
mExposureEventSparseArray.put(position, event)
|
||||
|
||||
holder.itemView.setOnClickListener {
|
||||
GameDetailActivity.startGameDetailActivity(
|
||||
mContext,
|
||||
gameEntity,
|
||||
StringUtils.buildString(
|
||||
mEntrance,
|
||||
"+(",
|
||||
toolbarTitle,
|
||||
":列表[",
|
||||
selectedCategoryName,
|
||||
"=",
|
||||
sortType,
|
||||
"=",
|
||||
(position + 1).toString(),
|
||||
"])"
|
||||
),
|
||||
traceEvent = event
|
||||
)
|
||||
}
|
||||
DownloadItemUtils.setOnClickListener(
|
||||
mContext,
|
||||
holder.binding.downloadBtn,
|
||||
gameEntity,
|
||||
position,
|
||||
this,
|
||||
StringUtils.buildString(
|
||||
StringUtils.buildString(
|
||||
mEntrance,
|
||||
"+(",
|
||||
toolbarTitle,
|
||||
":列表[",
|
||||
selectedCategoryName,
|
||||
"=",
|
||||
sortType,
|
||||
"=",
|
||||
(position + 1).toString(),
|
||||
"])"
|
||||
)
|
||||
),
|
||||
location = StringUtils.buildString(selectedCategoryName, ":", gameEntity.name),
|
||||
traceEvent = event
|
||||
)
|
||||
|
||||
DownloadItemUtils.updateItem(mContext, gameEntity, GameViewHolder(holder.binding))
|
||||
} else if (holder is FooterViewHolder) {
|
||||
holder.initItemPadding()
|
||||
holder.initFooterViewHolder(mViewModel, mIsLoading, mIsNetworkError, mIsOver)
|
||||
}
|
||||
}
|
||||
|
||||
fun notifyItemByDownload(download: DownloadEntity) {
|
||||
for (key in positionAndPackageMap.keys) {
|
||||
if (key.contains(download.packageName) && key.contains(download.gameId)) {
|
||||
val position = positionAndPackageMap[key]
|
||||
if (position != null && mEntityList != null && position < mEntityList.size) {
|
||||
mEntityList[position].getEntryMap()[download.platform] = download
|
||||
notifyItemChanged(position)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun notifyItemAndRemoveDownload(status: EBDownloadStatus) {
|
||||
for (key in positionAndPackageMap.keys) {
|
||||
if (key.contains(status.packageName) && key.contains(status.gameId)) {
|
||||
val position = positionAndPackageMap[key]
|
||||
if (position != null && mEntityList != null && position < mEntityList.size) {
|
||||
mEntityList[position].getEntryMap().remove(status.platform)
|
||||
notifyItemChanged(position)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun getEventByPosition(pos: Int): ExposureEvent? {
|
||||
return mExposureEventSparseArray.get(pos)
|
||||
}
|
||||
|
||||
override fun getEventListByPosition(pos: Int): List<ExposureEvent>? {
|
||||
return null
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,198 +0,0 @@
|
||||
package com.gh.gamecenter.category
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import com.ethanhua.skeleton.Skeleton
|
||||
import com.gh.common.exposure.ExposureListener
|
||||
import com.gh.common.util.DialogUtils
|
||||
import com.gh.common.view.ConfigFilterView
|
||||
import com.gh.common.xapk.XapkInstaller
|
||||
import com.gh.common.xapk.XapkUnzipStatus
|
||||
import com.gh.download.DownloadManager
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.constant.Constants
|
||||
import com.gh.gamecenter.common.baselist.ListAdapter
|
||||
import com.gh.gamecenter.common.baselist.ListFragment
|
||||
import com.gh.gamecenter.common.constant.EntranceConsts
|
||||
import com.gh.gamecenter.common.utils.observeNonNull
|
||||
import com.gh.gamecenter.common.utils.toColor
|
||||
import com.gh.gamecenter.common.utils.tryCatchInRelease
|
||||
import com.gh.gamecenter.common.utils.viewModelProvider
|
||||
import com.gh.gamecenter.databinding.FragmentTagsBinding
|
||||
import com.gh.gamecenter.entity.CategoryEntity
|
||||
import com.gh.gamecenter.feature.entity.GameEntity
|
||||
import com.gh.gamecenter.entity.SubjectSettingEntity
|
||||
import com.gh.gamecenter.eventbus.EBDownloadStatus
|
||||
import com.gh.gamecenter.eventbus.EBPackage
|
||||
import com.lightgame.download.DataWatcher
|
||||
import com.lightgame.download.DownloadEntity
|
||||
import org.greenrobot.eventbus.Subscribe
|
||||
import org.greenrobot.eventbus.ThreadMode
|
||||
|
||||
class NewCategoryListFragment : ListFragment<GameEntity, NewCategoryListViewModel>() {
|
||||
|
||||
private var mPrimeCategory: CategoryEntity? = null
|
||||
private var mSubCategoryList = arrayListOf<CategoryEntity>()
|
||||
private val mBinding by lazy { FragmentTagsBinding.inflate(layoutInflater) }
|
||||
|
||||
private var mAdapter: NewCategoryListAdapter? = null
|
||||
private val mDataWatcher = object : DataWatcher() {
|
||||
override fun onDataChanged(downloadEntity: DownloadEntity) {
|
||||
mAdapter?.notifyItemByDownload(downloadEntity)
|
||||
|
||||
if (downloadEntity.meta[XapkInstaller.XAPK_UNZIP_STATUS] == XapkUnzipStatus.FAILURE.name) {
|
||||
showUnzipFailureDialog(downloadEntity)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDataInit(downloadEntity: DownloadEntity) {
|
||||
mAdapter?.notifyItemByDownload(downloadEntity)
|
||||
}
|
||||
}
|
||||
|
||||
private lateinit var mExposureListener: ExposureListener
|
||||
private lateinit var mViewModel: NewCategoryListViewModel
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
mViewModel = provideListViewModel()
|
||||
|
||||
mViewModel.title = arguments?.getString(EntranceConsts.KEY_NAME) ?: ""
|
||||
mViewModel.categoryTitle = arguments?.getString(EntranceConsts.KEY_CATEGORY_TITLE) ?: ""
|
||||
mEntrance = arguments?.getString(EntranceConsts.KEY_ENTRANCE) ?: Constants.ENTRANCE_UNKNOWN
|
||||
mPrimeCategory = arguments?.getParcelable(EntranceConsts.KEY_DATA)
|
||||
mSubCategoryList = mPrimeCategory?.data as? ArrayList<CategoryEntity> ?: arrayListOf()
|
||||
|
||||
val initSelectedCategory = arguments?.getString(EntranceConsts.KEY_CATEGORY_INIT_TITLE)
|
||||
|
||||
mViewModel.selectedCategory =
|
||||
mSubCategoryList.find { categoryEntity -> categoryEntity.name == initSelectedCategory }
|
||||
?: CategoryEntity()
|
||||
|
||||
super.onCreate(savedInstanceState)
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
setNavigationTitle(mViewModel.title)
|
||||
|
||||
mViewModel.refresh.observeNonNull(this) { onRefresh() }
|
||||
|
||||
mBinding.configContainer.visibility = View.VISIBLE
|
||||
mBinding.configContainer.updateAllTextView(mViewModel.sortType)
|
||||
mBinding.configContainer.setOnConfigSetupListener(object : ConfigFilterView.OnConfigFilterSetupListener {
|
||||
override fun onShowSortSize() {}
|
||||
|
||||
override fun onSetupSortSize(sortSize: SubjectSettingEntity.Size) {
|
||||
mViewModel.updateSortConfig(sortSize = sortSize)
|
||||
}
|
||||
|
||||
override fun onSetupSortType(sortType: ConfigFilterView.SortType) {
|
||||
mViewModel.updateSortConfig(sortType = sortType)
|
||||
}
|
||||
})
|
||||
|
||||
mExposureListener = ExposureListener(this, mAdapter!!)
|
||||
mListRv.addOnScrollListener(mExposureListener)
|
||||
|
||||
updateCategoriesView(mSubCategoryList)
|
||||
|
||||
mSkeletonScreen =
|
||||
Skeleton.bind(mBinding.listSkeleton).shimmer(false).load(R.layout.fragment_subject_skeleton).show()
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
DownloadManager.getInstance().addObserver(mDataWatcher)
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
DownloadManager.getInstance().removeObserver(mDataWatcher)
|
||||
}
|
||||
|
||||
override fun getItemDecoration() = null
|
||||
|
||||
override fun getLayoutId() = 0
|
||||
|
||||
override fun getInflatedLayout() = mBinding.root
|
||||
|
||||
override fun provideListViewModel(): NewCategoryListViewModel {
|
||||
return viewModelProvider()
|
||||
}
|
||||
|
||||
override fun provideListAdapter(): ListAdapter<GameEntity> {
|
||||
return mAdapter
|
||||
?: NewCategoryListAdapter(requireContext(), mViewModel, mEntrance).apply { mAdapter = this }
|
||||
}
|
||||
|
||||
private fun updateCategoriesView(categoryList: ArrayList<CategoryEntity>) {
|
||||
mBinding.tagsRecyclerView.layoutManager =
|
||||
LinearLayoutManager(requireContext(), LinearLayoutManager.HORIZONTAL, false)
|
||||
mBinding.tagsRecyclerView.adapter = NewCategoryHorizontalAdapter(requireContext(), mViewModel, categoryList) {
|
||||
mBinding.tagsRecyclerView.smoothScrollToPosition(it)
|
||||
}
|
||||
|
||||
// 调整选中标签位置
|
||||
for (index in 0 until categoryList.size) {
|
||||
if (categoryList[index].name == mViewModel.selectedCategory.name) {
|
||||
mBinding.tagsRecyclerView.postDelayed({
|
||||
tryCatchInRelease { mBinding.tagsRecyclerView.smoothScrollToPosition(index) }
|
||||
}, 200)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onRefresh() {
|
||||
mAdapter?.clearPositionAndPackageMap()
|
||||
|
||||
super.onRefresh()
|
||||
}
|
||||
|
||||
// 下载被删除事件
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
fun onEventMainThread(status: EBDownloadStatus) {
|
||||
if ("delete" == status.status) {
|
||||
mAdapter?.notifyItemAndRemoveDownload(status)
|
||||
}
|
||||
}
|
||||
|
||||
// 安装/卸载 事件
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
fun onEventMainThread(busFour: EBPackage) {
|
||||
if (busFour.isInstalledOrUninstalled()) {
|
||||
mAdapter?.notifyDataSetChanged()
|
||||
}
|
||||
}
|
||||
|
||||
fun showUnzipFailureDialog(downloadEntity: DownloadEntity) {
|
||||
val data = mAdapter?.positionAndPackageMap ?: return
|
||||
for (gameAndPosition in data) {
|
||||
if (gameAndPosition.key.contains(downloadEntity.packageName)) {
|
||||
val targetView = mLayoutManager.findViewByPosition(gameAndPosition.value)
|
||||
if (targetView != null) {
|
||||
DialogUtils.showUnzipFailureDialog(requireContext(), downloadEntity)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDarkModeChanged() {
|
||||
super.onDarkModeChanged()
|
||||
mBinding.run {
|
||||
divider.setBackgroundColor(R.color.ui_background.toColor(requireContext()))
|
||||
tagsRecyclerView.setBackgroundColor(R.color.ui_surface.toColor(requireContext()))
|
||||
tagsRecyclerView.adapter?.run {
|
||||
notifyItemRangeChanged(0, itemCount)
|
||||
}
|
||||
configContainer.run {
|
||||
container.setBackgroundColor(R.color.ui_surface.toColor(requireContext()))
|
||||
updateAllTextView(mViewModel.sortType)
|
||||
updatePopupWindow()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,81 +0,0 @@
|
||||
package com.gh.gamecenter.category
|
||||
|
||||
import android.app.Application
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import com.gh.common.exposure.ExposureUtils
|
||||
import com.gh.gamecenter.core.utils.UrlFilterUtils
|
||||
import com.gh.common.view.ConfigFilterView
|
||||
import com.gh.gamecenter.common.baselist.ListViewModel
|
||||
import com.gh.gamecenter.entity.CategoryEntity
|
||||
import com.gh.gamecenter.feature.entity.GameEntity
|
||||
import com.gh.gamecenter.entity.SubjectSettingEntity
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager
|
||||
import io.reactivex.Observable
|
||||
import io.reactivex.Single
|
||||
|
||||
class NewCategoryListViewModel(application: Application) : ListViewModel<GameEntity, GameEntity>(application) {
|
||||
|
||||
var title = "" // 显示在 Toolbar 的标题
|
||||
var categoryTitle = "" // 跳转进来的分类的标题
|
||||
|
||||
val refresh = MutableLiveData<Boolean>()
|
||||
|
||||
var selectedCategory = CategoryEntity()
|
||||
|
||||
var sortType = ConfigFilterView.SortType.RECOMMENDED
|
||||
private var mSortSize = SubjectSettingEntity.Size()
|
||||
|
||||
override fun provideDataObservable(page: Int): Observable<List<GameEntity>>? {
|
||||
return null
|
||||
}
|
||||
|
||||
override fun provideDataSingle(page: Int): Single<List<GameEntity>> {
|
||||
return RetrofitManager.getInstance()
|
||||
.api
|
||||
.getGamesInCategory(selectedCategory.id, getSortType(), getSortSize(), page)
|
||||
}
|
||||
|
||||
override fun mergeResultLiveData() {
|
||||
mResultLiveData.addSource(mListLiveData) {
|
||||
ExposureUtils.updateExposureInfo(it)
|
||||
mResultLiveData.postValue(it)
|
||||
}
|
||||
}
|
||||
|
||||
fun changeSelectedCategory(category: CategoryEntity) {
|
||||
if (selectedCategory != category) {
|
||||
selectedCategory = category
|
||||
|
||||
refresh.postValue(true)
|
||||
}
|
||||
}
|
||||
|
||||
fun updateSortConfig(
|
||||
sortSize: SubjectSettingEntity.Size? = null,
|
||||
sortType: ConfigFilterView.SortType? = null
|
||||
) {
|
||||
if (sortSize != null && sortSize != mSortSize) {
|
||||
mSortSize = sortSize
|
||||
refresh.postValue(true)
|
||||
} else if (sortType != null && sortType != this.sortType) {
|
||||
this.sortType = sortType
|
||||
refresh.postValue(true)
|
||||
}
|
||||
}
|
||||
|
||||
private fun getSortSize(): String? {
|
||||
return UrlFilterUtils.getFilterQuery(
|
||||
"min_size", mSortSize.min.toString(),
|
||||
"max_size", mSortSize.max.toString()
|
||||
)
|
||||
}
|
||||
|
||||
fun getSortType(): String? {
|
||||
return if (sortType == ConfigFilterView.SortType.RECOMMENDED) {
|
||||
"download:-1"
|
||||
} else {
|
||||
"publish:-1"
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -63,9 +63,11 @@ class DiscoveryAdapter(
|
||||
itemData.interestCardLabels != null -> {
|
||||
ITEM_RECOMMEND_INTEREST
|
||||
}
|
||||
|
||||
itemData.interestImageCardLabel != null -> {
|
||||
ITEM_RECOMMEND_INTEREST_IMAGE
|
||||
}
|
||||
|
||||
else -> {
|
||||
ItemViewType.GAME_NORMAL
|
||||
}
|
||||
@ -90,18 +92,23 @@ class DiscoveryAdapter(
|
||||
ItemViewType.GAME_NORMAL -> {
|
||||
DiscoveryGameViewHolder(parent.toBinding())
|
||||
}
|
||||
|
||||
ItemViewType.ITEM_FOOTER -> {
|
||||
FooterViewHolder(mLayoutInflater.inflate(R.layout.refresh_footerview, parent, false))
|
||||
}
|
||||
|
||||
ITEM_DIRECT_GAME_BLOCK -> {
|
||||
DirectGameBlockViewHolder(parent.toBinding())
|
||||
}
|
||||
|
||||
ITEM_RECOMMEND_INTEREST -> {
|
||||
RecommendInterestViewHolder(parent.toBinding())
|
||||
}
|
||||
|
||||
ITEM_RECOMMEND_INTEREST_IMAGE -> {
|
||||
RecommendInterestImageViewHolder(parent.toBinding())
|
||||
}
|
||||
|
||||
else -> {
|
||||
throw NullPointerException()
|
||||
}
|
||||
@ -139,6 +146,12 @@ class DiscoveryAdapter(
|
||||
mExposureEventSparseArray.put(position, event)
|
||||
|
||||
holder.itemView.setOnClickListener {
|
||||
SensorsBridge.trackGameExploreClick(
|
||||
"游戏",
|
||||
"详情页",
|
||||
gameId = gameEntity.id,
|
||||
gameName = gameEntity.name ?: "",
|
||||
)
|
||||
GameDetailActivity.startGameDetailActivity(
|
||||
mContext,
|
||||
gameEntity,
|
||||
@ -159,8 +172,16 @@ class DiscoveryAdapter(
|
||||
StringUtils.buildString("(${mEntrance}", "-列表[", (position).toString(), "])"),
|
||||
location = StringUtils.buildString(mEntrance, ":", gameEntity.name),
|
||||
traceEvent = event
|
||||
)
|
||||
) {
|
||||
SensorsBridge.trackGameExploreClick(
|
||||
"按钮",
|
||||
"详情页",
|
||||
gameId = gameEntity.id,
|
||||
gameName = gameEntity.name ?: "",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
is RecommendInterestViewHolder -> {
|
||||
holder.binding.root.setBackgroundColor(R.color.ui_surface.toColor(mContext))
|
||||
holder.binding.backgroundView.background = R.drawable.bg_shape_space_radius_8.toDrawable(mContext)
|
||||
@ -175,24 +196,42 @@ class DiscoveryAdapter(
|
||||
labels[index].text = labels[index].linkText
|
||||
labelTv.text = labels[index].title
|
||||
labelTv.setOnClickListener {
|
||||
DirectUtils.directToLinkPage(holder.binding.root.context, labels[index], mEntrance, "")
|
||||
val link = labels[index]
|
||||
SensorsBridge.trackGameExploreClick(
|
||||
"内容标签",
|
||||
"详情页",
|
||||
linkType = link.type ?: "",
|
||||
linkId = link.link ?: "",
|
||||
linkText = link.text ?: "",
|
||||
buttonType = link.title ?: ""
|
||||
)
|
||||
DirectUtils.directToLinkPage(holder.binding.root.context, link, mEntrance, "")
|
||||
logDiscoverPageRecommendedInterestCardClick(
|
||||
mEntityList[position].cardPosition,
|
||||
labels[index]
|
||||
link
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
is RecommendInterestImageViewHolder -> {
|
||||
holder.binding.root.setBackgroundColor(R.color.ui_surface.toColor(mContext))
|
||||
val label = mEntityList[position].interestImageCardLabel ?: return
|
||||
label.text = label.linkText
|
||||
holder.binding.root.setOnClickListener {
|
||||
SensorsBridge.trackGameExploreClick(
|
||||
"内容标签",
|
||||
"详情页",
|
||||
linkType = label.type ?: "",
|
||||
linkId = label.link ?: "",
|
||||
linkText = label.text ?: "",
|
||||
)
|
||||
DirectUtils.directToLinkPage(holder.binding.root.context, label, mEntrance, "")
|
||||
logDiscoverPageRecommendedInterestCardClick(mEntityList[position].cardPosition, label)
|
||||
}
|
||||
}
|
||||
|
||||
is DirectGameBlockViewHolder -> {
|
||||
holder.binding.run {
|
||||
val userInterestedGame = Config.getUserInterestedGame()
|
||||
@ -202,6 +241,10 @@ class DiscoveryAdapter(
|
||||
interestedGameTv.goneIf(!userInterestedGame) {
|
||||
interestedGameTv.text = mContext.getString(R.string.interested_game_footer_hint).fromHtml()
|
||||
interestedGameTv.setOnClickListener {
|
||||
SensorsBridge.trackGameExploreClick(
|
||||
"偏好设置",
|
||||
"详情页",
|
||||
)
|
||||
mContext.ifLogin("发现页-底部") {
|
||||
mFragment.startActivityForResult(
|
||||
InterestedGameActivity.getIntent(
|
||||
@ -215,8 +258,23 @@ class DiscoveryAdapter(
|
||||
}
|
||||
}
|
||||
recommendIv.setOnClickListener {
|
||||
|
||||
val blockData = HomeBottomBarHelper.getDefaultGameBarData()
|
||||
mContext.startActivity(BlockActivity.getIntent(mContext, blockData, mBaseExposureSource, mEntrance))
|
||||
SensorsBridge.trackGameExploreClick(
|
||||
"内容标签",
|
||||
"详情页",
|
||||
linkType = blockData.type ?: "",
|
||||
linkId = blockData.link ?: "",
|
||||
linkText = blockData.text ?: ""
|
||||
)
|
||||
mContext.startActivity(
|
||||
BlockActivity.getIntent(
|
||||
mContext,
|
||||
blockData,
|
||||
mBaseExposureSource,
|
||||
mEntrance
|
||||
)
|
||||
)
|
||||
NewFlatLogUtils.logDiscoverPageJumpGamesLibraries()
|
||||
}
|
||||
}
|
||||
|
||||
@ -161,6 +161,7 @@ class DownloadFragment : BaseFragment_TabLayout() {
|
||||
val showOnFailed = downloadManagerAd?.displayRule?.onFailedAction == "show"
|
||||
if ((showThirdPartyAd && thirdPartyAd != null) || (!showThirdPartyAd && thirdPartyAd != null && ownerAd == null)) {
|
||||
initThirdPartyAd(thirdPartyAd) { isSuccess ->
|
||||
if (!isAdded) return@initThirdPartyAd
|
||||
mBinding.maskView.goneIf(!isSuccess)
|
||||
if (!isSuccess && ownerAd != null && showOnFailed) {
|
||||
mSlideInterval = ownerAd.adSource?.sliderInterval ?: -1
|
||||
@ -193,7 +194,7 @@ class DownloadFragment : BaseFragment_TabLayout() {
|
||||
}
|
||||
|
||||
private fun initOwnerAd(adConfig: AdConfig) {
|
||||
if (adConfig.id.isEmpty()) return
|
||||
if (!isAdded || adConfig.id.isEmpty()) return
|
||||
mAdGameViewModel = viewModelProvider(AdGameViewModel.Factory(adConfig))
|
||||
initAdGameBanner(adConfig)
|
||||
mBinding.closeAdIv.setOnClickListener {
|
||||
@ -227,6 +228,7 @@ class DownloadFragment : BaseFragment_TabLayout() {
|
||||
adConfig.displayRule.onFailedAction == "show" && adConfig.thirdPartyAd != null) {
|
||||
// 自有广告游戏为空时,显示第三方广告
|
||||
initThirdPartyAd(adConfig.thirdPartyAd) { isSuccess ->
|
||||
if (!isAdded) return@initThirdPartyAd
|
||||
mBinding.maskView.goneIf(!isSuccess)
|
||||
if (isSuccess) {
|
||||
SPUtils.setLong(Constants.SP_LAST_DOWNLOAD_MANAGER_AD_SHOW_TIME, System.currentTimeMillis())
|
||||
@ -273,7 +275,7 @@ class DownloadFragment : BaseFragment_TabLayout() {
|
||||
mDownloadManager.markDownloadedTaskAsRead()
|
||||
updateDownloadHint()
|
||||
}
|
||||
DownloadManager.getInstance().checkAndRetryDownload()
|
||||
DownloadManager.getInstance().checkAndRetryDownload(false)
|
||||
if (mBinding.adGameItemContainer.isVisible) {
|
||||
DownloadManager.getInstance().addObserver(mDataWatcher)
|
||||
}
|
||||
|
||||
@ -19,12 +19,13 @@ data class BottomTab(
|
||||
@DrawableRes
|
||||
val iconSelector: Int = 0, // 本地字段
|
||||
@SerializedName("js_code")
|
||||
val jsCode: String = "", // js代码
|
||||
var jsCode: String = "", // js代码
|
||||
val link: LinkEntity? = null, // 通用链接
|
||||
@SerializedName("search_style")
|
||||
val searchStyle: SearchStyle = SearchStyle(), // 搜索样式
|
||||
@SerializedName("is_default_page")
|
||||
var default: Boolean = false, // 是否为默认显示页
|
||||
var guide: Guide? = null, // 引导文案
|
||||
var isTransparentStyle: Boolean = false // 本地字段,透明底部Tab
|
||||
) : Parcelable {
|
||||
@Parcelize
|
||||
@ -43,6 +44,13 @@ data class BottomTab(
|
||||
}
|
||||
}
|
||||
|
||||
@Parcelize
|
||||
data class Guide(
|
||||
var bottomTabId: String = "", // 底部tab id
|
||||
var multiTabId: String = "", // 多tab导航页id
|
||||
var text: String = "",
|
||||
): Parcelable
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
if (javaClass != other?.javaClass) return false
|
||||
|
||||
@ -6,40 +6,6 @@ import com.gh.gamecenter.feature.entity.GameEntity
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import kotlinx.parcelize.Parcelize
|
||||
|
||||
@Parcelize
|
||||
data class CatalogEntity(
|
||||
@SerializedName("_id")
|
||||
var id: String = "",
|
||||
var name: String = "",
|
||||
var switch: CatalogSwitch = CatalogSwitch(),
|
||||
@SerializedName("has_special")
|
||||
var hasSpecial: Boolean = false,
|
||||
@SerializedName("sub_catalogs")
|
||||
var subCatalog: List<SubCatalogEntity> = emptyList()
|
||||
) : Parcelable {
|
||||
|
||||
@Parcelize
|
||||
data class SubCatalogEntity(
|
||||
@SerializedName("_id")
|
||||
var id: String = "",
|
||||
var name: String = "",
|
||||
var icon: String = "",
|
||||
var type: String = "",
|
||||
var link: LinkEntity = LinkEntity(),
|
||||
var recommended: Boolean = false
|
||||
) : Parcelable
|
||||
|
||||
@Parcelize
|
||||
data class CatalogSwitch(
|
||||
@SerializedName("sort_hot")
|
||||
var hotSort: String = "",
|
||||
@SerializedName("sort_new")
|
||||
var newSort: String = "",
|
||||
@SerializedName("sort_star")
|
||||
var starSort: String = ""
|
||||
) : Parcelable
|
||||
}
|
||||
|
||||
|
||||
@Parcelize
|
||||
class SpecialCatalogEntity(
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
package com.gh.gamecenter.entity
|
||||
|
||||
import android.os.Parcelable
|
||||
import com.gh.gamecenter.home.custom.model.CustomPageData
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import kotlinx.parcelize.Parcelize
|
||||
|
||||
@ -17,8 +18,14 @@ data class CommonCollectionEntity(
|
||||
@SerializedName("vertical_line")
|
||||
val verticalLine: String = "", // 竖排时才有数据,代表竖排行数控制
|
||||
@SerializedName("common_collection_content")
|
||||
val collectionList: MutableList<CommonCollectionContentEntity> = mutableListOf()
|
||||
val collectionList: MutableList<CommonCollectionContentEntity> = mutableListOf(),
|
||||
@SerializedName("common_collection_recommend_cards")
|
||||
private val _commonCollectionRecommendCards: List<CustomPageData.RecommendCard>? = null
|
||||
) {
|
||||
|
||||
val commonCollectionRecommendCards: List<CustomPageData.RecommendCard>
|
||||
get() = _commonCollectionRecommendCards ?: emptyList()
|
||||
|
||||
val layoutChinese: String
|
||||
get() = when (layout) {
|
||||
0 -> "轮播banner"
|
||||
@ -30,6 +37,10 @@ data class CommonCollectionEntity(
|
||||
6 -> "双列竖式卡片"
|
||||
7 -> "竖式图文列表"
|
||||
8 -> "横排图文列表"
|
||||
9 -> "内容标签泳道"
|
||||
10 -> "通知栏目"
|
||||
11 -> "公告横幅"
|
||||
12 -> "推荐卡片"
|
||||
else -> ""
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
package com.gh.gamecenter.entity
|
||||
|
||||
import android.graphics.Color
|
||||
import com.gh.gamecenter.common.entity.LinkEntity
|
||||
import com.gh.gamecenter.feature.entity.Time
|
||||
import com.google.gson.annotations.SerializedName
|
||||
@ -22,5 +23,87 @@ data class GameNavigationEntity(
|
||||
var hintStartTime: Long = 0,
|
||||
@SerializedName("hint_end_time")
|
||||
var hintEndTime: Long = 0,
|
||||
var time: Time? = null
|
||||
)
|
||||
var time: Time? = null,
|
||||
@SerializedName("entry_name_status")
|
||||
private val _entryNameStatus: String? = null,
|
||||
@SerializedName("guide")
|
||||
private val _guide: Guide? = null
|
||||
) {
|
||||
|
||||
val isShowEntryName: Boolean
|
||||
get() = ENTRY_NAME_STATUS_HIDE != _entryNameStatus
|
||||
|
||||
val isShowBubble: Boolean
|
||||
get() = _guide != null
|
||||
|
||||
val guide: Guide
|
||||
get() = _guide ?: Guide()
|
||||
|
||||
data class Guide(
|
||||
@SerializedName("text")
|
||||
private val _text: String? = null,
|
||||
@SerializedName("color")
|
||||
private val _color: String? = null
|
||||
) {
|
||||
|
||||
val text: String
|
||||
get() = _text ?: ""
|
||||
|
||||
val color: String
|
||||
get() = _color ?: ""
|
||||
|
||||
/**
|
||||
* 文字颜色 不透明度为 70%
|
||||
* 十六进制: B2
|
||||
* 十进制: 178
|
||||
*/
|
||||
val textColorInt: Int
|
||||
get() = parseColorWithAlpha(TEXT_ALPHA, color)
|
||||
|
||||
/**
|
||||
* 边框颜色 不透明度为 10%
|
||||
* 十六进制: 4D
|
||||
* 十进制: 77
|
||||
*/
|
||||
val borderColorInt: Int
|
||||
get() = parseColorWithAlpha(BORDER_ALPHA, color)
|
||||
|
||||
/**
|
||||
* 背景颜色 不透明度为 30%
|
||||
* 十六进制: 1A
|
||||
* 十进制: 26
|
||||
*/
|
||||
val backgroundColorInt: Int
|
||||
get() = parseColorWithAlpha(BACKGROUND_ALPHA, color)
|
||||
|
||||
|
||||
private fun parseColorWithAlpha(alpha: Int, color: String): Int {
|
||||
val colorInt = try {
|
||||
Color.parseColor(color)
|
||||
} catch (e: IllegalArgumentException) {
|
||||
// 解析失败,默认使用红色
|
||||
Color.RED
|
||||
}
|
||||
val hsv = FloatArray(3)
|
||||
Color.colorToHSV(colorInt, hsv)
|
||||
return Color.HSVToColor(alpha, hsv)
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val COLOR_BLUE = "blue"
|
||||
private const val COLOR_PURPLE = "purple"
|
||||
private const val COLOR_RED = "red"
|
||||
private const val COLOR_ORANGE = "orange"
|
||||
private const val COLOR_YELLOW = "yellow"
|
||||
private const val COLOR_GREEN = "green"
|
||||
|
||||
private const val TEXT_ALPHA = 178
|
||||
private const val BORDER_ALPHA = 77
|
||||
private const val BACKGROUND_ALPHA = 26
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val ENTRY_NAME_STATUS_HIDE = "hide"
|
||||
}
|
||||
}
|
||||
|
||||
@ -33,9 +33,9 @@ data class HomeItemTestV2Entity(
|
||||
val rightTop: RightTop = RightTop(),
|
||||
@SerializedName("start_id")
|
||||
val startId: String = "",
|
||||
@SerializedName("start_point")
|
||||
@SerializedName("recommend_data_point")
|
||||
private val _startPoint: Map<String, String> = mapOf(), // key 时间轴名称,value 当前时间轴第一个游戏id
|
||||
@SerializedName("data_count")
|
||||
@SerializedName("recommend_data_count")
|
||||
private val _dataCount: Map<String, Int> = mapOf(), //key 时间轴名称,value 当前时间轴所包含的游戏数量
|
||||
@SerializedName("time_type")
|
||||
val timeType: String = "",
|
||||
@ -51,13 +51,8 @@ data class HomeItemTestV2Entity(
|
||||
val dataCount: List<DataCount>
|
||||
get() {
|
||||
val dataCountList = arrayListOf<DataCount>()
|
||||
// 需要将 推荐 类型的数据放在第一位
|
||||
_dataCount.forEach { (key, value) ->
|
||||
if (timeType == TIME_TYPE_RECOMMEND && key == TIME_TYPE_RECOMMEND) {
|
||||
dataCountList.add(0, DataCount(key, value))
|
||||
} else {
|
||||
dataCountList.add(DataCount(key, value))
|
||||
}
|
||||
dataCountList.add(DataCount(key, value))
|
||||
}
|
||||
return dataCountList
|
||||
}
|
||||
@ -66,18 +61,10 @@ data class HomeItemTestV2Entity(
|
||||
get() {
|
||||
val startPointList = arrayListOf<StartPoint>()
|
||||
_startPoint.forEach { (key, value) ->
|
||||
if (timeType == TIME_TYPE_RECOMMEND && key == TIME_TYPE_RECOMMEND) {
|
||||
startPointList.add(0, StartPoint(key, value))
|
||||
} else {
|
||||
startPointList.add(StartPoint(key, value))
|
||||
}
|
||||
startPointList.add(StartPoint(key, value))
|
||||
}
|
||||
return startPointList
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val TIME_TYPE_RECOMMEND = "recommend"
|
||||
}
|
||||
}
|
||||
|
||||
@Keep
|
||||
|
||||
@ -20,7 +20,8 @@ data class HomeRecommend(
|
||||
private val _image: String? = null,
|
||||
@SerializedName("link_community")
|
||||
private val community: CommunityEntity? = null,
|
||||
|
||||
@SerializedName("guide")
|
||||
private val _guide: Guide? = null,
|
||||
// 绑定的曝光实体
|
||||
var exposureEvent: ExposureEvent? = null,
|
||||
) {
|
||||
@ -28,6 +29,12 @@ data class HomeRecommend(
|
||||
val image: String
|
||||
get() = _image ?: ""
|
||||
|
||||
val isShowGuide: Boolean
|
||||
get() = _guide != null
|
||||
|
||||
val guide: Guide
|
||||
get() = _guide ?: Guide()
|
||||
|
||||
fun transformLinkEntity(): LinkEntity {
|
||||
return LinkEntity(
|
||||
name = name,
|
||||
@ -38,4 +45,12 @@ data class HomeRecommend(
|
||||
community = community
|
||||
)
|
||||
}
|
||||
|
||||
data class Guide(
|
||||
@SerializedName("text")
|
||||
private val _text: String? = null
|
||||
) {
|
||||
val text: String
|
||||
get() = _text ?: ""
|
||||
}
|
||||
}
|
||||
@ -44,9 +44,12 @@ data class HomeSubSlide(
|
||||
data class CardData(
|
||||
var games: List<GameEntity> = arrayListOf(),
|
||||
@SerializedName("game_total")
|
||||
val gameTotal: GameTotal = GameTotal(),
|
||||
private val _gameTotal: GameTotal? = null,
|
||||
val stamp: String = ""
|
||||
)
|
||||
) {
|
||||
val gameTotal: GameTotal
|
||||
get() = _gameTotal ?: GameTotal()
|
||||
}
|
||||
|
||||
data class GameTotal(
|
||||
val vote: Int = 0,
|
||||
|
||||
@ -10,8 +10,12 @@ data class MultiTabNav(
|
||||
val id: String = "",
|
||||
val title: String = "",
|
||||
@SerializedName("link_multi_tab_nav")
|
||||
val linkMultiTabNav: List<LinkMultiTabNav> = ArrayList()
|
||||
private val _linkMultiTabNav: List<LinkMultiTabNav>?
|
||||
) {
|
||||
|
||||
val linkMultiTabNav:List<LinkMultiTabNav>
|
||||
get() = _linkMultiTabNav?: emptyList()
|
||||
|
||||
data class LinkMultiTabNav(
|
||||
@SerializedName("_id")
|
||||
val id: String = "",
|
||||
@ -22,6 +26,7 @@ data class MultiTabNav(
|
||||
@SerializedName("is_default_page")
|
||||
var default: Boolean = false, // 是否为默认显示页
|
||||
val link: LinkEntity? = null, // 通用链接
|
||||
var guide: BottomTab.Guide? = null, // 引导文案
|
||||
|
||||
// 本地字段
|
||||
var style: TabStyle = TabStyle(),
|
||||
|
||||
@ -21,8 +21,14 @@ class NewApiSettingsEntity(
|
||||
var install: Install, // 安装相关的
|
||||
@SerializedName("game_shield_contents")
|
||||
var gameShieldContents: List<String>? = listOf(),//游戏屏蔽内容
|
||||
var search: SettingsEntity.Search? = null// 游戏搜索配置
|
||||
var search: SettingsEntity.Search? = null,// 游戏搜索配置
|
||||
@SerializedName("jiguang_switch")
|
||||
private val _jiguangSwitch: Boolean? = null
|
||||
) {
|
||||
|
||||
val jiguangSwitch: Boolean
|
||||
get() = _jiguangSwitch ?: false
|
||||
|
||||
/**
|
||||
*
|
||||
* "icon": false, // 是否显示切换,true显示
|
||||
@ -37,7 +43,9 @@ class NewApiSettingsEntity(
|
||||
|
||||
class Install(
|
||||
@SerializedName("guides")
|
||||
val guides: List<Guide>? = null
|
||||
val guides: List<Guide>? = null,
|
||||
@SerializedName("question_tip")
|
||||
var questionTip: QuestionTip? = null // 厂商安装问题提示
|
||||
)
|
||||
|
||||
/**
|
||||
@ -82,4 +90,9 @@ class NewApiSettingsEntity(
|
||||
@SerializedName("REP")
|
||||
val rep: String
|
||||
)
|
||||
|
||||
class QuestionTip(
|
||||
@SerializedName("link")
|
||||
val linkEntity: LinkEntity? = null,
|
||||
)
|
||||
}
|
||||
@ -39,6 +39,8 @@ class ServerTestEntity(
|
||||
@SerializedName("time_type")
|
||||
val timeType: String,
|
||||
@SerializedName("games")
|
||||
var gameList: ArrayList<GameEntity> = arrayListOf()
|
||||
var gameList: ArrayList<GameEntity> = arrayListOf(),
|
||||
@SerializedName("put_away_games")
|
||||
var collapsedGameList: ArrayList<GameEntity> = arrayListOf(),
|
||||
)
|
||||
}
|
||||
@ -13,7 +13,32 @@ class StartupAdEntity(
|
||||
val img: String = "",
|
||||
// 显示规则: none无, each每一次打开, everyday每一天一次, once一次
|
||||
val rule: String = "",
|
||||
val time: TimeEntity? = null
|
||||
val time: TimeEntity? = null,
|
||||
@SerializedName("type")
|
||||
private val _type: String? = null,
|
||||
@SerializedName("video")
|
||||
private val _video: VideoEntity? = null,
|
||||
@SerializedName("display_interval")
|
||||
private val _displayInterval: Int? = null
|
||||
) {
|
||||
|
||||
// 默认为图片
|
||||
val type: String
|
||||
get() = _type ?: AD_TYPE_IMG
|
||||
|
||||
val isImageType: Boolean
|
||||
get() = type == AD_TYPE_IMG
|
||||
|
||||
val video: VideoEntity
|
||||
get() = _video ?: VideoEntity()
|
||||
|
||||
// 默认时长为 5s
|
||||
val displayInterval: Int
|
||||
get() = _displayInterval ?: 5
|
||||
|
||||
class TimeEntity(val start: Long = 0, val end: Long = 0)
|
||||
|
||||
companion object {
|
||||
private const val AD_TYPE_IMG = "img"
|
||||
}
|
||||
}
|
||||
@ -19,6 +19,8 @@ class SubjectData(
|
||||
var briefStyle: String = "",
|
||||
var subjectType: SubjectType = SubjectType.NORMAL,
|
||||
var subjectStyle: String = "",
|
||||
var showDetailSubtitle: Boolean = false,
|
||||
var showDetailIconSubscript: Boolean = false,
|
||||
|
||||
var requireUpdateSetting: Boolean = false, // 多专题页面需要专题页面自行获取专题配置
|
||||
var isAdData: Boolean = false,
|
||||
|
||||
@ -4,6 +4,7 @@ import android.os.Parcelable
|
||||
import com.gh.common.filter.RegionSettingHelper
|
||||
import com.gh.gamecenter.common.entity.LinkEntity
|
||||
import com.gh.gamecenter.feature.entity.GameEntity
|
||||
import com.gh.gamecenter.feature.entity.WelfareInfo
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import kotlinx.parcelize.IgnoredOnParcel
|
||||
import kotlinx.parcelize.Parcelize
|
||||
@ -106,7 +107,15 @@ data class SubjectEntity(
|
||||
var explain: String = "", // 游戏单合集说明
|
||||
|
||||
@SerializedName("show_star")
|
||||
private val _showStar: Boolean? = null
|
||||
private val _showStar: Boolean? = null,
|
||||
@SerializedName("home_text")
|
||||
val homeText: String? = null,
|
||||
@SerializedName("show_index_subtitle")
|
||||
val showIndexSubtitle: Boolean = false,
|
||||
@SerializedName("show_index_icon_subscript")
|
||||
val showIndexIconSubscript: Boolean = false,
|
||||
@SerializedName("welfare_info")
|
||||
val welfareInfo: WelfareInfo? = null
|
||||
) : Parcelable {
|
||||
|
||||
@IgnoredOnParcel
|
||||
|
||||
@ -73,8 +73,6 @@ data class SubjectRecommendEntity(
|
||||
"column" -> "专题"
|
||||
"column_collection" -> "专题合集"
|
||||
"block" -> "版块"
|
||||
"category" -> "分类"
|
||||
"catalog" -> "新分类"
|
||||
"category_v2" -> "新分类2.0"
|
||||
"column_test" -> "开测表"
|
||||
"server" -> "开服表"
|
||||
|
||||
@ -28,7 +28,18 @@ class SubjectSettingEntity(
|
||||
var adIconActive: Boolean = false,
|
||||
@SerializedName("column_style")
|
||||
var columnStyle: String = "", // 对应自定义页面的专题样式
|
||||
@SerializedName("show_detail_subtitle")
|
||||
private val _showDetailSubtitle: Boolean? = null,
|
||||
@SerializedName("show_detail_icon_subscript")
|
||||
private val _showDetailIconSubscript: Boolean? = null
|
||||
) : Parcelable {
|
||||
|
||||
val showDetailSubtitle: Boolean
|
||||
get() = _showDetailSubtitle ?: false
|
||||
|
||||
val showDetailIconSubscript: Boolean
|
||||
get() = _showDetailIconSubscript ?: false
|
||||
|
||||
@Parcelize
|
||||
class TypeEntity(
|
||||
var content: MutableList<String> = ArrayList(), // top/tile
|
||||
|
||||
@ -63,6 +63,7 @@ class FollowHomeSlideListViewHolder(
|
||||
val slideList = data.linkCommonCollection.slides.slide
|
||||
|
||||
slideListUi.bind(slideList, bindingAdapterPosition + 1)
|
||||
slideListUi.updateWhenTopVisibleItemCountChanged(false)
|
||||
|
||||
itemView.setBackgroundColor(R.color.ui_surface.toColor(itemView.context))
|
||||
|
||||
|
||||
@ -74,6 +74,7 @@ class FollowHomeSlideWithCardsViewHolder(
|
||||
fun bindView(data: FollowCommonContentCollection) {
|
||||
this.data = data
|
||||
slideWithCardsUi.bind(data.linkCommonCollection, bindingAdapterPosition + 1)
|
||||
slideWithCardsUi.updateWhenTopVisibleItemCountChanged(false)
|
||||
itemView.setBackgroundColor(R.color.ui_surface.toColor(itemView.context))
|
||||
}
|
||||
|
||||
|
||||
@ -11,8 +11,6 @@ import androidx.fragment.app.Fragment
|
||||
import androidx.viewpager.widget.ViewPager
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.amway.AmwayFragment
|
||||
import com.gh.gamecenter.catalog.CatalogFragment
|
||||
import com.gh.gamecenter.category.CategoryDirectoryFragment
|
||||
import com.gh.gamecenter.category2.CategoryV2Fragment
|
||||
import com.gh.gamecenter.common.base.adapter.FragmentAdapter
|
||||
import com.gh.gamecenter.common.constant.EntranceConsts
|
||||
@ -159,16 +157,6 @@ abstract class HomeTabWrapperFragment : SearchToolWrapperFragment() {
|
||||
putString(GameServersTestFragment.TEST_COLUMN_ID, tabEntity.link)
|
||||
})
|
||||
|
||||
"category" -> CategoryDirectoryFragment().with(Bundle().apply {
|
||||
putString(EntranceConsts.KEY_CATEGORY_ID, tabEntity.link)
|
||||
putString(EntranceConsts.KEY_CATEGORY_TITLE, tabEntity.text)
|
||||
})
|
||||
|
||||
"catalog" -> CatalogFragment().with(Bundle().apply {
|
||||
putString(EntranceConsts.KEY_CATALOG_ID, tabEntity.link)
|
||||
putString(EntranceConsts.KEY_CATALOG_TITLE, tabEntity.text)
|
||||
})
|
||||
|
||||
"category_v2" -> CategoryV2Fragment().with(Bundle().apply {
|
||||
putString(EntranceConsts.KEY_CATEGORY_ID, tabEntity.link)
|
||||
putString(EntranceConsts.KEY_CATEGORY_TITLE, tabEntity.text)
|
||||
@ -224,6 +212,7 @@ abstract class HomeTabWrapperFragment : SearchToolWrapperFragment() {
|
||||
})
|
||||
|
||||
"column_test_v2" -> GameServerTestV2Fragment().with(Bundle().apply {
|
||||
putString(EntranceConsts.KEY_ID, tabEntity.link)
|
||||
putString(EntranceConsts.KEY_ENTRANCE, entrance)
|
||||
putInt(EntranceConsts.KEY_POSITION, index)
|
||||
putParcelable(
|
||||
|
||||
@ -26,7 +26,6 @@ import com.gh.gamecenter.adapter.viewholder.GameHeadViewHolder
|
||||
import com.gh.gamecenter.adapter.viewholder.GameImageViewHolder
|
||||
import com.gh.gamecenter.adapter.viewholder.GameViewHolder
|
||||
import com.gh.gamecenter.adapter.viewholder.GameViewPagerViewHolder
|
||||
import com.gh.gamecenter.category.CategoryDirectoryActivity
|
||||
import com.gh.gamecenter.common.baselist.LoadStatus
|
||||
import com.gh.gamecenter.common.callback.OnViewClickListener
|
||||
import com.gh.gamecenter.common.constant.EntranceConsts
|
||||
@ -54,6 +53,7 @@ import com.gh.gamecenter.feature.entity.GameEntity
|
||||
import com.gh.gamecenter.feature.exposure.ExposureEvent
|
||||
import com.gh.gamecenter.feature.exposure.ExposureType
|
||||
import com.gh.gamecenter.feature.game.GameItemViewHolder
|
||||
import com.gh.gamecenter.feature.minigame.MiniGameItemHelper
|
||||
import com.gh.gamecenter.game.bigimagerecommend.BigImageRecommendViewHolder
|
||||
import com.gh.gamecenter.game.columncollection.GameColumnCollectionViewHolder
|
||||
import com.gh.gamecenter.game.commoncollection.CommonCollection12ViewHolder
|
||||
@ -90,7 +90,6 @@ import com.gh.gamecenter.home.test_v2.HomeGameTestV2GameListRvAdapter
|
||||
import com.gh.gamecenter.home.test_v2.HomeGameTestV2ViewModel
|
||||
import com.gh.gamecenter.home.test_v2.HomeItemGameTestV2ViewHolder
|
||||
import com.gh.gamecenter.home.video.ScrollCalculatorHelper
|
||||
import com.gh.gamecenter.feature.minigame.MiniGameItemHelper
|
||||
import com.gh.gamecenter.minigame.qq.QGameRecentlyPlayViewHolder
|
||||
import com.gh.gamecenter.servers.gametest2.GameServerTestV2Activity
|
||||
import com.gh.gamecenter.subject.SubjectActivity
|
||||
@ -177,6 +176,20 @@ class GameFragmentAdapter(
|
||||
return ItemViewType.LOADING
|
||||
}
|
||||
|
||||
override fun onViewAttachedToWindow(holder: ViewHolder) {
|
||||
super.onViewAttachedToWindow(holder)
|
||||
if (holder is QGameRecentlyPlayViewHolder) {
|
||||
holder.onAttached()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onViewDetachedFromWindow(holder: ViewHolder) {
|
||||
super.onViewDetachedFromWindow(holder)
|
||||
if (holder is QGameRecentlyPlayViewHolder) {
|
||||
holder.onDetached()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
||||
return when (viewType) {
|
||||
// 轮播图+导航栏+专题入口
|
||||
@ -195,7 +208,7 @@ class GameFragmentAdapter(
|
||||
ItemViewType.GAME_SUBJECT -> GameHorizontalListViewHolder(parent.toBinding())
|
||||
// 游戏专题-横屏滑动
|
||||
ItemViewType.GAME_SUBJECT_SLIDE -> GameHorizontalSlideListViewHolder(parent.toBinding())
|
||||
ItemViewType.QQ_GAME_SUBJECT_SLIDE -> QGameRecentlyPlayViewHolder(parent.toBinding())
|
||||
ItemViewType.QQ_GAME_SUBJECT_SLIDE -> QGameRecentlyPlayViewHolder(mLifecycleOwner, parent.toBinding())
|
||||
// 正常游戏
|
||||
ItemViewType.GAME_NORMAL -> GameItemViewHolder(parent.toBinding())
|
||||
// 游戏专题-大图-显示/只显示
|
||||
@ -966,14 +979,6 @@ class GameFragmentAdapter(
|
||||
)
|
||||
)
|
||||
|
||||
"category" -> mContext.startActivity(
|
||||
CategoryDirectoryActivity.getIntent(
|
||||
mContext,
|
||||
entity.link!!,
|
||||
entity.text!!
|
||||
)
|
||||
)
|
||||
|
||||
"column" -> {
|
||||
SubjectActivity.startSubjectActivity(
|
||||
mContext,
|
||||
@ -1515,7 +1520,7 @@ class GameFragmentAdapter(
|
||||
if (text == "全部") {
|
||||
NewFlatLogUtils.logGameTestV2MoreClick(text, location)
|
||||
//点击进入[新游开测]详情页面
|
||||
mContext.startActivity(GameServerTestV2Activity.getIntent(mContext, "新游开测"))
|
||||
mContext.startActivity(GameServerTestV2Activity.getIntent(mContext, "none", "新游开测"))
|
||||
} else {
|
||||
//点击跳转通用链接
|
||||
if (link != null) {
|
||||
|
||||
@ -2,8 +2,8 @@ package com.gh.gamecenter.game.columncollection.detail
|
||||
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import com.gh.gamecenter.common.base.activity.ToolBarActivity
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.base.activity.ToolBarActivity
|
||||
import com.gh.gamecenter.common.constant.EntranceConsts
|
||||
import com.gh.gamecenter.common.utils.updateStatusBarColor
|
||||
|
||||
@ -34,8 +34,8 @@ class ColumnCollectionDetailActivity : ToolBarActivity() {
|
||||
}
|
||||
|
||||
override fun getBusinessId(): Pair<String, String> {
|
||||
val fragment = targetFragment as ColumnCollectionDetailFragment
|
||||
return if (fragment.arguments != null) {
|
||||
val fragment = targetFragment as? ColumnCollectionDetailFragment?
|
||||
return if (fragment?.arguments != null) {
|
||||
Pair(fragment.requireArguments().getString(EntranceConsts.KEY_COLLECTION_ID) ?: "", "")
|
||||
} else {
|
||||
super.getBusinessId()
|
||||
|
||||
@ -14,6 +14,11 @@ import com.gh.gamecenter.common.utils.updateStatusBarColor
|
||||
*/
|
||||
class CommonCollectionDetailActivity : ToolBarActivity() {
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
updateStatusBarColor(R.color.ui_surface, R.color.ui_surface)
|
||||
}
|
||||
|
||||
override fun provideNormalIntent(): Intent {
|
||||
return getTargetIntent(
|
||||
this,
|
||||
@ -31,8 +36,8 @@ class CommonCollectionDetailActivity : ToolBarActivity() {
|
||||
}
|
||||
|
||||
override fun getBusinessId(): Pair<String, String> {
|
||||
val fragment = targetFragment as CommonCollectionDetailFragment
|
||||
return if (fragment.arguments != null) {
|
||||
val fragment = targetFragment as? CommonCollectionDetailFragment?
|
||||
return if (fragment?.arguments != null) {
|
||||
Pair(
|
||||
fragment.requireArguments().getString(EntranceConsts.KEY_COLLECTION_ID) ?: "",
|
||||
fragment.requireArguments().getString(EntranceConsts.KEY_BLOCK_ID) ?: ""
|
||||
|
||||
@ -14,6 +14,11 @@ import com.gh.gamecenter.common.utils.updateStatusBarColor
|
||||
*/
|
||||
class CustomCommonCollectionDetailActivity : ToolBarActivity() {
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
updateStatusBarColor(R.color.ui_surface, R.color.ui_surface)
|
||||
}
|
||||
|
||||
override fun provideNormalIntent(): Intent {
|
||||
return getTargetIntent(
|
||||
this,
|
||||
@ -31,8 +36,8 @@ class CustomCommonCollectionDetailActivity : ToolBarActivity() {
|
||||
}
|
||||
|
||||
override fun getBusinessId(): Pair<String, String> {
|
||||
val fragment = targetFragment as CustomCommonCollectionDetailFragment
|
||||
return if (fragment.arguments != null) {
|
||||
val fragment = targetFragment as? CustomCommonCollectionDetailFragment?
|
||||
return if (fragment?.arguments != null) {
|
||||
Pair(
|
||||
fragment.requireArguments().getString(EntranceConsts.KEY_COLLECTION_ID) ?: "",
|
||||
fragment.requireArguments().getString(EntranceConsts.KEY_BLOCK_ID) ?: ""
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user