Compare commits
163 Commits
delete
...
v5.28.2-91
| Author | SHA1 | Date | |
|---|---|---|---|
| 42d5d46e53 | |||
| cdccc35703 | |||
| d3e2fea019 | |||
| f343841233 | |||
| f62083eff2 | |||
| 8594e998c2 | |||
| 6865706b0f | |||
| b6d8ca4d84 | |||
| 455e1f0432 | |||
| 15276cc4b3 | |||
| 130a7cdf2a | |||
| 164ec0c368 | |||
| 991bd22511 | |||
| df1ab5221d | |||
| 226d6c4f2c | |||
| 896adc9d36 | |||
| 0e33abebdd | |||
| c8ed126605 | |||
| b510a329b6 | |||
| 2de1ba4e1d | |||
| e4a0f0e68b | |||
| c064f9d3a6 | |||
| 759401d9ae | |||
| e56209d15e | |||
| c466ff1f21 | |||
| e09cf299f0 | |||
| 25352ba609 | |||
| 3cd065cb6e | |||
| 919a98ffe6 | |||
| eff84218a8 | |||
| 7c9c363422 | |||
| 8b1a38214c | |||
| 2acde0af00 | |||
| 201c1207f9 | |||
| 75d86b5a91 | |||
| 7976355e34 | |||
| a9097793ac | |||
| 86e4ddd3f7 | |||
| 8312d8e5fe | |||
| 98b4901d55 | |||
| 8555673d71 | |||
| cfe4c243e6 | |||
| c999ddf914 | |||
| f9004bf884 | |||
| 7794ef4acf | |||
| 1ef9c1fc23 | |||
| 2561767b9a | |||
| 8bda0e178e | |||
| 1dcc7654e8 | |||
| 3579b9d808 | |||
| c74663c082 | |||
| 848d352c60 | |||
| 5176766b29 | |||
| 12cb9a4883 | |||
| a30cc8c273 | |||
| 0f0620586b | |||
| b9e86dd67a | |||
| 9ce793d47e | |||
| 43cb18d6e0 | |||
| 843aa4d1c8 | |||
| 1745ac91b7 | |||
| 20bc4a0dc8 | |||
| 1105f1b92a | |||
| 53f00f00d3 | |||
| 330bcd72d7 | |||
| b04231772b | |||
| ec1bbdc7d5 | |||
| c685a02653 | |||
| 6594bf14df | |||
| 655380d547 | |||
| da3948228f | |||
| 5c03119c32 | |||
| 2a496b680b | |||
| db535cf281 | |||
| c199582efc | |||
| b53677a118 | |||
| 043f3c5d17 | |||
| 68006dda38 | |||
| b5cab193be | |||
| 6f2692296c | |||
| 0bb7a53046 | |||
| 25fe362912 | |||
| 6749d94c34 | |||
| 51f5ea1cd9 | |||
| 50a6d5e204 | |||
| 044e5646ec | |||
| 0ebf3d191d | |||
| bb81d91fd5 | |||
| 7442da80e0 | |||
| 96c28907ec | |||
| e9e7c2043e | |||
| eb5c55f046 | |||
| 8f2a1ecaa1 | |||
| 8dbe9c5772 | |||
| 6c911e09d3 | |||
| df557099ec | |||
| fedc91d37e | |||
| 27484a8306 | |||
| 42193d222a | |||
| ff02ccd839 | |||
| d1cc0853d4 | |||
| 51eb814a42 | |||
| 6534c17cc0 | |||
| 749a76a09e | |||
| 0f59f79495 | |||
| af66a967b5 | |||
| 9a9095bcf0 | |||
| 225f2becf3 | |||
| a502fb64cb | |||
| 724fe8142c | |||
| dee5a0822d | |||
| e826346ca9 | |||
| 06b43cde77 | |||
| ae5edad87b | |||
| c8916f5f33 | |||
| 04cca95435 | |||
| 1bd3d8b044 | |||
| 4e79466cca | |||
| 88093d0a8e | |||
| 26adcc48f8 | |||
| e94e86d901 | |||
| 73355a4103 | |||
| 794377fdad | |||
| 1bff098369 | |||
| 45c7638dee | |||
| 4c57092300 | |||
| 1ddf9a667e | |||
| 84972e7ba7 | |||
| 03692ad753 | |||
| bb138fa25f | |||
| c5024e670a | |||
| fe5c92e988 | |||
| 9b31bf4164 | |||
| c670ab722f | |||
| fd4f3c25e7 | |||
| a14ea3708a | |||
| c003240f16 | |||
| 891e3d93fb | |||
| af5ec74b9e | |||
| d2c4483455 | |||
| 3a156aa8c1 | |||
| 60bd3ee9b2 | |||
| dacda1a858 | |||
| 265b5f6b57 | |||
| b4bd6f250b | |||
| 0f3ae5f085 | |||
| 3ab6cc202e | |||
| 7a154bc130 | |||
| 7cd6f2b0f4 | |||
| 8db2519f61 | |||
| 6b2902a73b | |||
| df7618bbda | |||
| 246983a097 | |||
| ca6146ad9a | |||
| c647320abc | |||
| afd738454e | |||
| 134cb327ec | |||
| f50ce741ae | |||
| 4547ba969e | |||
| 0a4af78ac8 | |||
| d38e1d1637 | |||
| 0d3456cf97 | |||
| f56529aa5b |
@ -71,8 +71,7 @@ android_build:
|
||||
exit_codes: 137
|
||||
only:
|
||||
- dev
|
||||
- dev-5.26.0
|
||||
- dev-5.27.0
|
||||
- dev-5.28.0
|
||||
|
||||
# 代码检查
|
||||
sonarqube_analysis:
|
||||
@ -103,8 +102,7 @@ sonarqube_analysis:
|
||||
exit_codes: 137
|
||||
only:
|
||||
- dev
|
||||
- dev-5.26.0
|
||||
- dev-5.27.0
|
||||
- dev-5.28.0
|
||||
|
||||
## 发送简易检测结果报告
|
||||
send_sonar_report:
|
||||
@ -122,8 +120,7 @@ send_sonar_report:
|
||||
exit_codes: 137
|
||||
only:
|
||||
- dev
|
||||
- dev-5.26.0
|
||||
- dev-5.27.0
|
||||
- dev-5.28.0
|
||||
|
||||
oss-upload&send-email:
|
||||
tags:
|
||||
@ -155,5 +152,4 @@ oss-upload&send-email:
|
||||
- /usr/local/bin/python /ci-android-mail.py
|
||||
only:
|
||||
- dev
|
||||
- dev-5.26.0
|
||||
- dev-5.27.0
|
||||
- dev-5.28.0
|
||||
@ -11,7 +11,7 @@ android {
|
||||
|
||||
String CONFIG_ID = ""
|
||||
String FIRST_LAUNCH = ""
|
||||
int ACTIVATE_REPORTING_RATIO = 0
|
||||
int ACTIVATE_REPORTING_RATIO = 100
|
||||
|
||||
buildFeatures {
|
||||
viewBinding true
|
||||
@ -71,6 +71,11 @@ android {
|
||||
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt', 'proguard-fresco.txt'
|
||||
|
||||
String CORE_EVENT_GAME_CATEGORY = ""
|
||||
|
||||
// 推广用的关键事件游戏类型
|
||||
buildConfigField "String", "CORE_EVENT_GAME_CATEGORY", "\"${CORE_EVENT_GAME_CATEGORY}\""
|
||||
|
||||
// 推广用的配置 id
|
||||
buildConfigField "String", "CONFIG_ID", "\"${CONFIG_ID}\""
|
||||
|
||||
@ -334,6 +339,7 @@ dependencies {
|
||||
implementation(project(':feature:oaid'))
|
||||
implementation(project(':feature:floating-window'))
|
||||
implementation(project(':feature:beizi_startup_ad'))
|
||||
implementation(project(':feature:xapk-installer'))
|
||||
}
|
||||
|
||||
File propFile = file('sign.properties')
|
||||
|
||||
@ -33,4 +33,8 @@ class FlavorProviderImp : IFlavorProvider {
|
||||
override fun logEvent(content: String) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
override fun logCoreEvent() {
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
@ -42,6 +42,10 @@ class FlavorProviderImp : IFlavorProvider {
|
||||
GdtHelper.logAction(content)
|
||||
}
|
||||
|
||||
override fun logCoreEvent() {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val GDT_DEFAULT_CHANNEL = "GDT_GHZS_01"
|
||||
}
|
||||
|
||||
@ -3,10 +3,13 @@ package com.gh.gamecenter.provider
|
||||
import android.app.Activity
|
||||
import android.app.Application
|
||||
import android.text.TextUtils
|
||||
import com.gh.gamecenter.BuildConfig
|
||||
import com.gh.gamecenter.KuaishouHelper
|
||||
import com.gh.gamecenter.core.AppExecutor
|
||||
import com.gh.gamecenter.core.provider.IFlavorProvider
|
||||
import com.gh.gamecenter.core.utils.SPUtils
|
||||
import com.gh.gamecenter.core.utils.TimeUtils
|
||||
import com.gh.gamecenter.core.utils.ToastUtils
|
||||
import com.halo.assistant.HaloApp
|
||||
import com.kwai.monitor.payload.TurboHelper
|
||||
|
||||
@ -42,6 +45,15 @@ class FlavorProviderImp : IFlavorProvider {
|
||||
KuaishouHelper.onEvent(content)
|
||||
}
|
||||
|
||||
override fun logCoreEvent() {
|
||||
logEvent("EVENT_KEY_PATH_OPTIMIZATION")
|
||||
if (BuildConfig.ACTIVATE_REPORTING_RATIO == 1) {
|
||||
AppExecutor.uiExecutor.executeWithDelay({
|
||||
ToastUtils.toast("关键行为 EVENT_KEY_PATH_OPTIMIZATION")
|
||||
}, 500)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val KUAISHOU_CHANNEL = "KS-GHZS-01"
|
||||
}
|
||||
|
||||
@ -106,8 +106,8 @@
|
||||
android:icon="@mipmap/logo"
|
||||
android:label="@string/app_name"
|
||||
android:largeHeap="true"
|
||||
android:resizeableActivity="true"
|
||||
android:networkSecurityConfig="@xml/network_security_config"
|
||||
android:resizeableActivity="true"
|
||||
android:theme="@style/AppCompatTheme.APP"
|
||||
tools:replace="android:name,android:allowBackup"
|
||||
tools:targetApi="n">
|
||||
@ -756,6 +756,10 @@
|
||||
android:name=".servers.gametest2.GameServerTestV2Activity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.gamecollection.hotlist.GameCollectionHotListActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
|
||||
<!-- <activity-->
|
||||
<!-- android:name="${applicationId}.douyinapi.DouYinEntryActivity"-->
|
||||
@ -826,6 +830,11 @@
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
|
||||
<activity
|
||||
android:name="com.gh.common.xapk.XapkInstallReceiver"
|
||||
android:theme="@style/Theme.Transparent"
|
||||
android:exported="false" />
|
||||
|
||||
<receiver
|
||||
android:name="com.gh.gamecenter.receiver.ActivitySkipReceiver"
|
||||
android:exported="true">
|
||||
|
||||
1
app/src/main/assets/lottie/icon_fab_change.json
Normal file
1
app/src/main/assets/lottie/icon_fab_change.json
Normal file
@ -0,0 +1 @@
|
||||
{"v":"5.9.1","fr":60,"ip":0,"op":60,"w":144,"h":144,"nm":"icon_change","ddd":0,"assets":[{"id":"comp_0","nm":"icon_change_detail","fr":60,"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"stroke1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[37.04,52.994,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-0.533,-0.143],[0.143,-0.533],[1.487,-1.304],[1.961,-0.258],[1.774,0.875],[0.709,0.661],[0,0],[0,0.445],[0,0],[-0.276,0],[0,0],[-0.013,0],[0,0],[0.315,-0.315],[0,0],[-0.682,-0.336],[-1.569,0.207],[-1.19,1.043],[-0.41,1.528]],"o":[[0.533,0.143],[-0.512,1.91],[-1.487,1.304],[-1.961,0.258],[-0.879,-0.433],[0,0],[-0.315,0.315],[0,0],[0,-0.276],[0,0],[0.013,0],[0,0],[0.445,0],[0,0],[0.555,0.508],[1.419,0.7],[1.569,-0.207],[1.19,-1.043],[0.143,-0.533]],"v":[[8.605,-4.301],[9.312,-3.076],[6.247,1.854],[0.958,4.25],[-4.77,3.304],[-7.163,1.652],[-8.493,2.982],[-9.347,2.628],[-9.347,-1.665],[-8.847,-2.165],[-8.161,-2.165],[-8.122,-2.165],[-4.554,-2.165],[-4.2,-1.311],[-5.748,0.237],[-3.885,1.51],[0.697,2.267],[4.928,0.35],[7.381,-3.594]],"c":true},"ix":2},"nm":"stroke1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"gf","o":{"a":0,"k":100,"ix":10},"r":1,"bm":0,"g":{"p":3,"k":{"a":0,"k":[0,1,1,1,0.5,1,1,1,1,1,1,1,0,1,0.5,0.8,1,0.6],"ix":9}},"s":{"a":0,"k":[-5.347,-4.665],"ix":5},"e":{"a":0,"k":[8.653,-4.665],"ix":6},"t":1,"nm":"color1","mn":"ADBE Vector Graphic - G-Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[300,300],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"stroke1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":300,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"stroke2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[34.96,19.006,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-1.961,0.258],[-1.774,-0.875],[-0.709,-0.661],[0,0],[0,-0.445],[0,0],[0.276,0],[0,0],[0.012,0],[0,0],[-0.315,0.315],[0,0],[0.682,0.336],[1.569,-0.207],[1.19,-1.043],[0.41,-1.528],[0.533,0.143],[-0.143,0.533],[-1.487,1.304]],"o":[[1.961,-0.258],[0.879,0.433],[0,0],[0.315,-0.315],[0,0],[0,0.276],[0,0],[-0.012,0],[0,0],[-0.445,0],[0,0],[-0.555,-0.508],[-1.419,-0.7],[-1.569,0.207],[-1.19,1.043],[-0.143,0.533],[-0.533,-0.143],[0.512,-1.91],[1.487,-1.304]],"v":[[-0.958,-4.25],[4.77,-3.304],[7.163,-1.652],[8.493,-2.982],[9.347,-2.628],[9.347,1.665],[8.847,2.165],[8.16,2.165],[8.123,2.165],[4.554,2.165],[4.2,1.311],[5.748,-0.237],[3.885,-1.51],[-0.697,-2.267],[-4.928,-0.35],[-7.381,3.594],[-8.605,4.301],[-9.312,3.076],[-6.247,-1.854]],"c":true},"ix":2},"nm":"stroke2","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"gf","o":{"a":0,"k":100,"ix":10},"r":1,"bm":0,"g":{"p":3,"k":{"a":0,"k":[0,1,1,1,0.5,1,1,1,1,1,1,1,0,1,0.5,0.8,1,0.6],"ix":9}},"s":{"a":0,"k":[5.347,4.665],"ix":5},"e":{"a":0,"k":[-8.653,4.665],"ix":6},"t":1,"nm":"color2","mn":"ADBE Vector Graphic - G-Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[300,300],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"stroke2","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":300,"st":0,"bm":0}]}],"layers":[{"ddd":0,"ind":1,"ty":0,"nm":"icon_change_detail","refId":"comp_0","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.5],"y":[1]},"o":{"x":[0.5],"y":[0]},"t":0,"s":[0]},{"t":36,"s":[360]}],"ix":10},"p":{"a":0,"k":[72,72,0],"ix":2,"l":2},"a":{"a":0,"k":[36,36,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"w":72,"h":72,"ip":0,"op":300,"st":0,"bm":0}],"markers":[]}
|
||||
@ -5,6 +5,7 @@ import android.app.Application
|
||||
import android.os.Bundle
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import com.gh.common.util.FloatingBackViewManager
|
||||
import com.gh.common.xapk.XapkInstaller
|
||||
import com.gh.download.DownloadManager
|
||||
import com.gh.gamecenter.SingletonWebActivity
|
||||
import com.gh.gamecenter.SkipActivity
|
||||
@ -61,6 +62,8 @@ class GlobalActivityLifecycleObserver : Application.ActivityLifecycleCallbacks {
|
||||
) {
|
||||
VHelper.showFeedbackDialogIfLastSuccessfulLaunchedGameExitUnexpectedly(activity)
|
||||
}
|
||||
|
||||
XapkInstaller.updateCurrentInstallStatus()
|
||||
}
|
||||
|
||||
override fun onActivityPaused(activity: Activity) {
|
||||
|
||||
@ -213,7 +213,7 @@ class DefaultJsApi(
|
||||
VHelper.launch(context, packageName)
|
||||
}
|
||||
} else {
|
||||
PackageUtils.launchApplicationByPackageName(context, packageName)
|
||||
PackageLauncher.launchApp(context, packageName = packageName)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -20,7 +20,7 @@ object FixedRateJobHelper {
|
||||
private const val CHECKER_PERIOD: Long = 15 * 1000L
|
||||
private const val TIME_PERIOD: Long = 10 * 60 * 1000L
|
||||
private const val LOGHUB_PERIOD: Long = 2 * 60 * 1000L
|
||||
private const val EXPOSURE_PERIOD: Long = 5 * 60 * 1000L
|
||||
private const val EXPOSURE_PERIOD: Long = 1 * 60 * 1000L
|
||||
private const val REGION_SETTING_PERIOD: Long = 60 * 1000L
|
||||
private const val VIDEO_RECORD_PERIOD: Long = 60 * 1000L
|
||||
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
package com.gh.common.chain
|
||||
|
||||
import android.content.Context
|
||||
import com.gh.common.xapk.XapkInstaller
|
||||
import com.gh.download.server.BrowserInstallHelper
|
||||
import com.gh.gamecenter.core.utils.EmptyCallback
|
||||
import com.gh.gamecenter.feature.entity.GameEntity
|
||||
@ -8,14 +9,15 @@ import com.gh.gamecenter.feature.entity.GameEntity
|
||||
class BrowserInstallHandler : ChainHandler() {
|
||||
|
||||
override fun handleRequest(context: Context, gameEntity: GameEntity) {
|
||||
BrowserInstallHelper.showBrowserInstallHintDialog(context, gameEntity.isVGame(), object : EmptyCallback {
|
||||
override fun onCallback() {
|
||||
if (hasNext()) {
|
||||
getNext()?.handleRequest(context, gameEntity)
|
||||
} else {
|
||||
processEndCallback?.invoke(null)
|
||||
}
|
||||
BrowserInstallHelper.showBrowserInstallHintDialog(
|
||||
context,
|
||||
gameEntity.isVGame() || gameEntity.isSplitXApk()
|
||||
) {
|
||||
if (hasNext()) {
|
||||
getNext()?.handleRequest(context, gameEntity)
|
||||
} else {
|
||||
processEndCallback?.invoke(null)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,27 @@
|
||||
package com.gh.common.chain
|
||||
|
||||
import android.content.Context
|
||||
import com.gh.gamecenter.common.utils.DialogHelper
|
||||
import com.gh.gamecenter.feature.entity.GameEntity
|
||||
|
||||
class UnsupportedFeatureHandler : ChainHandler() {
|
||||
|
||||
override fun handleRequest(
|
||||
context: Context, gameEntity: GameEntity
|
||||
) {
|
||||
if (shouldShowUnsupportedFeatureDialog()) {
|
||||
DialogHelper.showUnsupportedFeatureDialog(context)
|
||||
} else {
|
||||
if (hasNext()) {
|
||||
getNext()?.handleRequest(context, gameEntity)
|
||||
} else {
|
||||
processEndCallback?.invoke(null)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO 检查某个版本是否支持指定的功能
|
||||
*/
|
||||
private fun shouldShowUnsupportedFeatureDialog(): Boolean = false
|
||||
}
|
||||
@ -205,9 +205,6 @@ public class Config {
|
||||
|
||||
// 加载完设置后刷新下
|
||||
PackageHelper.initList();
|
||||
|
||||
// 初始化畅玩相关的东西
|
||||
VHelper.init(HaloApp.getInstance());
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@ -308,6 +305,26 @@ public class Config {
|
||||
return mVSetting;
|
||||
}
|
||||
|
||||
/**
|
||||
* 请求网络数据,尝试刷新畅玩相关配置
|
||||
*/
|
||||
@SuppressLint("CheckResult")
|
||||
public static void refreshVSettingEntity() {
|
||||
RetrofitManager.getInstance()
|
||||
.getVApi().getSettings(BuildConfig.VERSION_NAME)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(new BiResponse<VSetting>() {
|
||||
@Override
|
||||
public void onSuccess(VSetting data) {
|
||||
mVSetting = data;
|
||||
SPUtils.setString(Constants.SP_V_SETTINGS, GsonUtils.toJson(data));
|
||||
|
||||
VHelper.init(HaloApp.getInstance());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static GameGuidePopupEntity getGameGuidePopupEntity() {
|
||||
return mGameGuidePopupEntity;
|
||||
@ -385,16 +402,7 @@ public class Config {
|
||||
}
|
||||
});
|
||||
|
||||
RetrofitManager.getInstance()
|
||||
.getVApi().getSettings(BuildConfig.VERSION_NAME)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.subscribe(new BiResponse<VSetting>() {
|
||||
@Override
|
||||
public void onSuccess(VSetting data) {
|
||||
mVSetting = data;
|
||||
SPUtils.setString(Constants.SP_V_SETTINGS, GsonUtils.toJson(data));
|
||||
}
|
||||
});
|
||||
refreshVSettingEntity();
|
||||
|
||||
RetrofitManager.getInstance()
|
||||
.getApi().getGameGuidePopup(Build.MANUFACTURER, Build.VERSION.RELEASE, Build.MODEL, channel, BuildConfig.VERSION_NAME)
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
package com.gh.common.databind;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Typeface;
|
||||
@ -29,6 +30,7 @@ import com.gh.common.chain.DownloadDialogHelperHandler;
|
||||
import com.gh.common.chain.GamePermissionHandler;
|
||||
import com.gh.common.chain.OverseaDownloadHandler;
|
||||
import com.gh.common.chain.PackageCheckHandler;
|
||||
import com.gh.common.chain.UnsupportedFeatureHandler;
|
||||
import com.gh.common.chain.ValidateVSpaceHandler;
|
||||
import com.gh.common.chain.VersionNumberHandler;
|
||||
import com.gh.common.constant.Config;
|
||||
@ -45,10 +47,12 @@ import com.gh.common.util.GameViewUtils;
|
||||
import com.gh.common.util.LogUtils;
|
||||
import com.gh.common.util.NewsUtils;
|
||||
import com.gh.common.util.PackageInstaller;
|
||||
import com.gh.common.util.PackageLauncher;
|
||||
import com.gh.common.util.PackageUtils;
|
||||
import com.gh.common.util.ReservationHelper;
|
||||
import com.gh.download.DownloadManager;
|
||||
import com.gh.download.dialog.DownloadDialog;
|
||||
import com.gh.download.server.BrowserInstallHelper;
|
||||
import com.gh.gamecenter.DownloadManagerActivity;
|
||||
import com.gh.gamecenter.R;
|
||||
import com.gh.gamecenter.WebActivity;
|
||||
@ -63,6 +67,7 @@ import com.gh.gamecenter.common.view.DrawableView;
|
||||
import com.gh.gamecenter.core.utils.DisplayUtils;
|
||||
import com.gh.gamecenter.core.utils.MtaHelper;
|
||||
import com.gh.gamecenter.core.utils.NumberUtils;
|
||||
import com.gh.gamecenter.core.utils.ToastUtils;
|
||||
import com.gh.gamecenter.databinding.KaifuDetailItemRowBinding;
|
||||
import com.gh.gamecenter.feature.entity.ApkEntity;
|
||||
import com.gh.gamecenter.feature.entity.CommunityVideoEntity;
|
||||
@ -398,6 +403,7 @@ public class BindingAdapters {
|
||||
}
|
||||
|
||||
ChainBuilder builder = new ChainBuilder();
|
||||
builder.addHandler(new UnsupportedFeatureHandler());
|
||||
builder.addHandler(new GamePermissionHandler());
|
||||
builder.addHandler(new CheckStoragePermissionHandler());
|
||||
builder.addHandler(new ValidateVSpaceHandler());
|
||||
@ -410,7 +416,7 @@ public class BindingAdapters {
|
||||
builder.addHandler(new CheckDownloadHandler());
|
||||
|
||||
builder.setProcessEndCallback(o -> {
|
||||
download(progressBar, gameEntity, traceEvent, (boolean) o, entrance, location);
|
||||
download(v.getContext(), progressBar, gameEntity, traceEvent, (boolean) o, entrance, location);
|
||||
return null;
|
||||
});
|
||||
final ChainHandler chainHandler = builder.buildHandlerChain();
|
||||
@ -419,6 +425,7 @@ public class BindingAdapters {
|
||||
}
|
||||
} else {
|
||||
ChainBuilder builder = new ChainBuilder();
|
||||
builder.addHandler(new UnsupportedFeatureHandler());
|
||||
builder.addHandler(new GamePermissionHandler());
|
||||
builder.addHandler(new CertificationHandler());
|
||||
builder.addHandler(new VersionNumberHandler());
|
||||
@ -447,7 +454,7 @@ public class BindingAdapters {
|
||||
if (downloadEntity != null) {
|
||||
File file = new File(downloadEntity.getPath());
|
||||
if (!file.exists()) {
|
||||
download(progressBar, gameEntity, traceEvent, false, entrance, location);
|
||||
download(v.getContext(), progressBar, gameEntity, traceEvent, false, entrance, location);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -457,11 +464,11 @@ public class BindingAdapters {
|
||||
}
|
||||
|
||||
if (gameEntity.isVGame()) {
|
||||
VHelper.installOrLaunch((AppCompatActivity) v.getContext(), gameEntity);
|
||||
VHelper.installOrLaunch((AppCompatActivity) v.getContext(), gameEntity, null);
|
||||
return;
|
||||
}
|
||||
|
||||
PackageUtils.launchApplicationByPackageName(v.getContext(), gameEntity.getApk().get(0).getPackageName());
|
||||
PackageLauncher.launchApp(v.getContext(), gameEntity, gameEntity.getApk().get(0).getPackageName());
|
||||
} else {
|
||||
DownloadDialog.showDownloadDialog(
|
||||
v.getContext(),
|
||||
@ -477,7 +484,7 @@ public class BindingAdapters {
|
||||
DownloadEntity downloadEntity = DownloadManager.getInstance().getDownloadEntitySnapshot(gameEntity);
|
||||
|
||||
if (gameEntity.isVGame()) {
|
||||
VHelper.installOrLaunch(v.getContext(), gameEntity);
|
||||
VHelper.installOrLaunch(v.getContext(), gameEntity, null);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -673,12 +680,16 @@ public class BindingAdapters {
|
||||
|
||||
|
||||
// 开始下载
|
||||
private static void download(DownloadButton progressBar,
|
||||
private static void download(Context context,
|
||||
DownloadButton progressBar,
|
||||
GameEntity gameEntity,
|
||||
ExposureEvent traceEvent,
|
||||
boolean isSubscribe,
|
||||
String entrance,
|
||||
String location) {
|
||||
if (BrowserInstallHelper.shouldAutoSwitchAssistantInstall(gameEntity)) {
|
||||
ToastUtils.toast(context.getString(R.string.unsupported_browser_install_hint));
|
||||
}
|
||||
String str = progressBar.getText().toString();
|
||||
String method;
|
||||
if (str.contains("更新")) {
|
||||
|
||||
@ -48,6 +48,7 @@ object ExposureUtils {
|
||||
}
|
||||
if (!TextUtils.isEmpty(entity.id)) {
|
||||
ExposureManager.log(exposureEvent)
|
||||
ExposureManager.commitSavedExposureEvents(forcedUpload = true)
|
||||
}
|
||||
return exposureEvent
|
||||
}
|
||||
|
||||
@ -0,0 +1,119 @@
|
||||
package com.gh.common.provider
|
||||
|
||||
import android.content.Context
|
||||
import com.alibaba.android.arouter.facade.annotation.Route
|
||||
import com.gh.common.util.NewFlatLogUtils
|
||||
import com.gh.gamecenter.common.base.GlobalActivityManager
|
||||
import com.gh.gamecenter.common.constant.RouteConsts
|
||||
import com.gh.gamecenter.common.utils.*
|
||||
import com.gh.gamecenter.entity.GameUpdateEntity
|
||||
import com.gh.gamecenter.feature.entity.GameEntity
|
||||
import com.gh.gamecenter.feature.provider.IDownloadButtonClickedProvider
|
||||
import com.gh.gamecenter.feature.view.DownloadButton
|
||||
import com.gh.gamecenter.packagehelper.PackageRepository
|
||||
import com.lightgame.download.DownloadEntity
|
||||
import com.lightgame.utils.Utils
|
||||
|
||||
@Route(path = RouteConsts.provider.downloadButtonClickedHandler, name = "DownloadButton点击事件暴露服务")
|
||||
class DownloadButtonClickedProviderImpl : IDownloadButtonClickedProvider {
|
||||
override fun onClicked(downloadButton: DownloadButton) {
|
||||
var gameId = ""
|
||||
var gameName = ""
|
||||
var gameCategory = ""
|
||||
var gameTypeInChinese = ""
|
||||
var downloadStatus = ""
|
||||
var downloadStatusInChinese = ""
|
||||
var gameSchemaType = ""
|
||||
var packageName = ""
|
||||
|
||||
val boundedObject = downloadButton.getObject()
|
||||
|
||||
Utils.log("DownloadButtonClickedProviderImpl", "$downloadButton onClicked ${boundedObject?.javaClass}")
|
||||
|
||||
if (boundedObject != null) {
|
||||
when (boundedObject) {
|
||||
is GameEntity -> {
|
||||
gameId = boundedObject.id
|
||||
gameName = boundedObject.name ?: ""
|
||||
gameCategory = boundedObject.category ?: ""
|
||||
downloadStatus = if (boundedObject.isVGame()) {
|
||||
"畅玩"
|
||||
} else if (boundedObject.downloadStatus == "demo") {
|
||||
"试玩"
|
||||
} else {
|
||||
"下载"
|
||||
}
|
||||
gameTypeInChinese = boundedObject.categoryChinese
|
||||
downloadStatusInChinese = boundedObject.downloadStatusChinese
|
||||
gameSchemaType = boundedObject.gameBitChinese
|
||||
packageName = boundedObject.getUniquePackageName() ?: ""
|
||||
}
|
||||
|
||||
is GameUpdateEntity -> {
|
||||
gameId = boundedObject.id
|
||||
gameName = boundedObject.name ?: ""
|
||||
// 下载管理-更新页面,把下载状态都置为下载
|
||||
downloadStatus = "下载"
|
||||
gameTypeInChinese = boundedObject.categoryChinese
|
||||
downloadStatusInChinese = boundedObject.downloadStatusChinese
|
||||
packageName = boundedObject.packageName
|
||||
}
|
||||
|
||||
is DownloadEntity -> {
|
||||
gameId = boundedObject.gameId
|
||||
gameName = boundedObject.name ?: ""
|
||||
gameCategory = boundedObject.getGameCategory()
|
||||
downloadStatus = if (boundedObject.isVGame()) "畅玩" else "下载"
|
||||
packageName = boundedObject.packageName
|
||||
}
|
||||
}
|
||||
|
||||
// 上报 UI 状态为启动的点击事件 (样式为启动,或者文案包含启动都算能启动)
|
||||
if (downloadButton.buttonStyle == DownloadButton.ButtonStyle.LAUNCH_OR_OPEN
|
||||
|| downloadButton.text.contains("启动")) {
|
||||
|
||||
// boundedObject 里找不到游戏类型时,尝试从已安装列表中获取
|
||||
if (gameCategory.isEmpty() && packageName.isNotEmpty()) {
|
||||
gameCategory = PackageRepository.gameInstalled.find { it.packageName == packageName }?.category ?: ""
|
||||
}
|
||||
|
||||
NewFlatLogUtils.logGameLaunchButtonClicked(
|
||||
gameId = gameId,
|
||||
gameName = gameName,
|
||||
location = downloadButton.getWidgetBusinessName(),
|
||||
gameCategory = gameCategory,
|
||||
downloadStatus = downloadStatus
|
||||
)
|
||||
}
|
||||
|
||||
// 预约状态不上报
|
||||
if (downloadButton.buttonStyle != DownloadButton.ButtonStyle.RESERVABLE
|
||||
&& downloadButton.buttonStyle != DownloadButton.ButtonStyle.RESERVED
|
||||
) {
|
||||
|
||||
// 上报神策点击事件
|
||||
SensorsBridge.trackEvent(
|
||||
"DownLoadbuttonClick",
|
||||
"game_id", gameId,
|
||||
"game_name", gameName,
|
||||
"game_type", gameTypeInChinese,
|
||||
"download_status", downloadStatusInChinese,
|
||||
"button_name", downloadButton.text,
|
||||
"game_schema_type", gameSchemaType,
|
||||
"page_name", GlobalActivityManager.getCurrentPageEntity().pageName,
|
||||
"page_id", GlobalActivityManager.getCurrentPageEntity().pageId,
|
||||
"page_business_id", GlobalActivityManager.getCurrentPageEntity().pageBusinessId,
|
||||
"last_page_name", GlobalActivityManager.getLastPageEntity().pageName,
|
||||
"last_page_id", GlobalActivityManager.getLastPageEntity().pageId,
|
||||
"last_page_business_id", GlobalActivityManager.getLastPageEntity().pageBusinessId
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
override fun init(context: Context?) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
}
|
||||
@ -9,7 +9,7 @@ import com.gh.gamecenter.manager.UpdateManager
|
||||
|
||||
@Route(path = RouteConsts.provider.updateManager, name = "UpdateManager暴露服务")
|
||||
class UpdateManagerProviderImpl: IUpdateManagerProvider {
|
||||
override fun checkUpdate(context: Context, isAutoCheck: Boolean, handler: Handler) {
|
||||
override fun checkUpdate(context: Context, isAutoCheck: Boolean, handler: Handler?) {
|
||||
UpdateManager.getInstance(context).checkUpdate(isAutoCheck, handler)
|
||||
}
|
||||
|
||||
|
||||
@ -57,8 +57,7 @@ public class DataUtils {
|
||||
return;
|
||||
}
|
||||
|
||||
// 初始化 Sentry 约占用 90ms,这里切换到子线程初始化
|
||||
AppExecutor.getIoExecutor().execute(() -> initSentry(context, channel));
|
||||
initSentry(context, channel);
|
||||
}
|
||||
|
||||
private static void initSentry(Context context, String channel) {
|
||||
|
||||
@ -24,6 +24,8 @@ import com.gh.vspace.VHelper;
|
||||
import com.lightgame.download.DownloadEntity;
|
||||
import com.lightgame.download.DownloadStatus;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Created by khy on 27/06/17.
|
||||
* 详情下载工具类
|
||||
@ -42,9 +44,7 @@ public class DetailDownloadUtils {
|
||||
viewHolder.mMultiVersionDownloadTv.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
if (viewHolder.gameEntity != null
|
||||
&& Config.isShowDownload(viewHolder.gameEntity.getId())
|
||||
&& !"光环助手".equals(viewHolder.gameEntity.getName())) {
|
||||
if (viewHolder.gameEntity != null && Config.isShowDownload(viewHolder.gameEntity.getId()) && !"光环助手".equals(viewHolder.gameEntity.getName())) {
|
||||
viewHolder.downloadBottom.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
viewHolder.downloadBottom.setVisibility(View.GONE);
|
||||
@ -233,6 +233,13 @@ public class DetailDownloadUtils {
|
||||
DownloadEntity downloadEntity = viewHolder.downloadEntity;
|
||||
String xapkStatus = downloadEntity.getMeta().get(XapkInstaller.XAPK_UNZIP_STATUS);
|
||||
|
||||
if (XapkUnzipStatus.SUCCESS.name().equals(xapkStatus) && XapkInstaller.INSTANCE.isInstalling(downloadEntity.getPath())) {
|
||||
viewHolder.mDownloadPb.setText("游戏安装中");
|
||||
viewHolder.mDownloadPb.setProgress(100);
|
||||
viewHolder.mDownloadPb.setButtonStyle(DownloadButton.ButtonStyle.INSTALL_NORMAL);
|
||||
return;
|
||||
}
|
||||
|
||||
if (XapkUnzipStatus.UNZIPPING.name().equals(xapkStatus)) {
|
||||
String percent = downloadEntity.getMeta().get(XapkInstaller.XAPK_UNZIP_PERCENT);
|
||||
viewHolder.mDownloadPb.setText("游戏解压中 " + percent + "%");
|
||||
@ -286,7 +293,7 @@ public class DetailDownloadUtils {
|
||||
viewHolder.mDownloadPb.setText(R.string.launch);
|
||||
viewHolder.mDownloadPb.setButtonStyle(DownloadButton.ButtonStyle.LAUNCH_OR_OPEN);
|
||||
} else {
|
||||
if (SPUtils.getBoolean(Constants.SP_USE_BROWSER_TO_INSTALL)) {
|
||||
if (SPUtils.getBoolean(Constants.SP_USE_BROWSER_TO_INSTALL) && !Objects.equals(Constants.XAPK_APKS_FORMAT, downloadEntity.getFormat())) {
|
||||
viewHolder.mDownloadPb.setText(R.string.browser_install_install);
|
||||
} else {
|
||||
viewHolder.mDownloadPb.setText(R.string.install);
|
||||
@ -307,13 +314,12 @@ public class DetailDownloadUtils {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (SPUtils.getBoolean(Constants.SP_USE_BROWSER_TO_INSTALL)) {
|
||||
if (SPUtils.getBoolean(Constants.SP_USE_BROWSER_TO_INSTALL) && !Objects.equals(Constants.XAPK_APKS_FORMAT, downloadEntity.getFormat())) {
|
||||
viewHolder.mDownloadPb.setText(R.string.browser_install_install);
|
||||
} else {
|
||||
viewHolder.mDownloadPb.setText(R.string.install);
|
||||
}
|
||||
if (downloadEntity.isPluggable()
|
||||
&& PackagesManager.isInstalled(downloadEntity.getPackageName())) {
|
||||
if (downloadEntity.isPluggable() && PackagesManager.isInstalled(downloadEntity.getPackageName())) {
|
||||
viewHolder.mDownloadPb.setButtonStyle(DownloadButton.ButtonStyle.INSTALL_PLUGIN);
|
||||
} else {
|
||||
viewHolder.mDownloadPb.setButtonStyle(DownloadButton.ButtonStyle.INSTALL_NORMAL);
|
||||
|
||||
@ -51,6 +51,7 @@ import com.gh.gamecenter.game.columncollection.detail.ColumnCollectionDetailActi
|
||||
import com.gh.gamecenter.game.commoncollection.detail.CommonCollectionDetailActivity
|
||||
import com.gh.gamecenter.game.upload.GameSubmissionActivity
|
||||
import com.gh.gamecenter.gamecollection.detail.GameCollectionDetailActivity
|
||||
import com.gh.gamecenter.gamecollection.hotlist.GameCollectionHotListActivity
|
||||
import com.gh.gamecenter.gamecollection.square.GameCollectionSquareActivity
|
||||
import com.gh.gamecenter.gamedetail.GameDetailFragment
|
||||
import com.gh.gamecenter.gamedetail.fuli.kaifu.ServersCalendarActivity
|
||||
@ -219,8 +220,9 @@ object DirectUtils {
|
||||
)
|
||||
} else {
|
||||
directToGameDetail(
|
||||
context, linkEntity.link
|
||||
?: "", BaseActivity.mergeEntranceAndPath(entrance, path)
|
||||
context,
|
||||
linkEntity.link ?: "",
|
||||
entrance = BaseActivity.mergeEntranceAndPath(entrance, path)
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -1877,7 +1879,9 @@ object DirectUtils {
|
||||
entrance: String = "",
|
||||
forumName: String = "",
|
||||
gameCollectionTitle: String = "",
|
||||
gameCollectionId: String = ""
|
||||
gameCollectionId: String = "",
|
||||
collectionName: String = "",
|
||||
collectionId: String = ""
|
||||
) {
|
||||
val bundle = Bundle()
|
||||
bundle.putString(KEY_TO, GameCollectionSquareActivity::class.java.name)
|
||||
@ -1885,6 +1889,19 @@ object DirectUtils {
|
||||
bundle.putString(KEY_FORUM_NAME, forumName)
|
||||
bundle.putString(KEY_GAME_COLLECTION_TITLE, gameCollectionTitle)
|
||||
bundle.putString(KEY_GAME_COLLECTION_ID, gameCollectionId)
|
||||
bundle.putString(KEY_COLLECTION_ID, collectionId)
|
||||
bundle.putString(KEY_COLLECTION_NAME, collectionName)
|
||||
jumpActivity(context, bundle)
|
||||
}
|
||||
|
||||
/**
|
||||
* 跳转至游戏单热榜
|
||||
*/
|
||||
@JvmStatic
|
||||
fun directToGameCollectionHotList(context: Context, entrance: String = "") {
|
||||
val bundle = Bundle()
|
||||
bundle.putString(KEY_TO, GameCollectionHotListActivity::class.java.name)
|
||||
bundle.putString(KEY_ENTRANCE, entrance)
|
||||
jumpActivity(context, bundle)
|
||||
}
|
||||
|
||||
|
||||
@ -18,18 +18,20 @@ import com.gh.common.simulator.SimulatorDownloadManager
|
||||
import com.gh.common.simulator.SimulatorGameManager
|
||||
import com.gh.common.xapk.XapkInstaller
|
||||
import com.gh.common.xapk.XapkInstaller.cancelUnzipTask
|
||||
import com.gh.common.xapk.XapkInstaller.isInstalling
|
||||
import com.gh.common.xapk.XapkUnzipStatus
|
||||
import com.gh.download.DownloadManager
|
||||
import com.gh.download.dialog.DownloadDialog
|
||||
import com.gh.download.server.BrowserInstallHelper
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.WebActivity
|
||||
import com.gh.gamecenter.adapter.viewholder.GameViewHolder
|
||||
import com.gh.gamecenter.common.base.GlobalActivityManager
|
||||
import com.gh.gamecenter.common.callback.CancelListener
|
||||
import com.gh.gamecenter.common.constant.Constants
|
||||
import com.gh.gamecenter.common.constant.EntranceConsts
|
||||
import com.gh.gamecenter.common.entity.LinkEntity
|
||||
import com.gh.gamecenter.common.utils.*
|
||||
import com.gh.gamecenter.core.AppExecutor
|
||||
import com.gh.gamecenter.core.utils.*
|
||||
import com.gh.gamecenter.feature.entity.GameEntity
|
||||
import com.gh.gamecenter.feature.entity.PluginLocation
|
||||
@ -163,6 +165,8 @@ object DownloadItemUtils {
|
||||
briefStyle: String? = null,
|
||||
isShowRecommendStar: Boolean = false
|
||||
) {
|
||||
holder.gameDownloadBtn.putObject(gameEntity)
|
||||
|
||||
// 显示预约
|
||||
if (gameEntity.isReservable) {
|
||||
holder.multiVersionDownloadTv?.visibility = View.GONE
|
||||
@ -263,18 +267,17 @@ object DownloadItemUtils {
|
||||
}
|
||||
}
|
||||
} else if (gameEntity.getApk().size == 1) {
|
||||
// 优先从下载管理获取 downloadEntity
|
||||
var downloadEntity = DownloadManager.getInstance().getDownloadEntitySnapshot(gameEntity)
|
||||
|
||||
// 找不到时,若类型为畅玩,尝试从畅玩数据库的快照中获取 downloadEntity。若存在,代表游戏已下载并成功安装
|
||||
if (downloadEntity == null && gameEntity.isVGame()) {
|
||||
downloadEntity = VHelper.getVDownloadEntitySnapshot(gameEntity.id, gameEntity.getUniquePackageName())
|
||||
}
|
||||
|
||||
// 还是找不到时,尝试从 gameEntity 里找已绑定的 downloadEntity
|
||||
if (downloadEntity == null) {
|
||||
val entryMap: ArrayMap<String, DownloadEntity> = gameEntity.getEntryMap()
|
||||
val apkEntity = gameEntity.getApk()[0]
|
||||
if (entryMap.isNotEmpty()) {
|
||||
downloadEntity = entryMap[apkEntity.getPlatform()]
|
||||
}
|
||||
downloadEntity = gameEntity.getEntryMap().getOrDefault(gameEntity.getUniquePlatform(), null)
|
||||
}
|
||||
|
||||
if (downloadEntity != null) {
|
||||
@ -297,6 +300,25 @@ object DownloadItemUtils {
|
||||
DownloadButton.ButtonStyle.LAUNCH_OR_OPEN
|
||||
}
|
||||
} else {
|
||||
val xapkStatus = downloadEntity.meta[XapkInstaller.XAPK_UNZIP_STATUS]
|
||||
if (XapkUnzipStatus.SUCCESS.name == xapkStatus && isInstalling(downloadEntity.path)) {
|
||||
progress = 100
|
||||
setText(R.string.installing)
|
||||
buttonStyle = DownloadButton.ButtonStyle.INSTALL_NORMAL
|
||||
return
|
||||
}
|
||||
if (XapkUnzipStatus.UNZIPPING.name == xapkStatus) {
|
||||
val percent = downloadEntity.meta[XapkInstaller.XAPK_UNZIP_PERCENT]
|
||||
progress = (java.lang.Float.valueOf(percent) * 10).toInt()
|
||||
text = "$percent%"
|
||||
buttonStyle = DownloadButton.ButtonStyle.XAPK_UNZIPPING
|
||||
return
|
||||
} else if (XapkUnzipStatus.FAILURE.name == xapkStatus) {
|
||||
setText(R.string.install)
|
||||
buttonStyle = DownloadButton.ButtonStyle.INSTALL_NORMAL
|
||||
return
|
||||
}
|
||||
|
||||
buttonStyle = DownloadButton.ButtonStyle.INSTALL_NORMAL
|
||||
setText(R.string.install)
|
||||
}
|
||||
@ -307,6 +329,7 @@ object DownloadItemUtils {
|
||||
DownloadButton.ButtonStyle.NORMAL
|
||||
}
|
||||
}
|
||||
|
||||
DownloadStatus.pause,
|
||||
DownloadStatus.timeout,
|
||||
DownloadStatus.neterror,
|
||||
@ -317,9 +340,11 @@ object DownloadItemUtils {
|
||||
buttonStyle = DownloadButton.ButtonStyle.NORMAL
|
||||
setText(R.string.resume)
|
||||
}
|
||||
|
||||
DownloadStatus.cancel -> {
|
||||
GameUtils.setDownloadBtnStatus(context, gameEntity, downloadBtn, pluginLocation)
|
||||
}
|
||||
|
||||
else -> {
|
||||
// do nothing
|
||||
}
|
||||
@ -396,7 +421,7 @@ object DownloadItemUtils {
|
||||
}
|
||||
|
||||
// 更改进度条和提示文本的状态
|
||||
fun changeStatus(
|
||||
private fun changeStatus(
|
||||
context: Context,
|
||||
holder: GameViewHolder,
|
||||
downloadEntity: DownloadEntity,
|
||||
@ -421,6 +446,7 @@ object DownloadItemUtils {
|
||||
holder.gameDownloadBtn.text = downloadEntity.percent.toString() + "%"
|
||||
}
|
||||
}
|
||||
|
||||
DownloadStatus.waiting -> {
|
||||
if (isMultiVersion) {
|
||||
holder.gameDownloadTips?.visibility = View.VISIBLE
|
||||
@ -429,6 +455,7 @@ object DownloadItemUtils {
|
||||
holder.gameDownloadBtn.buttonStyle = DownloadButton.ButtonStyle.WAITING
|
||||
holder.gameDownloadBtn.text = context.getString(R.string.waiting)
|
||||
}
|
||||
|
||||
DownloadStatus.pause,
|
||||
DownloadStatus.timeout,
|
||||
DownloadStatus.neterror,
|
||||
@ -443,6 +470,7 @@ object DownloadItemUtils {
|
||||
holder.gameDownloadBtn.buttonStyle = DownloadButton.ButtonStyle.NORMAL
|
||||
holder.gameDownloadBtn.text = context.getString(R.string.resume)
|
||||
}
|
||||
|
||||
DownloadStatus.done -> {
|
||||
if (isMultiVersion) {
|
||||
holder.gameDownloadTips?.visibility = View.VISIBLE
|
||||
@ -462,6 +490,7 @@ object DownloadItemUtils {
|
||||
holder.gameDownloadBtn.progress = 1000
|
||||
holder.gameDownloadBtn.setText(R.string.hundred_percent)
|
||||
}
|
||||
|
||||
else -> {
|
||||
holder.gameDownloadTips?.visibility = View.GONE
|
||||
}
|
||||
@ -592,13 +621,15 @@ object DownloadItemUtils {
|
||||
refreshCallback: EmptyCallback?,
|
||||
allStateClickCallback: EmptyCallback?
|
||||
) {
|
||||
// 为 downloadButton 添加游戏实体,供点击的时候上报用
|
||||
downloadBtn.putObject(gameEntity)
|
||||
|
||||
val gamePermissionDialogFragment = (context as AppCompatActivity).supportFragmentManager.findFragmentByTag(
|
||||
GamePermissionDialogFragment::class.java.name
|
||||
) as GamePermissionDialogFragment?
|
||||
gamePermissionDialogFragment?.dismissAllowingStateLoss()
|
||||
if (SPUtils.getBoolean(Constants.SP_TEENAGER_MODE)) {
|
||||
downloadBtn.setOnClickListener {
|
||||
logDownloadButtonClick(gameEntity, downloadBtn)
|
||||
DialogHelper.showDialog(
|
||||
context,
|
||||
"提示",
|
||||
@ -618,7 +649,6 @@ object DownloadItemUtils {
|
||||
if (gameEntity.isSpecialDownload()) {
|
||||
val info = RegionSettingHelper.getGameSpecialDownloadInfo(gameEntity.id) ?: return
|
||||
downloadBtn.setOnClickListener {
|
||||
logDownloadButtonClick(gameEntity, downloadBtn)
|
||||
DialogHelper.showDialog(
|
||||
context,
|
||||
"提示",
|
||||
@ -659,14 +689,12 @@ object DownloadItemUtils {
|
||||
ReservationHelper.reserve(
|
||||
context,
|
||||
gameEntity.id,
|
||||
gameEntity.name ?: "",
|
||||
object : EmptyCallback {
|
||||
override fun onCallback() {
|
||||
LogUtils.logReservation(gameEntity, traceEvent)
|
||||
adapter?.notifyItemChanged(position)
|
||||
refreshCallback?.onCallback()
|
||||
}
|
||||
})
|
||||
gameEntity.name ?: ""
|
||||
) {
|
||||
LogUtils.logReservation(gameEntity, traceEvent)
|
||||
adapter?.notifyItemChanged(position)
|
||||
refreshCallback?.onCallback()
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@ -708,16 +736,13 @@ object DownloadItemUtils {
|
||||
val gameH5Download = RegionSettingHelper.getGameH5DownloadByGameId(gameEntity.id)
|
||||
if (gameH5Download != null) {
|
||||
downloadBtn.setOnClickListener {
|
||||
logDownloadButtonClick(gameEntity, downloadBtn)
|
||||
DialogUtils.showGameH5DownloadDialog(context, gameEntity, gameH5Download)
|
||||
}
|
||||
return
|
||||
}
|
||||
if (gameEntity.getApk().size == 0 && gameEntity.h5Link != null) {
|
||||
downloadBtn.setOnClickListener {
|
||||
logDownloadButtonClick(gameEntity, downloadBtn)
|
||||
allStateClickCallback?.onCallback()
|
||||
MtaHelper.onEvent("H5页面", "入口", "列表页_" + gameEntity.name)
|
||||
val linkEntity = gameEntity.h5Link
|
||||
val isPlay = "play" == linkEntity!!.type // 是否为开始玩
|
||||
if (isPlay) {
|
||||
@ -734,7 +759,6 @@ object DownloadItemUtils {
|
||||
}
|
||||
} else if (gameEntity.getApk().size == 1) {
|
||||
downloadBtn.setOnClickListener {
|
||||
logDownloadButtonClick(gameEntity, downloadBtn)
|
||||
val clickRunnable = EmptyCallback {
|
||||
allStateClickCallback?.onCallback()
|
||||
clickCallback?.onCallback()
|
||||
@ -795,6 +819,7 @@ object DownloadItemUtils {
|
||||
val apk = gameEntity.getApk().safelyGetInRelease(0) ?: return
|
||||
if (str == context.getString(R.string.download)) {
|
||||
ChainBuilder().apply {
|
||||
addHandler(UnsupportedFeatureHandler())
|
||||
addHandler(UpdateNewSimulatorHandler())
|
||||
addHandler(GamePermissionHandler())
|
||||
addHandler(BrowserInstallHandler())
|
||||
@ -812,6 +837,7 @@ object DownloadItemUtils {
|
||||
DataLogUtils.uploadGameLog(context, gameEntity.id, gameEntity.name, entrance)
|
||||
} else if (str == context.getString(R.string.attempt)) {
|
||||
ChainBuilder().apply {
|
||||
addHandler(UnsupportedFeatureHandler())
|
||||
addHandler(UpdateNewSimulatorHandler())
|
||||
addHandler(GamePermissionHandler())
|
||||
addHandler(BrowserInstallHandler())
|
||||
@ -830,6 +856,7 @@ object DownloadItemUtils {
|
||||
DataLogUtils.uploadGameLog(context, gameEntity.id, gameEntity.name, entrance)
|
||||
} else if (str == context.getString(R.string.smooth)) {
|
||||
ChainBuilder().apply {
|
||||
addHandler(UnsupportedFeatureHandler())
|
||||
addHandler(GamePermissionHandler())
|
||||
addHandler(PackageCheckHandler())
|
||||
addHandler(DownloadDialogHelperHandler())
|
||||
@ -846,9 +873,6 @@ object DownloadItemUtils {
|
||||
.buildHandlerChain()
|
||||
?.handleRequest(context, gameEntity)
|
||||
} else if (str.contains("化")) {
|
||||
if (entrance.contains("我的游戏")) {
|
||||
MtaHelper.onEvent("我的游戏_启动", "插件化", gameEntity.name)
|
||||
}
|
||||
if (gameEntity.pluggableCollection != null) {
|
||||
DownloadDialog.showDownloadDialog(context, gameEntity, traceEvent, entrance, location)
|
||||
} else {
|
||||
@ -913,42 +937,40 @@ object DownloadItemUtils {
|
||||
VHelper.installOrLaunch((context as AppCompatActivity), gameEntity)
|
||||
return
|
||||
}
|
||||
|
||||
if (entrance.contains("我的游戏")) {
|
||||
MtaHelper.onEvent("我的游戏_启动", "启动", gameEntity.name)
|
||||
}
|
||||
PackageUtils.launchApplicationByPackageName(context, gameEntity.getApk()[0].packageName)
|
||||
PackageLauncher.launchApp(context, gameEntity, gameEntity.getApk()[0].packageName)
|
||||
} else if (str == context.getString(R.string.update)) {
|
||||
if (entrance.contains("我的游戏")) {
|
||||
MtaHelper.onEvent("我的游戏_启动", "更新", gameEntity.name)
|
||||
}
|
||||
if (gameEntity.isVGame()) {
|
||||
VHelper.updateOrReDownload(gameEntity)
|
||||
return
|
||||
}
|
||||
DownloadDialogHelper.findAvailableDialogAndShow(context, gameEntity, apk, object : EmptyCallback {
|
||||
override fun onCallback() {
|
||||
DialogUtils.checkDownload(
|
||||
context,
|
||||
apk.size,
|
||||
gameEntity.id,
|
||||
gameEntity.name
|
||||
) { isSubscribe: Boolean ->
|
||||
update(context, gameEntity, entrance, location, isSubscribe, traceEvent)
|
||||
}
|
||||
}
|
||||
})
|
||||
} else {
|
||||
var downloadEntity = DownloadManager.getInstance().getDownloadEntitySnapshot(gameEntity)
|
||||
if (downloadEntity == null && gameEntity.getApk().size == 1) {
|
||||
val entryMap: ArrayMap<String, DownloadEntity> = gameEntity.getEntryMap()
|
||||
val apkEntity = gameEntity.getApk()[0]
|
||||
if (entryMap.isNotEmpty()) {
|
||||
downloadEntity = entryMap[apkEntity.getPlatform()]
|
||||
DownloadDialogHelper.findAvailableDialogAndShow(context, gameEntity, apk) {
|
||||
DialogUtils.checkDownload(
|
||||
context,
|
||||
apk.size,
|
||||
gameEntity.id,
|
||||
gameEntity.name
|
||||
) { isSubscribe: Boolean ->
|
||||
update(context, gameEntity, entrance, location, isSubscribe, traceEvent)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
var downloadEntity = DownloadManager.getInstance().getDownloadEntitySnapshot(gameEntity)
|
||||
|
||||
// 找不到时,若类型为畅玩,尝试从畅玩数据库的快照中获取 downloadEntity。若存在,代表游戏已下载并成功安装
|
||||
if (downloadEntity == null && gameEntity.isVGame()) {
|
||||
downloadEntity = VHelper.getVDownloadEntitySnapshot(gameEntity.id, gameEntity.getUniquePackageName())
|
||||
}
|
||||
|
||||
// 还是找不到时,尝试从 gameEntity 里找已绑定的 downloadEntity
|
||||
if (downloadEntity == null) {
|
||||
downloadEntity = gameEntity.getEntryMap().getOrDefault(gameEntity.getUniquePlatform(), null)
|
||||
}
|
||||
|
||||
if (downloadEntity != null) {
|
||||
val xapkStatus = downloadEntity.meta[XapkInstaller.XAPK_UNZIP_STATUS]
|
||||
if (XapkUnzipStatus.SUCCESS.name == xapkStatus && isInstalling(downloadEntity.path)) {// 安装过程中避免重复点击
|
||||
return
|
||||
}
|
||||
if (XapkUnzipStatus.UNZIPPING.name == xapkStatus) {
|
||||
cancelUnzipTask(downloadEntity)
|
||||
return
|
||||
@ -957,9 +979,11 @@ object DownloadItemUtils {
|
||||
context.getString(R.string.resume) -> {
|
||||
DownloadManager.getInstance().resume(downloadEntity, true)
|
||||
}
|
||||
|
||||
context.getString(R.string.waiting) -> {
|
||||
Utils.toast(context, "最多只能同时下载三个任务,请稍等")
|
||||
}
|
||||
|
||||
else -> {
|
||||
DownloadManager.getInstance().pause(downloadEntity.url)
|
||||
}
|
||||
@ -980,7 +1004,7 @@ object DownloadItemUtils {
|
||||
) {
|
||||
if (gameEntity.getApk().isEmpty()) return
|
||||
|
||||
val msg = FileUtils.isCanDownload(context, gameEntity.getApk()[0].size)
|
||||
val msg = FileUtils.isCanDownload(context, gameEntity.getApk()[0].size ?: "")
|
||||
if (TextUtils.isEmpty(msg)) {
|
||||
DownloadManager.createDownload(
|
||||
context,
|
||||
@ -991,7 +1015,13 @@ object DownloadItemUtils {
|
||||
isSubscribe,
|
||||
traceEvent
|
||||
)
|
||||
Utils.toast(context, gameEntity.name + "已加入下载队列")
|
||||
ToastUtils.toast(gameEntity.name + "已加入下载队列")
|
||||
if (BrowserInstallHelper.shouldAutoSwitchAssistantInstall(gameEntity)) {
|
||||
val toast = context.getString(R.string.unsupported_browser_install_hint)
|
||||
AppExecutor.uiExecutor.executeWithDelay({
|
||||
ToastUtils.toast(toast)
|
||||
}, 1000)
|
||||
}
|
||||
if (downloadBtn is DownloadButton) {
|
||||
downloadBtn.text = "0%"
|
||||
downloadBtn.buttonStyle = DownloadButton.ButtonStyle.DOWNLOADING_NORMAL
|
||||
@ -1012,10 +1042,16 @@ object DownloadItemUtils {
|
||||
isSubscribe: Boolean,
|
||||
traceEvent: ExposureEvent?
|
||||
) {
|
||||
val msg = FileUtils.isCanDownload(context, gameEntity.getApk()[0].size)
|
||||
val msg = FileUtils.isCanDownload(context, gameEntity.getApk()[0].size ?: "")
|
||||
if (TextUtils.isEmpty(msg)) {
|
||||
DownloadManager.createDownload(context, gameEntity, "插件化", entrance, location, isSubscribe, traceEvent)
|
||||
Utils.toast(context, gameEntity.name + "已加入下载队列")
|
||||
ToastUtils.toast(gameEntity.name + "已加入下载队列")
|
||||
if (BrowserInstallHelper.shouldAutoSwitchAssistantInstall(gameEntity)) {
|
||||
val toast = context.getString(R.string.unsupported_browser_install_hint)
|
||||
AppExecutor.uiExecutor.executeWithDelay({
|
||||
ToastUtils.toast(toast)
|
||||
}, 1000)
|
||||
}
|
||||
if (downloadBtn is DownloadButton) {
|
||||
downloadBtn.setText(R.string.downloading)
|
||||
downloadBtn.buttonStyle = DownloadButton.ButtonStyle.DOWNLOADING_PLUGIN
|
||||
@ -1045,9 +1081,11 @@ object DownloadItemUtils {
|
||||
adapter?.notifyItemChanged(position)
|
||||
refreshCallback?.onCallback()
|
||||
}
|
||||
|
||||
PackageUtils.isCanPluggable(apkEntity) -> {
|
||||
DialogHelper.showPluginDialog(context) { PackageInstaller.uninstall(context, path) }
|
||||
}
|
||||
|
||||
else -> {
|
||||
PackageInstaller.install(context, downloadEntity)
|
||||
}
|
||||
@ -1066,23 +1104,4 @@ object DownloadItemUtils {
|
||||
) {
|
||||
DownloadManager.createDownload(context, gameEntity, "更新", entrance, location, isSubscribe, traceEvent)
|
||||
}
|
||||
|
||||
private fun logDownloadButtonClick(gameEntity: GameEntity, downloadBtn: View) {
|
||||
val buttonName = if (downloadBtn is DownloadButton) downloadBtn.text else ""
|
||||
SensorsBridge.trackEvent(
|
||||
"DownLoadbuttonClick",
|
||||
"game_id", gameEntity.id,
|
||||
"game_name", gameEntity.name ?: "",
|
||||
"game_type", gameEntity.categoryChinese,
|
||||
"download_status", gameEntity.downloadStatusChinese,
|
||||
"button_name", buttonName,
|
||||
"game_schema_type", gameEntity.gameBitChinese,
|
||||
"page_name", GlobalActivityManager.getCurrentPageEntity().pageName,
|
||||
"page_id", GlobalActivityManager.getCurrentPageEntity().pageId,
|
||||
"page_business_id", GlobalActivityManager.getCurrentPageEntity().pageBusinessId,
|
||||
"last_page_name", GlobalActivityManager.getLastPageEntity().pageName,
|
||||
"last_page_id", GlobalActivityManager.getLastPageEntity().pageId,
|
||||
"last_page_business_id", GlobalActivityManager.getLastPageEntity().pageBusinessId
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -16,7 +16,6 @@ import com.gh.gamecenter.common.constant.Constants
|
||||
import com.gh.gamecenter.common.entity.SimpleGameEntity
|
||||
import com.gh.gamecenter.common.entity.SuggestType
|
||||
import com.gh.gamecenter.common.eventbus.EBShowDialog
|
||||
import com.gh.gamecenter.common.retrofit.Response
|
||||
import com.gh.gamecenter.common.utils.*
|
||||
import com.gh.gamecenter.core.utils.*
|
||||
import com.gh.gamecenter.eventbus.EBDownloadStatus
|
||||
@ -24,18 +23,13 @@ import com.gh.gamecenter.feature.entity.GameEntity
|
||||
import com.gh.gamecenter.feature.entity.SimulatorEntity
|
||||
import com.gh.gamecenter.feature.utils.PlatformUtils
|
||||
import com.gh.gamecenter.help.HelpAndFeedbackBridge
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager
|
||||
import com.gh.gamecenter.pkg.PkgHelper
|
||||
import com.gh.vspace.VHelper
|
||||
import com.halo.assistant.HaloApp
|
||||
import com.lightgame.download.*
|
||||
import com.lightgame.utils.AppManager
|
||||
import com.lightgame.utils.Utils
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
import okhttp3.MediaType
|
||||
import okhttp3.RequestBody
|
||||
import org.greenrobot.eventbus.EventBus
|
||||
import org.json.JSONObject
|
||||
|
||||
object DownloadObserver {
|
||||
|
||||
@ -45,7 +39,7 @@ object DownloadObserver {
|
||||
// TODO 修复因为更改内存对象造成的双重下载完成事件问题,具体触发代码见 DownloadDao.updateSnapshotList
|
||||
private var mDoneDebouncePair: Pair<String, Long>? = null
|
||||
|
||||
private const val TEA_EVENT_DOWNLOAD_COMPLETE = "game_addiction"
|
||||
private const val CORE_EVENT_DOWNLOAD_COMPLETE_LOGGED = "CORE_EVENT_DOWNLOAD_COMPLETE_LOGGED"
|
||||
|
||||
// 如果在WIFI状态下,下载自动暂停,则再重试一遍
|
||||
@JvmStatic
|
||||
@ -210,10 +204,7 @@ object DownloadObserver {
|
||||
} else {
|
||||
statDoneEvent(downloadEntity)
|
||||
|
||||
if (!SPUtils.getBoolean(TEA_EVENT_DOWNLOAD_COMPLETE)) {
|
||||
HaloApp.getInstance().flavorProvider.logEvent(TEA_EVENT_DOWNLOAD_COMPLETE)
|
||||
SPUtils.setBoolean(TEA_EVENT_DOWNLOAD_COMPLETE, true)
|
||||
}
|
||||
logCoreEventIfNeeded(downloadEntity.getGameCategory())
|
||||
|
||||
GameActivityDownloadHelper.clear()
|
||||
|
||||
@ -392,7 +383,7 @@ object DownloadObserver {
|
||||
"DownloadProcessFinish",
|
||||
"game_id", downloadEntity.gameId,
|
||||
"game_name", downloadEntity.meta[Constants.GAME_NAME] ?: "",
|
||||
"game_type", downloadEntity.meta[Constants.GAME_TYPE] ?: "",
|
||||
"game_type", downloadEntity.meta[Constants.GAME_CATEGORY_IN_CHINESE] ?: "",
|
||||
"game_schema_type", if (downloadEntity.getMetaExtra(VHelper.KEY_BIT) == "32") "32位" else "64位",
|
||||
"page_name", getCurrentPageEntity().pageName,
|
||||
"page_id", getCurrentPageEntity().pageId,
|
||||
@ -452,4 +443,21 @@ object DownloadObserver {
|
||||
DataLogUtils.uploadHijack(mApplication, downloadEntity)
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据预设的游戏类型上报关键事件(下载完成事件)
|
||||
*/
|
||||
private fun logCoreEventIfNeeded(gameCategory: String) {
|
||||
val category = PkgHelper.getCoreEventGameCategory()
|
||||
val categoryMatched = if (category == "standard" || category.isNullOrEmpty()) {
|
||||
true
|
||||
} else {
|
||||
gameCategory == category
|
||||
}
|
||||
|
||||
if (!SPUtils.getBoolean(CORE_EVENT_DOWNLOAD_COMPLETE_LOGGED) && categoryMatched) {
|
||||
HaloApp.getInstance().flavorProvider.logCoreEvent()
|
||||
SPUtils.setBoolean(CORE_EVENT_DOWNLOAD_COMPLETE_LOGGED, true)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -15,6 +15,7 @@ import com.gh.common.simulator.SimulatorDownloadManager
|
||||
import com.gh.common.simulator.SimulatorGameManager
|
||||
import com.gh.download.DownloadManager
|
||||
import com.gh.download.dialog.DownloadDialog
|
||||
import com.gh.download.server.BrowserInstallHelper
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.WebActivity
|
||||
import com.gh.gamecenter.common.constant.Constants
|
||||
@ -26,6 +27,7 @@ import com.gh.gamecenter.common.utils.DialogHelper
|
||||
import com.gh.gamecenter.common.utils.observableToMain
|
||||
import com.gh.gamecenter.common.utils.singleToMain
|
||||
import com.gh.gamecenter.common.view.dsbridge.CompletionHandler
|
||||
import com.gh.gamecenter.core.AppExecutor
|
||||
import com.gh.gamecenter.core.runOnUiThread
|
||||
import com.gh.gamecenter.core.utils.EmptyCallback
|
||||
import com.gh.gamecenter.core.utils.MtaHelper
|
||||
@ -183,6 +185,12 @@ object GameActivityDownloadHelper {
|
||||
str != context.getString(R.string.launch)
|
||||
) {
|
||||
ToastUtils.toast("${gameEntity.name}已加入下载队列")
|
||||
if (BrowserInstallHelper.shouldAutoSwitchAssistantInstall(gameEntity)) {
|
||||
val toast = context.getString(R.string.unsupported_browser_install_hint)
|
||||
AppExecutor.uiExecutor.executeWithDelay({
|
||||
ToastUtils.toast(toast)
|
||||
}, 1000)
|
||||
}
|
||||
} else {
|
||||
when {
|
||||
str == context.getString(R.string.download) || str == context.getString(R.string.attempt) -> {
|
||||
@ -205,6 +213,12 @@ object GameActivityDownloadHelper {
|
||||
}
|
||||
else -> {
|
||||
ToastUtils.toast("${gameEntity.name}已加入下载队列")
|
||||
if (BrowserInstallHelper.shouldAutoSwitchAssistantInstall(gameEntity)) {
|
||||
val toast = context.getString(R.string.unsupported_browser_install_hint)
|
||||
AppExecutor.uiExecutor.executeWithDelay({
|
||||
ToastUtils.toast(toast)
|
||||
}, 1000)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -348,7 +362,7 @@ object GameActivityDownloadHelper {
|
||||
if (entrance.contains("我的游戏")) {
|
||||
MtaHelper.onEvent("我的游戏_启动", "启动", gameEntity.name)
|
||||
}
|
||||
PackageUtils.launchApplicationByPackageName(context, gameEntity.getApk()[0].packageName)
|
||||
PackageLauncher.launchApp(context, gameEntity, gameEntity.getApk()[0].packageName)
|
||||
}
|
||||
|
||||
// 处理更新状态
|
||||
@ -424,6 +438,12 @@ object GameActivityDownloadHelper {
|
||||
), entrance, location, isSubscribe, traceEvent
|
||||
)
|
||||
ToastUtils.toast("${gameEntity.name}已加入下载队列")
|
||||
if (BrowserInstallHelper.shouldAutoSwitchAssistantInstall(gameEntity)) {
|
||||
val toast = context.getString(R.string.unsupported_browser_install_hint)
|
||||
AppExecutor.uiExecutor.executeWithDelay({
|
||||
ToastUtils.toast(toast)
|
||||
}, 1000)
|
||||
}
|
||||
} else {
|
||||
ToastUtils.toast(msg)
|
||||
}
|
||||
@ -443,6 +463,12 @@ object GameActivityDownloadHelper {
|
||||
if (TextUtils.isEmpty(msg)) {
|
||||
DownloadManager.createDownload(context, apk, gameEntity, "插件化", entrance, location, isSubscribe, traceEvent)
|
||||
ToastUtils.toast("${gameEntity.name}已加入下载队列")
|
||||
if (BrowserInstallHelper.shouldAutoSwitchAssistantInstall(gameEntity)) {
|
||||
val toast = context.getString(R.string.unsupported_browser_install_hint)
|
||||
AppExecutor.uiExecutor.executeWithDelay({
|
||||
ToastUtils.toast(toast)
|
||||
}, 1000)
|
||||
}
|
||||
} else {
|
||||
ToastUtils.toast(msg)
|
||||
}
|
||||
@ -483,6 +509,12 @@ object GameActivityDownloadHelper {
|
||||
) {
|
||||
DownloadManager.createDownload(context, apk, gameEntity, "更新", entrance, location, isSubscribe, traceEvent)
|
||||
ToastUtils.toast("${gameEntity.name}已加入下载队列")
|
||||
if (BrowserInstallHelper.shouldAutoSwitchAssistantInstall(gameEntity)) {
|
||||
val toast = context.getString(R.string.unsupported_browser_install_hint)
|
||||
AppExecutor.uiExecutor.executeWithDelay({
|
||||
ToastUtils.toast(toast)
|
||||
}, 1000)
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("CheckResult")
|
||||
|
||||
@ -8,6 +8,7 @@ import androidx.annotation.WorkerThread;
|
||||
|
||||
import com.gh.common.constant.Config;
|
||||
import com.gh.common.simulator.SimulatorGameManager;
|
||||
import com.gh.gamecenter.common.constant.Constants;
|
||||
import com.gh.gamecenter.feature.view.DownloadButton;
|
||||
import com.gh.download.DownloadManager;
|
||||
import com.gh.gamecenter.R;
|
||||
@ -180,7 +181,8 @@ public class GameUtils {
|
||||
if (gameEntity.isVGame()) {
|
||||
return context.getString(R.string.smooth);
|
||||
} else {
|
||||
if ("smooth".equals(gameEntity.getDownloadStatus())) {
|
||||
if (Constants.V_GAME.equals(gameEntity.getDownloadStatus())
|
||||
|| Constants.V_GAME_32.equals(gameEntity.getDownloadStatus())) {
|
||||
GameEntity.GameCategory gameCategory = gameEntity.getGameCategory();
|
||||
if (gameCategory.equals(GameEntity.GameCategory.ONLINE_GAME)
|
||||
|| gameCategory.equals(GameEntity.GameCategory.INTERNATIONAL_ONLINE_GAME)) {
|
||||
|
||||
@ -786,7 +786,7 @@ public class LibaoUtils {
|
||||
, "关闭", "启动游戏"
|
||||
, () -> {
|
||||
if (LibaoUtils.isAppInstalled(context, libaoEntity.getPackageName())) {
|
||||
PackageUtils.launchApplicationByPackageName(context, libaoEntity.getPackageName());
|
||||
PackageLauncher.launchApp(context, null, libaoEntity.getPackageName());
|
||||
} else {
|
||||
Utils.toast(context, "请安装游戏:" + libaoEntity.getGame().getName()
|
||||
+ PlatformUtils.getInstance(context).getPlatformName(libaoEntity.getPlatform()) + "版");
|
||||
|
||||
@ -23,6 +23,9 @@ object NewFlatLogUtils {
|
||||
private const val KEY_TEXT = "text"
|
||||
private const val KEY_BUTTON_TYPE = "button_type"
|
||||
private const val KEY_BBS_ID = "bbs_id"
|
||||
private const val KEY_GAME_CATEGORY = "game_category"
|
||||
private const val KEY_DOWNLOAD_STATE = "download_state"
|
||||
private const val KEY_LOCATION = "location"
|
||||
|
||||
private const val EVENT_LOGIN_FROM_GHZS_SHOW = "halo_fun_login_from_ghzs_show"
|
||||
private const val EVENT_LOGIN_FROM_GHZS_CLICK = "halo_fun_login_from_ghzs_click"
|
||||
@ -118,7 +121,7 @@ object NewFlatLogUtils {
|
||||
fun logHaloFunGameDetailJumpClick(downloadStatus: String, gameId: String) {
|
||||
val json = json {
|
||||
KEY_EVENT to "halo_fun_game_detail_jump_click"
|
||||
"download_state" to downloadStatus
|
||||
KEY_DOWNLOAD_STATE to downloadStatus
|
||||
KEY_GAME_ID to gameId
|
||||
parseAndPutMeta().invoke(this)
|
||||
}
|
||||
@ -684,7 +687,7 @@ object NewFlatLogUtils {
|
||||
val json = json {
|
||||
KEY_EVENT to "halo_self_publish_content"
|
||||
"tab_name" to tabName
|
||||
"location" to location
|
||||
KEY_LOCATION to location
|
||||
parseAndPutMeta().invoke(this)
|
||||
}
|
||||
log(json)
|
||||
@ -1052,10 +1055,11 @@ object NewFlatLogUtils {
|
||||
}
|
||||
|
||||
//游戏单广场浏览时长
|
||||
fun logGameCollectSquareStayTime(interval: Long) {
|
||||
fun logGameCollectSquareStayTime(interval: Long, source: String) {
|
||||
val json = json {
|
||||
KEY_EVENT to "game_collect_square_stay_time"
|
||||
"interval" to interval
|
||||
"source" to source
|
||||
parseAndPutMeta().invoke(this)
|
||||
}
|
||||
log(json)
|
||||
@ -1479,7 +1483,7 @@ object NewFlatLogUtils {
|
||||
) {
|
||||
val json = json {
|
||||
KEY_EVENT to "game_detail_comment_tab_game_comment_click"
|
||||
"location" to location
|
||||
KEY_LOCATION to location
|
||||
"tag" to tag
|
||||
"filter_tag_name" to filter
|
||||
"button" to button
|
||||
@ -1521,7 +1525,7 @@ object NewFlatLogUtils {
|
||||
) {
|
||||
val json = json {
|
||||
KEY_EVENT to "game_detail_comment_tab_game_comment_detail_click"
|
||||
"location" to location
|
||||
KEY_LOCATION to location
|
||||
"tag" to tag
|
||||
"filter_tag_name" to filter
|
||||
"button" to button
|
||||
@ -1623,7 +1627,7 @@ object NewFlatLogUtils {
|
||||
val json = json {
|
||||
"event" to "game_test_detail_game_category_click"
|
||||
"tab_name" to tabName
|
||||
"game_category" to gameCategory
|
||||
KEY_GAME_CATEGORY to gameCategory
|
||||
"game_test_start_type" to gameTestStartType
|
||||
parseAndPutMeta().invoke(this)
|
||||
}
|
||||
@ -1658,7 +1662,7 @@ object NewFlatLogUtils {
|
||||
val json = json {
|
||||
"event" to "game_test_home_more_click"
|
||||
"text" to text //右上角文案,包括:全部、更多
|
||||
"location" to location //新游开测所处位置,包括:首页、版块
|
||||
KEY_LOCATION to location //新游开测所处位置,包括:首页、版块
|
||||
"block_id" to blockId //新游开测所处位置为“版块”,上报版块ID
|
||||
"block_name" to blockName //新游开测所处位置为“版块”,上报版块名称
|
||||
"link_type" to linkType //右上角文案为“更多”时的链接类型
|
||||
@ -1685,7 +1689,7 @@ object NewFlatLogUtils {
|
||||
) {
|
||||
val json = json {
|
||||
"event" to "game_test_home_recommend_tag_click"
|
||||
"location" to location //新游开测所处位置,包括:首页、版块
|
||||
KEY_LOCATION to location //新游开测所处位置,包括:首页、版块
|
||||
"block_id" to blockId //新游开测所处位置为“版块”,上报版块ID
|
||||
"block_name" to blockName //新游开测所处位置为“版块”,上报版块名称
|
||||
"tag_id" to tagId //点击推荐标签的ID
|
||||
@ -1733,7 +1737,7 @@ object NewFlatLogUtils {
|
||||
) {
|
||||
val json = json {
|
||||
"event" to "game_test_home_view"
|
||||
"location" to location //新游开测所处位置,包括:首页、版块
|
||||
KEY_LOCATION to location //新游开测所处位置,包括:首页、版块
|
||||
"block_id" to blockId //新游开测所处位置为“版块”,上报版块ID
|
||||
"block_name" to blockName //新游开测所处位置为“版块”,上报版块名称
|
||||
"interval" to interval //内容在屏幕可见范围完整展示的时长
|
||||
@ -1988,7 +1992,7 @@ object NewFlatLogUtils {
|
||||
"type" to homeSubSlide.cardType
|
||||
"text" to homeSubSlide.cardText
|
||||
"count_num" to countNum
|
||||
"location" to location
|
||||
KEY_LOCATION to location
|
||||
"link_type" to homeSubSlide.linkType
|
||||
"link_id" to homeSubSlide.linkId
|
||||
"link_text" to homeSubSlide.linkText
|
||||
@ -2185,4 +2189,155 @@ object NewFlatLogUtils {
|
||||
}
|
||||
log(json, "event", false)
|
||||
}
|
||||
|
||||
// 游戏单广场刷新
|
||||
@JvmStatic
|
||||
fun logGameCollectionSquareFlush(action: String, countNum: Int) {
|
||||
val json = json {
|
||||
KEY_EVENT to "game_list_square_flush"
|
||||
"action" to action
|
||||
"count_num" to countNum
|
||||
parseAndPutMeta().invoke(this)
|
||||
}
|
||||
log(json)
|
||||
}
|
||||
|
||||
// 游戏详情点击公告文章
|
||||
@JvmStatic
|
||||
fun logGameDetailNoticeClick(gameId: String, gameName: String, linkId: String, linkType: String, linkText: String) {
|
||||
val json = json {
|
||||
KEY_EVENT to "game_detail_notice_click"
|
||||
KEY_GAME_ID to gameId
|
||||
KEY_GAME_NAME to gameName
|
||||
"link_id" to linkId
|
||||
"link_type" to linkType
|
||||
"link_text" to linkText
|
||||
parseAndPutMeta().invoke(this)
|
||||
}
|
||||
log(json)
|
||||
}
|
||||
|
||||
// 启动游戏(UI被点击)
|
||||
fun logGameLaunchButtonClicked(
|
||||
gameId: String,
|
||||
gameName: String,
|
||||
location: String,
|
||||
gameCategory: String,
|
||||
downloadStatus: String
|
||||
) {
|
||||
val json = json {
|
||||
KEY_EVENT to "game_launch_button_click"
|
||||
KEY_GAME_ID to gameId
|
||||
KEY_GAME_NAME to gameName
|
||||
KEY_LOCATION to location
|
||||
KEY_GAME_CATEGORY to gameCategory
|
||||
KEY_DOWNLOAD_STATE to downloadStatus
|
||||
parseAndPutMeta().invoke(this)
|
||||
}
|
||||
log(json)
|
||||
}
|
||||
|
||||
// 启动游戏(具体实现逻辑)
|
||||
fun logGameLaunch(
|
||||
gameId: String,
|
||||
gameName: String,
|
||||
gameCategory: String,
|
||||
downloadStatus: String
|
||||
) {
|
||||
val json = json {
|
||||
KEY_EVENT to "game_launch"
|
||||
KEY_GAME_ID to gameId
|
||||
KEY_GAME_NAME to gameName
|
||||
KEY_GAME_CATEGORY to gameCategory
|
||||
KEY_DOWNLOAD_STATE to downloadStatus
|
||||
parseAndPutMeta().invoke(this)
|
||||
}
|
||||
log(json)
|
||||
}
|
||||
|
||||
// 进入游戏单热榜
|
||||
@JvmStatic
|
||||
fun logGameCollectionHotListEnter(entrance: String) {
|
||||
val json = json {
|
||||
KEY_EVENT to "game_list_hot_rank_enter"
|
||||
"entrance" to entrance
|
||||
parseAndPutMeta().invoke(this)
|
||||
}
|
||||
log(json)
|
||||
}
|
||||
|
||||
// 离开游戏单热榜
|
||||
@JvmStatic
|
||||
fun logGameCollectionHotListExit(interval: Long, tabName: String) {
|
||||
val json = json {
|
||||
KEY_EVENT to "game_list_hot_rank_exit"
|
||||
"interval" to interval
|
||||
"tab_name" to tabName
|
||||
parseAndPutMeta().invoke(this)
|
||||
}
|
||||
log(json)
|
||||
}
|
||||
|
||||
// 游戏热榜点击tab
|
||||
@JvmStatic
|
||||
fun logGameCollectionHotListTabClick(tabName: String, collectionId: String, collectionName: String) {
|
||||
val json = json {
|
||||
KEY_EVENT to "game_hot_rank_tab_click"
|
||||
"tab_name" to tabName
|
||||
"game_list_collection_id" to collectionId
|
||||
"game_list_collection_name" to collectionName
|
||||
parseAndPutMeta().invoke(this)
|
||||
}
|
||||
log(json)
|
||||
}
|
||||
|
||||
// 游戏热榜tab浏览
|
||||
@JvmStatic
|
||||
fun logGameCollectionHotListTabView(interval: Int, tabName: String, collectionId: String, collectionName: String) {
|
||||
val json = json {
|
||||
KEY_EVENT to "game_hot_rank_tab_view"
|
||||
"interval" to interval
|
||||
"tab_name" to tabName
|
||||
"game_list_collection_id" to collectionId
|
||||
"game_list_collection_name" to collectionName
|
||||
parseAndPutMeta().invoke(this)
|
||||
}
|
||||
log(json)
|
||||
}
|
||||
|
||||
// 游戏单热榜点击
|
||||
@JvmStatic
|
||||
fun logGameCollectionHotListClick(tabName: String, collectionId: String, collectionName: String, text: String) {
|
||||
val json = json {
|
||||
KEY_EVENT to "game_list_hot_rank_click"
|
||||
"tab_name" to tabName
|
||||
"game_list_collection_id" to collectionId
|
||||
"game_list_collection_name" to collectionName
|
||||
"text" to text
|
||||
parseAndPutMeta().invoke(this)
|
||||
}
|
||||
log(json)
|
||||
}
|
||||
|
||||
// 游戏单合集点击
|
||||
fun logGameListCollectionClick(
|
||||
source: String,
|
||||
blockName: String,
|
||||
blockId: String,
|
||||
collectionName: String,
|
||||
collectionId: String,
|
||||
text: String
|
||||
) {
|
||||
val json = json {
|
||||
KEY_EVENT to "game_list_collection_click"
|
||||
"source" to source
|
||||
"block_name" to blockName
|
||||
"block_id" to blockId
|
||||
"game_list_collection_id" to collectionId
|
||||
"game_list_collection_name" to collectionName
|
||||
"text" to text
|
||||
parseAndPutMeta().invoke(this)
|
||||
}
|
||||
log(json)
|
||||
}
|
||||
}
|
||||
@ -1657,13 +1657,22 @@ object NewLogUtils {
|
||||
}
|
||||
|
||||
//进入游戏单广场
|
||||
fun logEnterGameCollectionSquare(entrance: String, forumName: String = "", title: String = "", id: String = "") {
|
||||
fun logEnterGameCollectionSquare(
|
||||
entrance: String,
|
||||
forumName: String = "",
|
||||
gameCollectionTitle: String = "",
|
||||
gameCollectionId: String = "",
|
||||
collectionName: String = "",
|
||||
collectionId: String = ""
|
||||
) {
|
||||
val json = json {
|
||||
KEY_EVENT to "enter_game_collect_square"
|
||||
KEY_ENTRANCE to entrance
|
||||
"forum_name" to forumName
|
||||
"game_collect_title" to title
|
||||
"game_collect_id" to id
|
||||
"game_collect_title" to gameCollectionTitle
|
||||
"game_collect_id" to gameCollectionId
|
||||
"game_list_collection_name" to collectionName
|
||||
"game_list_collection_id" to collectionId
|
||||
KEY_TIMESTAMP to System.currentTimeMillis() / 1000
|
||||
parseAndPutMeta().invoke(this)
|
||||
}
|
||||
@ -1671,9 +1680,10 @@ object NewLogUtils {
|
||||
}
|
||||
|
||||
//进入选择标签
|
||||
fun logEnterGameCollectionTag() {
|
||||
fun logEnterGameCollectionTag(source: String) {
|
||||
val json = json {
|
||||
KEY_EVENT to "enter_game_collect_tag_location"
|
||||
"source" to source
|
||||
KEY_TIMESTAMP to System.currentTimeMillis() / 1000
|
||||
parseAndPutMeta().invoke(this)
|
||||
}
|
||||
@ -1681,11 +1691,12 @@ object NewLogUtils {
|
||||
}
|
||||
|
||||
//筛选游戏单标签
|
||||
fun logFilterGameCollectionTag(tagCategory: String, tagName: String) {
|
||||
fun logFilterGameCollectionTag(tagCategory: String, tagName: String, source: String) {
|
||||
val json = json {
|
||||
KEY_EVENT to "filter_game_collect_tag"
|
||||
"filter_tag_category" to tagCategory
|
||||
"filter_tag_name" to tagName
|
||||
"source" to source
|
||||
KEY_TIMESTAMP to System.currentTimeMillis() / 1000
|
||||
parseAndPutMeta().invoke(this)
|
||||
}
|
||||
@ -1693,9 +1704,10 @@ object NewLogUtils {
|
||||
}
|
||||
|
||||
//点击安利墙卡片
|
||||
fun logClickGameCollectionAmway() {
|
||||
fun logClickGameCollectionAmway(tabName: String) {
|
||||
val json = json {
|
||||
KEY_EVENT to "click_game_collect_recommend_card"
|
||||
"tab_name" to tabName
|
||||
KEY_TIMESTAMP to System.currentTimeMillis() / 1000
|
||||
parseAndPutMeta().invoke(this)
|
||||
}
|
||||
|
||||
@ -1,14 +1,19 @@
|
||||
package com.gh.common.util
|
||||
|
||||
import android.app.Activity
|
||||
import android.app.PendingIntent
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.pm.PackageInstaller.SessionCallback
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.util.Log
|
||||
import android.view.View
|
||||
import androidx.annotation.RequiresApi
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.content.FileProvider
|
||||
import com.gh.common.dialog.InstallPermissionDialogFragment
|
||||
import com.gh.common.xapk.XapkInstallReceiver
|
||||
import com.gh.common.xapk.XapkInstaller
|
||||
import com.gh.download.server.BrowserInstallHelper
|
||||
import com.gh.gamecenter.BuildConfig
|
||||
@ -16,6 +21,7 @@ import com.gh.gamecenter.common.constant.Constants
|
||||
import com.gh.gamecenter.common.utils.DialogHelper
|
||||
import com.gh.gamecenter.common.utils.getExtension
|
||||
import com.gh.gamecenter.common.utils.getMetaExtra
|
||||
import com.gh.gamecenter.core.AppExecutor
|
||||
import com.gh.gamecenter.core.utils.CurrentActivityHolder
|
||||
import com.gh.gamecenter.core.utils.MD5Utils
|
||||
import com.gh.gamecenter.core.utils.ToastUtils
|
||||
@ -142,6 +148,32 @@ object PackageInstaller {
|
||||
context.startActivity(installIntent)
|
||||
}
|
||||
|
||||
fun installMultiple(
|
||||
context: Context,
|
||||
pkgPath: String,
|
||||
sessionId: Int = -1
|
||||
) {
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
|
||||
return
|
||||
}
|
||||
val installer = context.packageManager.packageInstaller
|
||||
val session = installer.openSession(sessionId)
|
||||
// 监听安装回调的组件,可以是Activity、Service或者是BroadcastReceiver
|
||||
val intent = Intent(context, XapkInstallReceiver::class.java)
|
||||
.also {
|
||||
it.putExtra(XapkInstallReceiver.KEY_PACKAGE_PATH, pkgPath)
|
||||
}
|
||||
|
||||
val flags = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
||||
PendingIntent.FLAG_MUTABLE or PendingIntent.FLAG_CANCEL_CURRENT
|
||||
} else {
|
||||
PendingIntent.FLAG_CANCEL_CURRENT
|
||||
}
|
||||
val pendingIntent = PendingIntent.getActivity(context, sessionId, intent, flags)
|
||||
// 提交数据流并执行安装
|
||||
session.commit(pendingIntent.intentSender)
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取启动安装意图
|
||||
*
|
||||
@ -216,7 +248,8 @@ object PackageInstaller {
|
||||
}
|
||||
|
||||
private fun getFileSuffixByFormat(format: String?): String {
|
||||
return if (format == XapkInstaller.XAPK_EXTENSION_NAME) {
|
||||
return if (format == Constants.XAPK_FORMAT
|
||||
|| format == Constants.XAPK_APKS_FORMAT) {
|
||||
XapkInstaller.XAPK_EXTENSION_NAME
|
||||
} else {
|
||||
"apk"
|
||||
|
||||
54
app/src/main/java/com/gh/common/util/PackageLauncher.kt
Normal file
54
app/src/main/java/com/gh/common/util/PackageLauncher.kt
Normal file
@ -0,0 +1,54 @@
|
||||
package com.gh.common.util
|
||||
|
||||
import android.content.Context
|
||||
import com.gh.gamecenter.core.utils.ToastUtils
|
||||
import com.gh.gamecenter.entity.GameInstall
|
||||
import com.gh.gamecenter.feature.entity.GameEntity
|
||||
import com.gh.gamecenter.packagehelper.PackageRepository
|
||||
|
||||
object PackageLauncher {
|
||||
|
||||
/*
|
||||
* 启动应用
|
||||
*/
|
||||
@JvmStatic
|
||||
fun launchApp(
|
||||
context: Context,
|
||||
gameEntity: GameEntity? = null,
|
||||
packageName: String?
|
||||
) {
|
||||
|
||||
if (packageName.isNullOrEmpty()) {
|
||||
ToastUtils.toast("启动失败")
|
||||
return
|
||||
}
|
||||
|
||||
// 获取 GameInstall 实体,用于记录启动日志用
|
||||
val gameInstall = if (gameEntity != null) {
|
||||
GameInstall.transformGameInstall(gameEntity, packageName)
|
||||
} else {
|
||||
PackageRepository.gameInstalled.find { it.packageName == packageName }
|
||||
}
|
||||
|
||||
if (gameInstall != null) {
|
||||
NewFlatLogUtils.logGameLaunch(
|
||||
gameId = gameInstall.id ?: "unknown",
|
||||
gameName = gameInstall.name ?: "unknown",
|
||||
gameCategory = gameInstall.category ?: "unknown",
|
||||
downloadStatus = if (gameInstall.downloadStatus == "demo") "试玩" else "下载"
|
||||
)
|
||||
}
|
||||
|
||||
try {
|
||||
val intent = context.applicationContext.packageManager.getLaunchIntentForPackage(packageName)
|
||||
if (intent != null) {
|
||||
context.startActivity(intent)
|
||||
} else {
|
||||
ToastUtils.toast("启动失败")
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
ToastUtils.toast( "启动失败")
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -746,9 +746,11 @@ public class PackageUtils {
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
/**
|
||||
* 启动应用
|
||||
* 请使用 PackageLauncher.launchApp()
|
||||
*/
|
||||
@Deprecated
|
||||
public static void launchApplicationByPackageName(Context context, String packageName) {
|
||||
try {
|
||||
Intent intent = context.getApplicationContext().getPackageManager().getLaunchIntentForPackage(packageName);
|
||||
|
||||
@ -66,7 +66,7 @@ object RealNameHelper {
|
||||
"game_name",
|
||||
downloadEntity.name ?: "",
|
||||
"game_type",
|
||||
downloadEntity.meta[Constants.GAME_TYPE] ?: ""
|
||||
downloadEntity.meta[Constants.GAME_CATEGORY_IN_CHINESE] ?: ""
|
||||
)
|
||||
|
||||
val contentText = if (downloadEntity.status == DownloadStatus.done) {
|
||||
|
||||
59
app/src/main/java/com/gh/common/xapk/XapkInstallReceiver.kt
Normal file
59
app/src/main/java/com/gh/common/xapk/XapkInstallReceiver.kt
Normal file
@ -0,0 +1,59 @@
|
||||
package com.gh.common.xapk
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.pm.PackageInstaller
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import androidx.annotation.RequiresApi
|
||||
|
||||
@RequiresApi(Build.VERSION_CODES.LOLLIPOP)
|
||||
class XapkInstallReceiver : Activity() {
|
||||
|
||||
companion object {
|
||||
const val KEY_PACKAGE_PATH = "package_path"
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
overridePendingTransition(0, 0)
|
||||
handleIntent(this, intent)
|
||||
|
||||
}
|
||||
|
||||
private fun handleIntent(context: Context, intent: Intent) {
|
||||
when (intent.getIntExtra(PackageInstaller.EXTRA_STATUS, -999)) {
|
||||
PackageInstaller.STATUS_PENDING_USER_ACTION -> {
|
||||
val installIntent = intent.getParcelableExtra<Intent>(Intent.EXTRA_INTENT)
|
||||
if (installIntent != null) {
|
||||
context.startActivity(installIntent)
|
||||
updatePendingSessionInfoStatus(intent, XapkPendingSessionInfo.STATUS_PENDING_USER_ACTION)
|
||||
finish()
|
||||
}
|
||||
}
|
||||
PackageInstaller.STATUS_FAILURE,
|
||||
PackageInstaller.STATUS_FAILURE_ABORTED,
|
||||
PackageInstaller.STATUS_FAILURE_BLOCKED,
|
||||
PackageInstaller.STATUS_FAILURE_CONFLICT,
|
||||
PackageInstaller.STATUS_FAILURE_INCOMPATIBLE,
|
||||
PackageInstaller.STATUS_FAILURE_INVALID,
|
||||
PackageInstaller.STATUS_FAILURE_STORAGE -> {
|
||||
updatePendingSessionInfoStatus(intent, XapkPendingSessionInfo.STATUS_INSTALL_CANCELED)
|
||||
finish()
|
||||
}
|
||||
else -> {
|
||||
updatePendingSessionInfoStatus(intent, XapkPendingSessionInfo.STATUS_INSTALL_SUCCESS)
|
||||
finish()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun updatePendingSessionInfoStatus(intent: Intent, status: Int) {
|
||||
val installPackagePath = intent.getStringExtra(KEY_PACKAGE_PATH)
|
||||
if (!installPackagePath.isNullOrEmpty()) {
|
||||
val pendingSessionInfo = XapkInstaller.getPendingSessionInfo(installPackagePath)
|
||||
pendingSessionInfo?.updateStatus(status)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2,20 +2,30 @@ package com.gh.common.xapk
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import android.os.Build
|
||||
import com.gh.common.util.*
|
||||
import com.gh.download.DownloadDataHelper
|
||||
import com.gh.download.DownloadManager
|
||||
import com.gh.gamecenter.common.utils.debugOnly
|
||||
import com.gh.gamecenter.common.utils.getExtension
|
||||
import com.gh.gamecenter.common.utils.throwExceptionInDebug
|
||||
import com.gh.gamecenter.common.utils.tryCatchInRelease
|
||||
import com.gh.gamecenter.core.AppExecutor
|
||||
import com.gh.gamecenter.core.utils.SentryHelper
|
||||
import com.gh.gamecenter.xapk.XApkUnZipper
|
||||
import com.gh.gamecenter.xapk.core.XApkFile
|
||||
import com.gh.gamecenter.xapk.core.XApkUnZipCallback
|
||||
import com.gh.gamecenter.xapk.core.XApkUnZipEntry
|
||||
import com.gh.gamecenter.xapk.core.XApkUnZipOutputFactory
|
||||
import com.gh.gamecenter.xapk.io.NonSplitApksOutput
|
||||
import com.gh.gamecenter.xapk.io.OBBFileOutput
|
||||
import com.gh.gamecenter.xapk.io.SplitApksOutput
|
||||
import com.gh.gamecenter.xapk.io.XApkFileOutput
|
||||
import com.gh.gamecenter.xapk.pi.IPackageInstaller
|
||||
import com.gh.ndownload.NDataChanger
|
||||
import com.halo.assistant.HaloApp
|
||||
import com.lightgame.download.DownloadEntity
|
||||
import com.lightgame.utils.Utils
|
||||
import java.text.DecimalFormat
|
||||
import java.io.File
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
@ -28,7 +38,8 @@ import java.util.*
|
||||
* apk文件这解压的gh-files文件夹中
|
||||
*/
|
||||
@SuppressLint("StaticFieldLeak")
|
||||
object XapkInstaller : IXapkUnzipListener {
|
||||
object XapkInstaller : XApkUnZipCallback, XApkUnZipOutputFactory {
|
||||
|
||||
private const val XAPK_PACKAGE_PATH_TAG = "xapk_package_path"
|
||||
|
||||
const val XAPK_EXTENSION_NAME = "xapk"
|
||||
@ -42,8 +53,14 @@ object XapkInstaller : IXapkUnzipListener {
|
||||
|
||||
private var mContext = HaloApp.getInstance().application.applicationContext
|
||||
|
||||
// 是否需要开启特定线程处理
|
||||
private val mXapkUnzipThreadMap = Collections.synchronizedMap(HashMap<String, XapkUnzipThread>())
|
||||
private val mXApkUnZipper = XApkUnZipper(this)
|
||||
.also {
|
||||
it.registerCallback(this)
|
||||
}
|
||||
|
||||
private val mDownloadEntityMap = Collections.synchronizedMap(HashMap<String, DownloadEntity>())
|
||||
|
||||
private val mPendingSessionInfoMap = HashMap<String, XapkPendingSessionInfo>()
|
||||
|
||||
// 按并行解压
|
||||
@JvmStatic
|
||||
@ -63,122 +80,227 @@ object XapkInstaller : IXapkUnzipListener {
|
||||
}
|
||||
|
||||
private fun unzipXapkFile(downloadEntity: DownloadEntity) {
|
||||
if (mXapkUnzipThreadMap[downloadEntity.path] == null) {
|
||||
DownloadDataHelper.uploadDownloadStatusEvent(downloadEntity, "xapk解压开始")
|
||||
val xapkUnzipThread = XapkUnzipThread(downloadEntity, this)
|
||||
xapkUnzipThread.start()
|
||||
mXapkUnzipThreadMap[downloadEntity.path] = xapkUnzipThread
|
||||
} else {
|
||||
debugOnly {
|
||||
Utils.log("unzip", "重复解压,该文件解压已在队列中")
|
||||
}
|
||||
}
|
||||
mXApkUnZipper.unzip(
|
||||
XApkUnZipEntry(
|
||||
downloadEntity.path,
|
||||
File(downloadEntity.path)
|
||||
)
|
||||
)
|
||||
mDownloadEntityMap[downloadEntity.path] = downloadEntity
|
||||
}
|
||||
|
||||
override fun onProgress(downloadEntity: DownloadEntity, unzipPath: String, unzipSize: Long, unzipProgress: Long) {
|
||||
AppExecutor.uiExecutor.execute {
|
||||
val df = DecimalFormat("#.0")
|
||||
var percent = 0.0
|
||||
tryCatchInRelease {
|
||||
percent = df.format((unzipProgress / unzipSize.toFloat()) * 100).toDouble()
|
||||
}
|
||||
downloadEntity.meta[XAPK_UNZIP_PERCENT] = percent.toString()
|
||||
downloadEntity.meta[XAPK_UNZIP_STATUS] = XapkUnzipStatus.UNZIPPING.name
|
||||
@JvmStatic
|
||||
fun cancelUnzipTask(downloadEntity: DownloadEntity) {
|
||||
mXApkUnZipper.cancel(downloadEntity.path)
|
||||
}
|
||||
|
||||
override fun onProgress(apk: XApkFile, progress: Float) {
|
||||
val downloadEntity = mDownloadEntityMap[apk.file.path] ?: return
|
||||
downloadEntity.meta[XAPK_UNZIP_PERCENT] = String.format("%.2f", progress * 100)
|
||||
downloadEntity.meta[XAPK_UNZIP_STATUS] = XapkUnzipStatus.UNZIPPING.name
|
||||
|
||||
AppExecutor.ioExecutor.execute {
|
||||
NDataChanger.notifyDataChanged(downloadEntity)
|
||||
}
|
||||
|
||||
debugOnly {
|
||||
Utils.log("unzip", "onProgress->" + (unzipProgress / unzipSize.toFloat()))
|
||||
Utils.log("unzip", "onProgress->$progress")
|
||||
}
|
||||
}
|
||||
|
||||
override fun onNext(downloadEntity: DownloadEntity, unzipPath: String) {
|
||||
if (PACKAGE_EXTENSION_NAME == unzipPath.getExtension()) {
|
||||
downloadEntity.meta[XAPK_PACKAGE_PATH_TAG] = unzipPath
|
||||
override fun onSuccess(apk: XApkFile, installer: IPackageInstaller) {
|
||||
val downloadEntity = mDownloadEntityMap[apk.file.path] ?: return
|
||||
|
||||
downloadEntity.meta[XAPK_UNZIP_PERCENT] = "100.0"
|
||||
downloadEntity.meta[XAPK_UNZIP_STATUS] = XapkUnzipStatus.SUCCESS.name
|
||||
|
||||
AppExecutor.ioExecutor.execute {
|
||||
NDataChanger.notifyDataChanged(downloadEntity)
|
||||
DownloadManager.getInstance().updateDownloadEntity(downloadEntity)
|
||||
DownloadDataHelper.uploadDownloadStatusEvent(downloadEntity, "xapk解压成功")
|
||||
}
|
||||
|
||||
debugOnly {
|
||||
Utils.log("unzip", "onNext->$unzipPath")
|
||||
Utils.log("unzip", "onSuccess->${downloadEntity.path}")
|
||||
}
|
||||
|
||||
installer.install(mContext)
|
||||
}
|
||||
|
||||
/**
|
||||
* 取消解压回调
|
||||
*
|
||||
* 取消后的表现与下载完成一致
|
||||
*/
|
||||
override fun onCancel(downloadEntity: DownloadEntity) {
|
||||
mXapkUnzipThreadMap.remove(downloadEntity.path)
|
||||
override fun onError(apk: XApkFile, exception: Throwable) {
|
||||
val downloadEntity = mDownloadEntityMap[apk.file.path] ?: return
|
||||
downloadEntity.meta[XAPK_UNZIP_STATUS] = XapkUnzipStatus.FAILURE.name
|
||||
|
||||
AppExecutor.uiExecutor.execute {
|
||||
downloadEntity.meta[XAPK_UNZIP_PERCENT] = "0.0"
|
||||
downloadEntity.meta[XAPK_UNZIP_STATUS] = XapkUnzipStatus.CANCEL.name
|
||||
NDataChanger.notifyDataChanged(downloadEntity)
|
||||
DownloadManager.getInstance().updateDownloadEntity(downloadEntity)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onFailure(downloadEntity: DownloadEntity, exception: Exception) {
|
||||
mXapkUnzipThreadMap.remove(downloadEntity.path)
|
||||
|
||||
AppExecutor.uiExecutor.execute {
|
||||
downloadEntity.meta[XAPK_UNZIP_STATUS] = XapkUnzipStatus.FAILURE.name
|
||||
AppExecutor.ioExecutor.execute {
|
||||
DownloadNotificationHelper.addOrUpdateDownloadNotification(downloadEntity)
|
||||
NDataChanger.notifyDataChanged(downloadEntity)
|
||||
DownloadManager.getInstance().updateDownloadEntity(downloadEntity)
|
||||
}
|
||||
// 仅官网渠道上报 XAPK 异常信息
|
||||
if (HaloApp.getInstance().channel == "GH_206") {
|
||||
SentryHelper.onEvent(
|
||||
"XAPK_UNZIP_ERROR",
|
||||
"gameName", downloadEntity.name,
|
||||
"errorDigest", exception.localizedMessage
|
||||
)
|
||||
}
|
||||
|
||||
// 仅官网渠道上报 XAPK 异常信息
|
||||
if (HaloApp.getInstance().channel == "GH_206") {
|
||||
SentryHelper.onEvent(
|
||||
"XAPK_UNZIP_ERROR",
|
||||
"gameName", downloadEntity.name,
|
||||
"errorDigest", exception.localizedMessage
|
||||
)
|
||||
DownloadDataHelper.uploadDownloadStatusEvent(downloadEntity, "xapk解压失败")
|
||||
}
|
||||
|
||||
DownloadDataHelper.uploadDownloadStatusEvent(downloadEntity, "xapk解压失败")
|
||||
|
||||
debugOnly {
|
||||
Utils.log("unzip", "onFailure->$exception")
|
||||
}
|
||||
}
|
||||
|
||||
override fun onSuccess(downloadEntity: DownloadEntity) {
|
||||
mXapkUnzipThreadMap.remove(downloadEntity.path)
|
||||
|
||||
AppExecutor.uiExecutor.execute {
|
||||
val pkgPath = downloadEntity.meta[XAPK_PACKAGE_PATH_TAG]
|
||||
|
||||
if (pkgPath == null) {
|
||||
Utils.toast(mContext, "下载出错,请重新下载!")
|
||||
|
||||
return@execute
|
||||
}
|
||||
|
||||
PackageInstaller.install(mContext, downloadEntity.isPlugin, pkgPath, downloadEntity)
|
||||
|
||||
downloadEntity.meta[XAPK_UNZIP_PERCENT] = "100.0"
|
||||
downloadEntity.meta[XAPK_UNZIP_STATUS] = XapkUnzipStatus.SUCCESS.name
|
||||
override fun onCancel(apk: XApkFile) {
|
||||
val downloadEntity = mDownloadEntityMap.remove(apk.file.path) ?: return
|
||||
downloadEntity.meta[XAPK_UNZIP_PERCENT] = "0.0"
|
||||
downloadEntity.meta[XAPK_UNZIP_STATUS] = XapkUnzipStatus.CANCEL.name
|
||||
AppExecutor.ioExecutor.execute {
|
||||
NDataChanger.notifyDataChanged(downloadEntity)
|
||||
DownloadManager.getInstance().updateDownloadEntity(downloadEntity)
|
||||
}
|
||||
}
|
||||
|
||||
DownloadDataHelper.uploadDownloadStatusEvent(downloadEntity, "xapk解压成功")
|
||||
|
||||
override fun onNext(apk: XApkFile, fileName: String) {
|
||||
debugOnly {
|
||||
Utils.log("unzip", "onSuccess->${downloadEntity.path}")
|
||||
Utils.log("unzip", "onNext->$fileName")
|
||||
}
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun cancelUnzipTask(downloadEntity: DownloadEntity) {
|
||||
val xapkUnzipThread = mXapkUnzipThreadMap[downloadEntity.path]
|
||||
if (xapkUnzipThread != null) {
|
||||
xapkUnzipThread.canceled = true
|
||||
fun getPendingSessionInfo(packagePath: String): XapkPendingSessionInfo? = mPendingSessionInfoMap[packagePath]
|
||||
|
||||
fun isInstalling(packagePath: String): Boolean = mPendingSessionInfoMap.containsKey(packagePath)
|
||||
|
||||
/**
|
||||
* 通知XAPK安装完成
|
||||
*/
|
||||
fun onInstalled(packagePath: String) {
|
||||
val downloadEntity = mDownloadEntityMap.remove(packagePath) ?: return
|
||||
|
||||
mPendingSessionInfoMap.remove(packagePath)
|
||||
|
||||
downloadEntity.meta[XAPK_UNZIP_PERCENT] = "100.0"
|
||||
downloadEntity.meta[XAPK_UNZIP_STATUS] = XapkUnzipStatus.INSTALLED.name
|
||||
|
||||
AppExecutor.ioExecutor.execute {
|
||||
NDataChanger.notifyDataChanged(downloadEntity)
|
||||
DownloadManager.getInstance().updateDownloadEntity(downloadEntity)
|
||||
DownloadDataHelper.uploadDownloadStatusEvent(downloadEntity, "xapk安装成功")
|
||||
}
|
||||
}
|
||||
|
||||
fun onInstallCanceled(packagePath: String) {
|
||||
|
||||
val downloadEntity = mDownloadEntityMap.remove(packagePath) ?: return
|
||||
|
||||
mPendingSessionInfoMap.remove(packagePath)
|
||||
|
||||
downloadEntity.meta[XAPK_UNZIP_PERCENT] = "0.0"
|
||||
downloadEntity.meta[XAPK_UNZIP_STATUS] = XapkUnzipStatus.CANCEL.name
|
||||
|
||||
AppExecutor.ioExecutor.execute {
|
||||
NDataChanger.notifyDataChanged(downloadEntity)
|
||||
DownloadManager.getInstance().updateDownloadEntity(downloadEntity)
|
||||
DownloadDataHelper.uploadDownloadStatusEvent(downloadEntity, "xapk安装取消")
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新当前XAPK安装状态, 主要针对以下出现安装结果回调异常的情况:
|
||||
* 1. 用户触碰安装弹窗(原生Android系统)区域外导致安装取消
|
||||
*/
|
||||
fun updateCurrentInstallStatus() {
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP || mPendingSessionInfoMap.isEmpty()) {
|
||||
return
|
||||
}
|
||||
|
||||
val updateList = mutableListOf<XapkPendingSessionInfo>()
|
||||
|
||||
for (pendingSessionInfoEntry in mPendingSessionInfoMap) {
|
||||
|
||||
val pendingSessionInfo = pendingSessionInfoEntry.value
|
||||
|
||||
if (pendingSessionInfo.getStatus() == XapkPendingSessionInfo.STATUS_PENDING_USER_ACTION) {// 用户触摸安装弹窗外部区域取消安装后,更新安装状态
|
||||
val installer = mContext.packageManager.packageInstaller
|
||||
val sessionId = pendingSessionInfo.sessionId
|
||||
if (sessionId != -1) {
|
||||
val sessionInfo = installer.getSessionInfo(sessionId)
|
||||
// 表示用户点击了安装弹窗外部区域
|
||||
if (sessionInfo != null && sessionInfo.progress <= 0.8F) {
|
||||
AppExecutor.ioExecutor.execute {
|
||||
installer.abandonSession(sessionInfo.sessionId)
|
||||
}
|
||||
pendingSessionInfo.updateStatus(XapkPendingSessionInfo.STATUS_INSTALL_CANCELED)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val installStatus = pendingSessionInfo.getStatus()
|
||||
if (installStatus == XapkPendingSessionInfo.STATUS_INSTALL_CANCELED
|
||||
|| installStatus == XapkPendingSessionInfo.STATUS_INSTALL_SUCCESS
|
||||
) {
|
||||
updateList.add(pendingSessionInfo)
|
||||
}
|
||||
}
|
||||
|
||||
for (pendingSessionInfo in updateList) {
|
||||
val downloadEntity = mDownloadEntityMap[pendingSessionInfo.path] ?: continue
|
||||
val installStatus = pendingSessionInfo.getStatus()
|
||||
if (installStatus == XapkPendingSessionInfo.STATUS_INSTALL_SUCCESS) {
|
||||
onInstalled(downloadEntity.path)
|
||||
} else if (installStatus == XapkPendingSessionInfo.STATUS_INSTALL_CANCELED) {
|
||||
onInstallCanceled(downloadEntity.path)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreateOBBOutput(apk: XApkFile): XApkFileOutput<Unit> {
|
||||
return OBBFileOutput()
|
||||
}
|
||||
|
||||
override fun onCreateApkOutput(apk: XApkFile): XApkFileOutput<IPackageInstaller> {
|
||||
val isMultiApks = apk.manifest.isMultiApks
|
||||
return if (isMultiApks) {
|
||||
SplitApksOutput(mContext.applicationContext) {
|
||||
SplitApksInstaller(apk, it)
|
||||
}
|
||||
} else {
|
||||
onCancel(downloadEntity) // 刷新页面
|
||||
NonSplitApksOutput {
|
||||
NonSplitApkInstaller(apk, it)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class SplitApksInstaller(
|
||||
private val xApkFile: XApkFile,
|
||||
private val sessionId: Int,
|
||||
) : IPackageInstaller {
|
||||
|
||||
override fun install(context: Context) {
|
||||
val downloadEntity = mDownloadEntityMap[xApkFile.file.path] ?: return
|
||||
val applicationContext = context.applicationContext
|
||||
mPendingSessionInfoMap[downloadEntity.path] = XapkPendingSessionInfo(downloadEntity.path, sessionId)
|
||||
AppExecutor.ioExecutor.execute {// 有可能卡顿造成anr
|
||||
NDataChanger.notifyDataChanged(downloadEntity)
|
||||
PackageInstaller.installMultiple(applicationContext, downloadEntity.path, sessionId)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class NonSplitApkInstaller(
|
||||
private val xApkFile: XApkFile,
|
||||
private val file: File
|
||||
) : IPackageInstaller {
|
||||
|
||||
override fun install(context: Context) {
|
||||
val downloadEntity = mDownloadEntityMap[xApkFile.file.path] ?: return
|
||||
PackageInstaller.install(
|
||||
context,
|
||||
downloadEntity.isPlugin,
|
||||
file.absolutePath,
|
||||
downloadEntity
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -187,5 +309,7 @@ enum class XapkUnzipStatus(status: String) {
|
||||
UNZIPPING("unzipping"),
|
||||
SUCCESS("success"),
|
||||
CANCEL("cancel"),
|
||||
INSTALLING("installing"),
|
||||
INSTALLED("installed"),
|
||||
FAILURE("failure");
|
||||
}
|
||||
@ -0,0 +1,21 @@
|
||||
package com.gh.common.xapk
|
||||
|
||||
class XapkPendingSessionInfo(
|
||||
val path: String,
|
||||
val sessionId: Int = -1
|
||||
) {
|
||||
companion object {
|
||||
const val STATUS_INIT = -1
|
||||
const val STATUS_PENDING_USER_ACTION = 0
|
||||
const val STATUS_INSTALL_SUCCESS = 1
|
||||
const val STATUS_INSTALL_CANCELED = 2
|
||||
}
|
||||
|
||||
private var status = STATUS_INIT
|
||||
|
||||
internal fun updateStatus(status: Int) {
|
||||
this.status = status
|
||||
}
|
||||
|
||||
fun getStatus(): Int = status
|
||||
}
|
||||
@ -128,7 +128,7 @@ object DownloadDataHelper {
|
||||
payloadObject.put("package", downloadEntity.packageName)
|
||||
payloadObject.put("certification", RealNameHelper.getCertificationStatus())
|
||||
payloadObject.put("filename", getFileName(downloadEntity))
|
||||
payloadObject.put("task_num", NDataChanger.downloadingTasks.size)
|
||||
payloadObject.put("task_num", NDataChanger.downloadingTaskUrlSet.size)
|
||||
jsonObject.put("payload", payloadObject)
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
@ -214,7 +214,7 @@ object DownloadDataHelper {
|
||||
payloadObject.put("certification", RealNameHelper.getCertificationStatus())
|
||||
payloadObject.put("filename", getFileName(downloadEntity))
|
||||
payloadObject.put("launch_ms", startupTime)
|
||||
payloadObject.put("task_num", NDataChanger.downloadingTasks.size)
|
||||
payloadObject.put("task_num", NDataChanger.downloadingTaskUrlSet.size)
|
||||
if (parallel != null) {
|
||||
payloadObject.put("parallel", parallel)
|
||||
}
|
||||
@ -276,7 +276,7 @@ object DownloadDataHelper {
|
||||
payloadObject.put("speed", speed)
|
||||
}
|
||||
} else {
|
||||
payloadObject.put("task_num", NDataChanger.downloadingTasks.size)
|
||||
payloadObject.put("task_num", NDataChanger.downloadingTaskUrlSet.size)
|
||||
}
|
||||
payloadObject.put("completed_size", downloadEntity.progress / 1024 / 1024)
|
||||
if (downloadEntity.status == DownloadStatus.resume) {
|
||||
@ -329,7 +329,7 @@ object DownloadDataHelper {
|
||||
if (parallel != null) {
|
||||
payloadObject.put("parallel", parallel)
|
||||
}
|
||||
payloadObject.put("task_num", NDataChanger.downloadingTasks.size)
|
||||
payloadObject.put("task_num", NDataChanger.downloadingTaskUrlSet.size)
|
||||
jsonObject.put("payload", payloadObject)
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
@ -352,7 +352,8 @@ object DownloadDataHelper {
|
||||
* 在后台唤醒的情况下 下载状态可能无法修正
|
||||
* see [DownloadManager.initDownloadService]
|
||||
*/
|
||||
if (downloadEntity.status == DownloadStatus.downloading && NDataChanger.downloadingTasks[downloadEntity.url] != null) {
|
||||
if (downloadEntity.status == DownloadStatus.downloading
|
||||
&& NDataChanger.downloadingTaskUrlSet.contains(downloadEntity.url)) {
|
||||
var sheet = mDownloadHeartbeatSheet[downloadEntity.url]
|
||||
if (sheet == null) {
|
||||
sheet = JSONObject()
|
||||
|
||||
@ -61,7 +61,6 @@ import com.lightgame.download.DownloadDao;
|
||||
import com.lightgame.download.DownloadEntity;
|
||||
import com.lightgame.download.DownloadStatus;
|
||||
import com.lightgame.download.DownloadStatusListener;
|
||||
import com.lightgame.download.DownloadTask;
|
||||
import com.lightgame.download.FileUtils;
|
||||
import com.lightgame.download.HttpDnsManager;
|
||||
import com.lightgame.utils.Utils;
|
||||
@ -284,6 +283,7 @@ public class DownloadManager implements DownloadStatusListener {
|
||||
|
||||
String path;
|
||||
String downloadId = PackageInstaller.createDownloadId(gameEntity.getName());
|
||||
String gameCategory = gameEntity.getCategory();
|
||||
if (SimulatorGameManager.isSimulatorGame(gameEntity)) {
|
||||
path = SimulatorGameManager.getPathByType(gameEntity.getSimulatorType()) + "/" + gameEntity.getName() + "." + apkEntity.getFormat();
|
||||
|
||||
@ -316,6 +316,7 @@ public class DownloadManager implements DownloadStatusListener {
|
||||
downloadEntity.setGameId(gameEntity.getId());
|
||||
downloadEntity.setEntrance(entrance);
|
||||
downloadEntity.setLocation(location);
|
||||
downloadEntity.setFormat(apkEntity.getFormat());
|
||||
downloadEntity.setVersionName(apkEntity.getVersion());
|
||||
ExtensionsKt.addMetaExtra(downloadEntity, Constants.APK_MD5, apkEntity.getMd5());
|
||||
ExtensionsKt.addMetaExtra(downloadEntity, Constants.DOWNLOAD_ID, downloadId);
|
||||
@ -323,9 +324,11 @@ public class DownloadManager implements DownloadStatusListener {
|
||||
ExtensionsKt.addMetaExtra(downloadEntity, Constants.GAME_ICON_SUBSCRIPT, gameEntity.getIconSubscript());
|
||||
ExtensionsKt.addMetaExtra(downloadEntity, Constants.IS_PLATFORM_RECOMMEND, apkEntity.getRecommend() != null ? "true" : "false");
|
||||
ExtensionsKt.addMetaExtra(downloadEntity, Constants.GAME_NAME, gameEntity.getName());
|
||||
ExtensionsKt.addMetaExtra(downloadEntity, Constants.GAME_TYPE, gameEntity.getCategoryChinese());
|
||||
ExtensionsKt.addMetaExtra(downloadEntity, Constants.GAME_CATEGORY_IN_CHINESE, gameEntity.getCategoryChinese());
|
||||
ExtensionsKt.addMetaExtra(downloadEntity, Constants.AD_ICON_ACTIVE, String.valueOf(gameEntity.getAdIconActive()));
|
||||
ExtensionsKt.addMetaExtra(downloadEntity, Constants.IS_AD_DATA, String.valueOf(gameEntity.isAdData()));
|
||||
ExtensionsKt.putGameCategory(downloadEntity, gameCategory != null ? gameCategory : "");
|
||||
ExtensionsKt.addMetaExtra(downloadEntity, Constants.APK_SIZE, apkEntity.getSize());
|
||||
if (gameEntity.getIconFloat() != null) {
|
||||
ExtensionsKt.addMetaExtra(downloadEntity, Constants.GAME_ICON_FLOAT_TOP_TEXT, gameEntity.getIconFloat().getUpperLeftText());
|
||||
ExtensionsKt.addMetaExtra(downloadEntity, Constants.GAME_ICON_FLOAT_TOP_COLOR, gameEntity.getIconFloat().getUpperLeftColor());
|
||||
@ -545,7 +548,7 @@ public class DownloadManager implements DownloadStatusListener {
|
||||
* 任务是否已经下载中
|
||||
*/
|
||||
public boolean isTaskDownloading(String url) {
|
||||
if (NDataChanger.INSTANCE.getDownloadingTasks().get(url) != null) {
|
||||
if (NDataChanger.INSTANCE.getDownloadingTaskUrlSet().contains(url)) {
|
||||
Utils.log(DownloadManager.class.getSimpleName(), url + "正在下载!");
|
||||
return true;
|
||||
}
|
||||
@ -867,12 +870,8 @@ public class DownloadManager implements DownloadStatusListener {
|
||||
private void cancelAndNotify(DownloadEntity entry, boolean cancelSilently) {
|
||||
mDownloadDao.removeErrorMessage(entry.getUrl());
|
||||
|
||||
DownloadTask task = NDataChanger.INSTANCE.getDownloadingTasks().get(entry.getUrl());
|
||||
if (task != null) {
|
||||
task.cancel();
|
||||
// 改任务队列的状态
|
||||
NDataChanger.INSTANCE.getDownloadingTasks().remove(entry.getUrl());
|
||||
}
|
||||
// 改任务队列的状态
|
||||
NDataChanger.INSTANCE.getDownloadingTaskUrlSet().remove(entry.getUrl());
|
||||
NDataChanger.INSTANCE.getDownloadEntries().remove(entry.getUrl());
|
||||
if (!cancelSilently) {
|
||||
NDataChanger.INSTANCE.notifyDataChanged(entry);
|
||||
@ -886,8 +885,10 @@ public class DownloadManager implements DownloadStatusListener {
|
||||
* 暂停所有正在下载的任务
|
||||
*/
|
||||
public void pauseAll() {
|
||||
for (DownloadEntity entity : NDataChanger.INSTANCE.getDownloadEntries().values()) {
|
||||
pause(entity.getUrl());
|
||||
synchronized (NDataChanger.INSTANCE.getDownloadEntries()) {
|
||||
for (DownloadEntity entity : NDataChanger.INSTANCE.getDownloadEntries().values()) {
|
||||
pause(entity.getUrl());
|
||||
}
|
||||
}
|
||||
Utils.log(DownloadManager.class.getSimpleName(), "pause all");
|
||||
}
|
||||
@ -913,10 +914,10 @@ public class DownloadManager implements DownloadStatusListener {
|
||||
* 3.检查是否显示下载通知栏
|
||||
*/
|
||||
public void initDownloadService() {
|
||||
final List<String> urlList = new ArrayList<>(NDataChanger.INSTANCE.getDownloadingTasks().keySet());
|
||||
final Set<String> urlSet = NDataChanger.INSTANCE.getDownloadingTaskUrlSet();
|
||||
for (DownloadEntity downloadEntity : getAllDownloadEntity()) {
|
||||
if (!urlList.contains(downloadEntity.getUrl()) &&
|
||||
(downloadEntity.getStatus().equals(DownloadStatus.downloading)
|
||||
if (!urlSet.contains(downloadEntity.getUrl())
|
||||
&& (downloadEntity.getStatus().equals(DownloadStatus.downloading)
|
||||
|| downloadEntity.getStatus().equals(DownloadStatus.waiting))) {
|
||||
downloadEntity.setStatus(DownloadStatus.subscribe);
|
||||
mDownloadDao.newOrUpdate(downloadEntity);
|
||||
|
||||
@ -6,6 +6,7 @@ import com.gh.common.util.ConcernUtils
|
||||
import com.gh.common.util.DataCollectionUtils
|
||||
import com.gh.common.util.PackageInstaller
|
||||
import com.gh.common.util.PackageUtils
|
||||
import com.gh.common.xapk.XapkInstaller
|
||||
import com.gh.download.server.BrowserInstallHelper
|
||||
import com.gh.gamecenter.common.constant.Constants
|
||||
import com.gh.gamecenter.common.loghub.LoghubUtils
|
||||
@ -110,6 +111,10 @@ object PackageObserver {
|
||||
runOnIoThread { FileUtils.deleteFile(mDownloadEntity.path) }
|
||||
}
|
||||
|
||||
if (mDownloadEntity.format == Constants.XAPK_FORMAT) {
|
||||
XapkInstaller.onInstalled(mDownloadEntity.path)
|
||||
}
|
||||
|
||||
DownloadManager.getInstance().cancel(mDownloadEntity.url, false, true, false)
|
||||
|
||||
if (SPUtils.getBoolean(Constants.SP_CONCERN_GAME, true)) { //设置页面控制是否安装后自动关注
|
||||
|
||||
@ -178,9 +178,18 @@ class DownloadDialog : BaseDraggableDialogFragment() {
|
||||
for (i in 0 until it.itemCount) {
|
||||
val apkEntity = itemList[i].normal ?: continue
|
||||
val apkCollection = apkEntity.apkCollection
|
||||
if (apkCollection != null && apkCollection.name == mPlatformName) {
|
||||
scrollAndDownload(recyclerView, false, i)
|
||||
break
|
||||
if (apkCollection != null) {
|
||||
if (apkCollection.name == mPlatformName) {
|
||||
scrollAndDownload(recyclerView, false, i)
|
||||
break
|
||||
} else {
|
||||
apkCollection.saveApkEntity?.forEach { entity ->
|
||||
if (entity.getPlatformName() == mPlatformName || entity.packageName == mPackageName) {
|
||||
scrollAndDownload(recyclerView, false, i)
|
||||
}
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
if (apkEntity.getPlatformName() == mPlatformName || apkEntity.packageName == mPackageName) {
|
||||
scrollAndDownload(recyclerView, true, i)
|
||||
|
||||
@ -10,12 +10,9 @@ import com.gh.common.constant.Config
|
||||
import com.gh.common.dialog.CertificationDialog
|
||||
import com.gh.common.dialog.DeviceRemindDialog
|
||||
import com.gh.common.dialog.PackageCheckDialogFragment
|
||||
import com.gh.common.util.*
|
||||
import com.gh.gamecenter.feature.exposure.ExposureEvent
|
||||
import com.gh.common.util.DialogUtils
|
||||
import com.gh.common.util.DirectUtils.directToLinkPage
|
||||
import com.gh.common.util.DownloadDialogHelper
|
||||
import com.gh.common.util.PackageInstaller
|
||||
import com.gh.common.util.PackageUtils
|
||||
import com.gh.download.DownloadManager
|
||||
import com.gh.download.server.BrowserInstallHelper
|
||||
import com.gh.gamecenter.DownloadManagerActivity
|
||||
@ -244,7 +241,7 @@ class DownloadDialogItemViewHolder(val binding: DownloadDialogItemBinding) : Bas
|
||||
mtaValue = gameEntity.name + "_" + apkEntity.getPlatformName() + "_下载"
|
||||
}
|
||||
DownloadDialogItemStatus.LAUNCH -> {
|
||||
PackageUtils.launchApplicationByPackageName(it.context, apkEntity.packageName)
|
||||
PackageLauncher.launchApp(it.context, gameEntity, apkEntity.packageName)
|
||||
|
||||
mtaValue = gameEntity.name + "_" + apkEntity.getPlatformName() + "_启动"
|
||||
}
|
||||
@ -352,54 +349,46 @@ class DownloadDialogItemViewHolder(val binding: DownloadDialogItemBinding) : Bas
|
||||
if (msg.isNullOrEmpty()) {
|
||||
BrowserInstallHelper.showBrowserInstallHintDialog(
|
||||
context,
|
||||
gameEntity.isVGame(),
|
||||
object : EmptyCallback {
|
||||
override fun onCallback() {
|
||||
DownloadDialogHelper.findAvailableDialogAndShow(
|
||||
gameEntity.isVGame() || gameEntity.isSplitXApk()
|
||||
) {
|
||||
DownloadDialogHelper.findAvailableDialogAndShow(
|
||||
context,
|
||||
gameEntity,
|
||||
apkEntity
|
||||
) {
|
||||
PackageCheckDialogFragment.show(
|
||||
context as AppCompatActivity,
|
||||
gameEntity
|
||||
) {
|
||||
CertificationDialog.showCertificationDialog(
|
||||
context,
|
||||
gameEntity,
|
||||
apkEntity,
|
||||
object : EmptyCallback {
|
||||
override fun onCallback() {
|
||||
PackageCheckDialogFragment.show(
|
||||
context as AppCompatActivity,
|
||||
gameEntity,
|
||||
object : ConfirmListener {
|
||||
override fun onConfirm() {
|
||||
CertificationDialog.showCertificationDialog(
|
||||
context,
|
||||
gameEntity,
|
||||
object : ConfirmListener {
|
||||
override fun onConfirm() {
|
||||
DialogUtils.checkDownload(
|
||||
context,
|
||||
apkEntity.size,
|
||||
gameEntity.id,
|
||||
gameEntity.name
|
||||
) { isSubscribe ->
|
||||
DownloadManager.createDownload(
|
||||
context,
|
||||
apkEntity,
|
||||
gameEntity,
|
||||
downloadMethod,
|
||||
entrance,
|
||||
location,
|
||||
isSubscribe, traceEvent
|
||||
)
|
||||
gameEntity
|
||||
) {
|
||||
DialogUtils.checkDownload(
|
||||
context,
|
||||
apkEntity.size,
|
||||
gameEntity.id,
|
||||
gameEntity.name
|
||||
) { isSubscribe ->
|
||||
DownloadManager.createDownload(
|
||||
context,
|
||||
apkEntity,
|
||||
gameEntity,
|
||||
downloadMethod,
|
||||
entrance,
|
||||
location,
|
||||
isSubscribe, traceEvent
|
||||
)
|
||||
|
||||
DeviceRemindDialog.showDeviceRemindDialog(
|
||||
context,
|
||||
gameEntity
|
||||
)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
DeviceRemindDialog.showDeviceRemindDialog(
|
||||
context,
|
||||
gameEntity
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Utils.toast(context, msg)
|
||||
}
|
||||
|
||||
@ -17,6 +17,7 @@ import com.gh.gamecenter.common.utils.tryCatchInRelease
|
||||
import com.gh.gamecenter.core.utils.EmptyCallback
|
||||
import com.gh.gamecenter.core.utils.GsonUtils
|
||||
import com.gh.gamecenter.core.utils.SPUtils
|
||||
import com.gh.gamecenter.feature.entity.GameEntity
|
||||
import com.google.gson.JsonObject
|
||||
import com.halo.assistant.HaloApp
|
||||
import com.lightgame.utils.Utils
|
||||
@ -93,6 +94,10 @@ object BrowserInstallHelper {
|
||||
return false
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun shouldAutoSwitchAssistantInstall(gameEntity: GameEntity): Boolean =
|
||||
isUseBrowserToInstallEnabled() && shouldUseBrowserToInstall() && gameEntity.isSplitXApk()
|
||||
|
||||
/**
|
||||
* 是否显示使用浏览器来安装弹窗
|
||||
*/
|
||||
@ -144,7 +149,8 @@ object BrowserInstallHelper {
|
||||
val manufacturer = Build.MANUFACTURER.toUpperCase(Locale.CHINA)
|
||||
var contentText = "当前安装方式为助手安装,如果出现游戏无法安装的问题,可选择切换安装方式为“浏览器安装”"
|
||||
if (manufacturer == "OPPO" || manufacturer == "VIVO") {
|
||||
contentText = "当前安装方式为助手安装,下载安装游戏需要验证账户密码或指纹。如需免密码安装,可选择切换安装方式为“浏览器安装”"
|
||||
contentText =
|
||||
"当前安装方式为助手安装,下载安装游戏需要验证账户密码或指纹。如需免密码安装,可选择切换安装方式为“浏览器安装”"
|
||||
}
|
||||
|
||||
DialogHelper.showDialog(
|
||||
|
||||
@ -198,7 +198,6 @@ public class MainActivity extends BaseActivity {
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
showAd = getIntent().getBooleanExtra(SHOW_AD, false) && savedInstanceState == null;
|
||||
|
||||
HaloApp.getInstance().initFresco();
|
||||
HaloApp.getInstance().isAlreadyUpAndRunning = true;
|
||||
|
||||
super.onCreate(savedInstanceState);
|
||||
@ -319,6 +318,8 @@ public class MainActivity extends BaseActivity {
|
||||
// 默认配置为空时重试
|
||||
if (Config.getSettings() == null) {
|
||||
Config.getGhzsSettings();
|
||||
} else if (Config.getVSettingEntity() == null) {
|
||||
Config.refreshVSettingEntity();
|
||||
}
|
||||
|
||||
// 耗时操作
|
||||
@ -803,6 +804,15 @@ public class MainActivity extends BaseActivity {
|
||||
ToastUtils.showToast("游戏启动失败,请联系客服反馈相关信息");
|
||||
return;
|
||||
}
|
||||
|
||||
VHelper.INSTANCE.logLaunchButtonClicked(
|
||||
gamePackageName,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
"桌面快捷图标"
|
||||
);
|
||||
|
||||
ToastUtils.showToast("游戏启动中,请稍后~");
|
||||
handler.postDelayed(() -> {
|
||||
VHelper.postOnInitialized(() -> {
|
||||
@ -1064,6 +1074,8 @@ public class MainActivity extends BaseActivity {
|
||||
if (busNetworkState.isNetworkConnected()) {
|
||||
if (Config.getSettings() == null) {
|
||||
Config.getGhzsSettings();
|
||||
} else if (Config.getVSettingEntity() == null) {
|
||||
Config.refreshVSettingEntity();
|
||||
}
|
||||
|
||||
mPackageViewModel.checkData();
|
||||
|
||||
@ -403,7 +403,7 @@ public class SkipActivity extends BaseActivity {
|
||||
DirectUtils.directToGameCollectionDetail(this, path, ENTRANCE_BROWSER, "", null);
|
||||
break;
|
||||
case HOST_GAME_COLLECTION_SQUARE:
|
||||
DirectUtils.directToGameCollectionSquare(this, ENTRANCE_BROWSER, "", "", "");
|
||||
DirectUtils.directToGameCollectionSquare(this, ENTRANCE_BROWSER, "", "", "", "", "");
|
||||
break;
|
||||
default:
|
||||
EntranceUtils.jumpActivity(this, new Bundle()); // 跳转至首页
|
||||
|
||||
@ -51,6 +51,7 @@ import java.io.IOException
|
||||
import java.io.InputStreamReader
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
import kotlin.collections.ArrayList
|
||||
|
||||
/**
|
||||
* 引导页面
|
||||
@ -79,6 +80,7 @@ class SplashScreenActivity : BaseActivity() {
|
||||
mIsNewForThisVersion =
|
||||
mSharedPreferences!!.getBoolean("isNewFirstLaunchV" + PackageUtils.getGhVersionName(), true)
|
||||
HaloApp.getInstance().isNewForThisVersion = mIsNewForThisVersion
|
||||
HaloApp.getInstance().isBrandNewInstall = SPUtils.getBoolean(Constants.SP_BRAND_NEW_USER, true)
|
||||
|
||||
// 用户不是新版本,但应用最后更新时间不是上次的时间代表用户重新安装了当前版本
|
||||
if (!mIsNewForThisVersion) {
|
||||
@ -104,12 +106,11 @@ class SplashScreenActivity : BaseActivity() {
|
||||
guideLayout.adapter = GuidePagerAdapter()
|
||||
|
||||
// 判断是不是光环的新用户
|
||||
if (SPUtils.getBoolean(Constants.SP_BRAND_NEW_USER, true)) {
|
||||
if (HaloApp.getInstance().isBrandNewInstall) {
|
||||
// 引导页需用户点击 “立即体验” 按钮才进入首页,所以这里不能置为true
|
||||
// https://git.ghzs.com/pm/halo-app-issues/-/issues/1422(第3点)
|
||||
// mStartMainActivityDirectly = true;
|
||||
SPUtils.setLong(Constants.SP_INITIAL_USAGE_TIME, System.currentTimeMillis())
|
||||
HaloApp.getInstance().isBrandNewInstall = true
|
||||
if (!PackageFlavorHelper.IS_TEST_FLAVOR) {
|
||||
showPrivacyDialog(guideLayout)
|
||||
} else {
|
||||
@ -188,20 +189,6 @@ class SplashScreenActivity : BaseActivity() {
|
||||
private fun showPrivacyDialog(guideLayout: ViewPager) {
|
||||
NewPrivacyPolicyDialogFragment.show(this, null) { isSuccess: Boolean ->
|
||||
if (isSuccess) {
|
||||
// guideLayout.visibility = View.VISIBLE
|
||||
// SPUtils.setBoolean(Constants.SP_BRAND_NEW_USER, false)
|
||||
//
|
||||
// // 恢复畅玩数据
|
||||
// VHelper.recoverVDataIfPossible()
|
||||
//
|
||||
// requestPermission()
|
||||
//
|
||||
// // 检查是否有旧版本光环,有就删掉
|
||||
// AppExecutor.ioExecutor.execute { deleteOutdatedUpdatePackage() }
|
||||
// if (mStartMainActivityDirectly) {
|
||||
// launchMainActivity()
|
||||
// }
|
||||
|
||||
mShouldPrefetchData = false
|
||||
prefetchData()
|
||||
|
||||
@ -226,12 +213,10 @@ class SplashScreenActivity : BaseActivity() {
|
||||
} else {
|
||||
DialogUtils.showPrivacyPolicyDisallowDialog(
|
||||
this,
|
||||
PrivacyPolicyEntity.createDefaultData(),
|
||||
object : EmptyCallback {
|
||||
override fun onCallback() {
|
||||
showPrivacyDialog(guideLayout)
|
||||
}
|
||||
})
|
||||
PrivacyPolicyEntity.createDefaultData()
|
||||
) {
|
||||
showPrivacyDialog(guideLayout)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -312,19 +297,7 @@ class SplashScreenActivity : BaseActivity() {
|
||||
private fun doFlavorInit() {
|
||||
HaloApp.getInstance().flavorProvider.init(HaloApp.getInstance(), this, PkgHelper.getActivateRatio())
|
||||
|
||||
val whiteListChannel = arrayListOf(
|
||||
"GH_206",
|
||||
"KS-GHZS-KY1",
|
||||
"KS-GHZS-MC1",
|
||||
"GDT_GHZS_MC1",
|
||||
"T11-GH-APPDY-ZC01",
|
||||
"T7-GH-APPDY-KY03",
|
||||
"T8-GH-APPUX-KY04",
|
||||
"T1-GHZS-MC01",
|
||||
"T4-GHZS-MC03"
|
||||
)
|
||||
|
||||
if (whiteListChannel.contains(HaloApp.getInstance().channel) || PackageFlavorHelper.IS_TEST_FLAVOR) {
|
||||
if (HaloApp.getInstance().channel == "GH_206" || PackageFlavorHelper.IS_TEST_FLAVOR) {
|
||||
SensorsBridge.init(HaloApp.getInstance(), HaloApp.getInstance().channel)
|
||||
}
|
||||
}
|
||||
@ -440,11 +413,8 @@ class SplashScreenActivity : BaseActivity() {
|
||||
@AfterPermissionGranted(REQUEST_PERMISSION_TAG)
|
||||
private fun checkAndRequestPermission() {
|
||||
if (EasyPermissions.hasPermissions(this, *mPermissions)) {
|
||||
// 恢复畅玩数据
|
||||
VHelper.recoverVDataIfPossible()
|
||||
onPermissionsGranted(REQUEST_PERMISSION_TAG, ArrayList(mPermissions.toList()))
|
||||
|
||||
// 检查是否有旧版本光环,有就删掉
|
||||
runOnIoThread { deleteOutdatedUpdatePackage() }
|
||||
if (mStartMainActivityDirectly) {
|
||||
if (com.gh.gamecenter.common.BuildConfig.BUILD_TIME != 0L) {
|
||||
showGitLogDialogIfNeeded()
|
||||
@ -467,6 +437,17 @@ class SplashScreenActivity : BaseActivity() {
|
||||
}
|
||||
}
|
||||
|
||||
override fun onPermissionsGranted(requestCode: Int, perms: MutableList<String>?) {
|
||||
super.onPermissionsGranted(requestCode, perms)
|
||||
|
||||
if (perms?.contains(Manifest.permission.READ_EXTERNAL_STORAGE) == true) {
|
||||
// 恢复畅玩数据
|
||||
VHelper.recoverVDataIfPossible()
|
||||
// 检查是否有旧版本光环,有就删掉
|
||||
runOnIoThread { deleteOutdatedUpdatePackage() }
|
||||
}
|
||||
}
|
||||
|
||||
// 检查下载文件夹下是否有旧版本的光环助手的包,有则删除
|
||||
private fun deleteOutdatedUpdatePackage() {
|
||||
try {
|
||||
|
||||
@ -208,9 +208,9 @@ public class LibaoDetailAdapter extends BaseRecyclerAdapter<ViewHolder> {
|
||||
}
|
||||
holder.binding.libaodetailName.setText(mLibaoEntity.getName());
|
||||
if (TextUtils.isEmpty(mLibaoEntity.getPlatform())) {
|
||||
holder.binding.libaodetailName.setText(mLibaoEntity.getGame().getName());
|
||||
holder.binding.libaodetailGameName.setText(mLibaoEntity.getGame().getName());
|
||||
} else {
|
||||
holder.binding.libaodetailName.setText((mLibaoEntity.getGame().getName() + " - " +
|
||||
holder.binding.libaodetailGameName.setText((mLibaoEntity.getGame().getName() + " - " +
|
||||
PlatformUtils.getInstance(mContext).getPlatformName(mLibaoEntity.getPlatform())));
|
||||
}
|
||||
|
||||
|
||||
@ -12,7 +12,6 @@ import androidx.fragment.app.DialogFragment;
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
|
||||
import com.airbnb.lottie.LottieAnimationView;
|
||||
import com.gh.gamecenter.common.base.GlobalActivityManager;
|
||||
import com.gh.common.chain.BrowserInstallHandler;
|
||||
import com.gh.common.chain.CertificationHandler;
|
||||
import com.gh.common.chain.ChainBuilder;
|
||||
@ -23,14 +22,13 @@ import com.gh.common.chain.DownloadDialogHelperHandler;
|
||||
import com.gh.common.chain.GamePermissionHandler;
|
||||
import com.gh.common.chain.OverseaDownloadHandler;
|
||||
import com.gh.common.chain.PackageCheckHandler;
|
||||
import com.gh.common.chain.UnsupportedFeatureHandler;
|
||||
import com.gh.common.chain.UpdateNewSimulatorHandler;
|
||||
import com.gh.common.chain.ValidateVSpaceHandler;
|
||||
import com.gh.common.chain.VersionNumberHandler;
|
||||
import com.gh.common.constant.Config;
|
||||
import com.gh.common.dialog.DeviceRemindDialog;
|
||||
import com.gh.common.dialog.GameOffServiceDialogFragment;
|
||||
import com.gh.gamecenter.common.utils.SensorsBridge;
|
||||
import com.gh.gamecenter.feature.exposure.ExposureEvent;
|
||||
import com.gh.common.filter.RegionSetting;
|
||||
import com.gh.common.filter.RegionSettingHelper;
|
||||
import com.gh.common.history.HistoryHelper;
|
||||
@ -38,41 +36,43 @@ import com.gh.common.simulator.NewSimulatorGameManager;
|
||||
import com.gh.common.simulator.SimulatorDownloadManager;
|
||||
import com.gh.common.simulator.SimulatorGameManager;
|
||||
import com.gh.common.util.CheckLoginUtils;
|
||||
import com.gh.common.util.DetailDownloadUtils;
|
||||
import com.gh.common.util.DialogUtils;
|
||||
import com.gh.common.util.DirectUtils;
|
||||
import com.gh.common.util.LogUtils;
|
||||
import com.gh.common.util.PackageInstaller;
|
||||
import com.gh.common.util.PackageLauncher;
|
||||
import com.gh.common.util.PackageUtils;
|
||||
import com.gh.common.util.ReservationHelper;
|
||||
import com.gh.common.xapk.XapkInstaller;
|
||||
import com.gh.common.xapk.XapkUnzipStatus;
|
||||
import com.gh.gamecenter.common.constant.EntranceConsts;
|
||||
import com.gh.gamecenter.common.utils.DataLogUtils;
|
||||
import com.gh.common.util.DetailDownloadUtils;
|
||||
import com.gh.gamecenter.common.utils.DialogHelper;
|
||||
import com.gh.common.util.DialogUtils;
|
||||
import com.gh.gamecenter.core.utils.PageSwitchDataHelper;
|
||||
import com.gh.common.util.LogUtils;
|
||||
import com.gh.gamecenter.core.utils.MtaHelper;
|
||||
import com.gh.common.util.PackageInstaller;
|
||||
import com.gh.common.util.PackageUtils;
|
||||
import com.gh.gamecenter.common.utils.PermissionHelper;
|
||||
import com.gh.common.util.ReservationHelper;
|
||||
import com.gh.gamecenter.feature.view.DownloadButton;
|
||||
import com.gh.download.DownloadManager;
|
||||
import com.gh.download.dialog.DownloadDialog;
|
||||
import com.gh.gamecenter.DownloadManagerActivity;
|
||||
import com.gh.gamecenter.R;
|
||||
import com.gh.gamecenter.WebActivity;
|
||||
import com.gh.gamecenter.common.constant.Constants;
|
||||
import com.gh.gamecenter.core.utils.StringUtils;
|
||||
import com.gh.gamecenter.feature.entity.ApkEntity;
|
||||
import com.gh.gamecenter.feature.entity.GameEntity;
|
||||
import com.gh.gamecenter.common.constant.EntranceConsts;
|
||||
import com.gh.gamecenter.common.entity.LinkEntity;
|
||||
import com.gh.gamecenter.common.eventbus.EBReuse;
|
||||
import com.gh.gamecenter.feature.entity.SimulatorEntity;
|
||||
import com.gh.gamecenter.common.utils.DataLogUtils;
|
||||
import com.gh.gamecenter.common.utils.DialogHelper;
|
||||
import com.gh.gamecenter.common.utils.ExtensionsKt;
|
||||
import com.gh.gamecenter.common.utils.PermissionHelper;
|
||||
import com.gh.gamecenter.common.utils.SensorsBridge;
|
||||
import com.gh.gamecenter.core.utils.PageSwitchDataHelper;
|
||||
import com.gh.gamecenter.core.utils.StringUtils;
|
||||
import com.gh.gamecenter.eventbus.EBScroll;
|
||||
import com.gh.gamecenter.feature.entity.ApkEntity;
|
||||
import com.gh.gamecenter.feature.entity.GameEntity;
|
||||
import com.gh.gamecenter.feature.entity.SimulatorEntity;
|
||||
import com.gh.gamecenter.feature.exposure.ExposureEvent;
|
||||
import com.gh.gamecenter.feature.view.DownloadButton;
|
||||
import com.gh.gamecenter.gamedetail.GameDetailFragment;
|
||||
import com.gh.gamecenter.gamedetail.dialog.GamePermissionDialogFragment;
|
||||
import com.gh.gamecenter.teenagermode.TeenagerModeActivity;
|
||||
import com.gh.vspace.VDownloadManagerActivity;
|
||||
import com.gh.vspace.VHelper;
|
||||
import com.gh.vspace.VSpaceLoadingActivity;
|
||||
import com.lightgame.download.DownloadEntity;
|
||||
import com.lightgame.download.FileUtils;
|
||||
import com.lightgame.utils.Utils;
|
||||
@ -121,6 +121,8 @@ public class DetailViewHolder {
|
||||
|
||||
final OnDetailDownloadClickListener listener = new OnDetailDownloadClickListener(this, entrance, name, title, traceEvent);
|
||||
mDownloadPb.setOnClickListener(listener);
|
||||
ExtensionsKt.putWidgetBusinessName(mDownloadPb, "游戏详情页");
|
||||
ExtensionsKt.putObject(mDownloadPb, gameEntity);
|
||||
|
||||
restoreDialogFragment();
|
||||
}
|
||||
@ -138,13 +140,13 @@ public class DetailViewHolder {
|
||||
}
|
||||
|
||||
static class OnDetailDownloadClickListener implements View.OnClickListener {
|
||||
private DetailViewHolder mViewHolder;
|
||||
private GameEntity mGameEntity;
|
||||
private final DetailViewHolder mViewHolder;
|
||||
private final GameEntity mGameEntity;
|
||||
private DownloadEntity mDownloadEntity;
|
||||
private String mEntrance;
|
||||
private String mName;
|
||||
private String mTitle;
|
||||
private ExposureEvent mTraceEvent;
|
||||
private final String mEntrance;
|
||||
private final String mName;
|
||||
private final String mTitle;
|
||||
private final ExposureEvent mTraceEvent;
|
||||
|
||||
public OnDetailDownloadClickListener(DetailViewHolder viewHolder, String entrance, String name, String title, ExposureEvent traceEvent) {
|
||||
mViewHolder = viewHolder;
|
||||
@ -158,67 +160,7 @@ public class DetailViewHolder {
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (mViewHolder.mDownloadPb.getButtonStyle() != DownloadButton.ButtonStyle.RESERVABLE && mViewHolder.mDownloadPb.getButtonStyle() != DownloadButton.ButtonStyle.RESERVED) {
|
||||
SensorsBridge.trackEvent(
|
||||
"DownLoadbuttonClick",
|
||||
"game_id", mGameEntity.getId(),
|
||||
"game_name", mGameEntity.getName(),
|
||||
"game_type", mGameEntity.getCategoryChinese(),
|
||||
"download_status", mGameEntity.getDownloadStatusChinese(),
|
||||
"button_name", mViewHolder.mDownloadPb.getText(),
|
||||
"game_schema_type", mGameEntity.getGameBitChinese(),
|
||||
"page_name", GlobalActivityManager.getCurrentPageEntity().getPageName(),
|
||||
"page_id", GlobalActivityManager.getCurrentPageEntity().getPageId(),
|
||||
"page_business_id", GlobalActivityManager.getCurrentPageEntity().getPageBusinessId(),
|
||||
"last_page_name", GlobalActivityManager.getLastPageEntity().getPageName(),
|
||||
"last_page_id", GlobalActivityManager.getLastPageEntity().getPageId(),
|
||||
"last_page_business_id", GlobalActivityManager.getLastPageEntity().getPageBusinessId()
|
||||
);
|
||||
}
|
||||
|
||||
// 这个 switch 纯粹是为了 MTA和上报光能任务 统计用的
|
||||
switch (mViewHolder.mDownloadPb.getButtonStyle()) {
|
||||
case DOWNLOADING_PLUGIN:
|
||||
MtaHelper.onEvent("游戏详情_新", "插件化中", mGameEntity.getName());
|
||||
break;
|
||||
case DOWNLOADING_NORMAL:
|
||||
MtaHelper.onEvent("游戏详情_新", "下载中", mGameEntity.getName());
|
||||
break;
|
||||
case NONE:
|
||||
MtaHelper.onEvent("游戏详情_新", "关闭下载", mGameEntity.getName());
|
||||
break;
|
||||
case NORMAL:
|
||||
MtaHelper.onEvent("游戏详情_新", "下载", mGameEntity.getName());
|
||||
break;
|
||||
case PLUGIN:
|
||||
MtaHelper.onEvent("游戏详情_新", "插件化", mGameEntity.getName());
|
||||
break;
|
||||
case INSTALL_PLUGIN:
|
||||
MtaHelper.onEvent("游戏详情_新", "安装插件化", mGameEntity.getName());
|
||||
break;
|
||||
case INSTALL_NORMAL:
|
||||
MtaHelper.onEvent("游戏详情_新", "安装", mGameEntity.getName());
|
||||
break;
|
||||
case RESERVABLE:
|
||||
MtaHelper.onEvent("游戏详情_新", "预约", mGameEntity.getName());
|
||||
break;
|
||||
case LAUNCH_OR_OPEN:
|
||||
if (!mGameEntity.getApk().isEmpty()) {
|
||||
}
|
||||
break;
|
||||
}
|
||||
// 由于部分状态不包含在 downloadType 里,所以还是需要手动获取下载按钮文字判断点击时的状态
|
||||
String downloadText = mViewHolder.mDownloadPb.getText().toString();
|
||||
if (downloadText.contains("打开")) {
|
||||
MtaHelper.onEvent("游戏详情_新", "打开", mGameEntity.getName());
|
||||
} else if (downloadText.contains("启动")) {
|
||||
MtaHelper.onEvent("游戏详情_新", "启动", mGameEntity.getName());
|
||||
} else if (downloadText.contains("更新")) {
|
||||
MtaHelper.onEvent("游戏详情_新", "更新", mGameEntity.getName());
|
||||
}
|
||||
|
||||
v.setTag(null);
|
||||
|
||||
if (mViewHolder.mDownloadPb.getButtonStyle() != DownloadButton.ButtonStyle.INSTALL_NORMAL
|
||||
&& mViewHolder.mDownloadPb.getButtonStyle() != DownloadButton.ButtonStyle.INSTALL_PLUGIN
|
||||
&& mViewHolder.mDownloadPb.getButtonStyle() != DownloadButton.ButtonStyle.LAUNCH_OR_OPEN) {
|
||||
@ -236,6 +178,9 @@ public class DetailViewHolder {
|
||||
|
||||
if (mDownloadEntity != null) {
|
||||
String xapkStatus = mDownloadEntity.getMeta().get(XapkInstaller.XAPK_UNZIP_STATUS);
|
||||
if (XapkUnzipStatus.SUCCESS.name().equals(xapkStatus) && XapkInstaller.INSTANCE.isInstalling(mDownloadEntity.getPath())) {// 安装过程中避免重复点击
|
||||
return;
|
||||
}
|
||||
if (XapkUnzipStatus.UNZIPPING.name().equals(xapkStatus)) {
|
||||
XapkInstaller.cancelUnzipTask(mDownloadEntity);
|
||||
return;
|
||||
@ -261,15 +206,12 @@ public class DetailViewHolder {
|
||||
String offStatus = mGameEntity.getDownloadOffStatus();
|
||||
if (offStatus != null && !"off".equals(offStatus)) {
|
||||
if ("dialog".equals(offStatus)) {
|
||||
// MtaHelper.onEvent("游戏下载状态按钮", "查看详情", mGameEntity.getName());
|
||||
showOffServiceDialog(mGameEntity.getDownloadOffDialog());
|
||||
} else if ("toast".equals(offStatus)) {
|
||||
// MtaHelper.onEvent("游戏下载状态按钮", "关闭且toast", mGameEntity.getName());
|
||||
EventBus.getDefault().post(new EBReuse(GameDetailFragment.SKIP_RATING));
|
||||
Utils.toast(mViewHolder.context, "该游戏因故暂不提供下载,具体详情可在相关评论中查看,敬请谅解~");
|
||||
}
|
||||
} else {
|
||||
// MtaHelper.onEvent("游戏下载状态按钮", "暂无下载", mGameEntity.getName());
|
||||
Utils.toast(mViewHolder.context, "该游戏已关闭下载");
|
||||
}
|
||||
break;
|
||||
@ -282,9 +224,8 @@ public class DetailViewHolder {
|
||||
DataLogUtils.uploadGameLog(mViewHolder.context, mGameEntity.getId(), mGameEntity.getName(), mEntrance);
|
||||
}
|
||||
case PLUGIN:
|
||||
|
||||
|
||||
ChainBuilder builder = new ChainBuilder();
|
||||
builder.addHandler(new UnsupportedFeatureHandler());
|
||||
builder.addHandler(new UpdateNewSimulatorHandler());
|
||||
builder.addHandler(new GamePermissionHandler());
|
||||
builder.addHandler(new CheckStoragePermissionHandler());
|
||||
@ -347,11 +288,11 @@ public class DetailViewHolder {
|
||||
}
|
||||
|
||||
if (mGameEntity.isVGame()) {
|
||||
VHelper.installOrLaunch(mViewHolder.context, mGameEntity);
|
||||
VHelper.installOrLaunch(mViewHolder.context, mGameEntity, null);
|
||||
return;
|
||||
}
|
||||
|
||||
PackageUtils.launchApplicationByPackageName(mViewHolder.context, mGameEntity.getApk().get(0).getPackageName());
|
||||
PackageLauncher.launchApp(mViewHolder.context, mGameEntity, mGameEntity.getApk().get(0).getPackageName());
|
||||
} else {
|
||||
GamePermissionDialogFragment.show((AppCompatActivity) mViewHolder.context, mGameEntity, mGameEntity.getInfo(), () -> {
|
||||
PermissionHelper.checkStoragePermissionBeforeAction(mViewHolder.context, () -> {
|
||||
@ -389,7 +330,7 @@ public class DetailViewHolder {
|
||||
}
|
||||
|
||||
if (mGameEntity.isVGame()) {
|
||||
VHelper.installOrLaunch(v.getContext(), mGameEntity);
|
||||
VHelper.installOrLaunch(v.getContext(), mGameEntity, null);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -436,7 +377,6 @@ public class DetailViewHolder {
|
||||
}
|
||||
break;
|
||||
case H5_GAME:
|
||||
MtaHelper.onEvent("H5页面", "入口", "详情页_" + mGameEntity.getName());
|
||||
LinkEntity linkEntity = mGameEntity.getH5Link();
|
||||
|
||||
boolean isPlay = "play".equals(linkEntity.getType()); // 是否为开始玩
|
||||
@ -482,7 +422,7 @@ public class DetailViewHolder {
|
||||
}
|
||||
|
||||
if (mDownloadEntity != null) {
|
||||
if (downloadText.contains("继续加载")) {
|
||||
if (mViewHolder.mDownloadPb.getText().contains("继续加载")) {
|
||||
DownloadManager.getInstance().resume(mDownloadEntity, true);
|
||||
} else {
|
||||
DownloadManager.getInstance().pause(mDownloadEntity.getUrl());
|
||||
|
||||
@ -43,6 +43,7 @@ class AmwayAdapter(
|
||||
context: Context,
|
||||
private var mViewModel: AmwayViewModel,
|
||||
private var mBasicExposureSource: List<ExposureSource>,
|
||||
private var mUseAlternativeLayout: Boolean,
|
||||
private var mLayoutManager: RecyclerView.LayoutManager
|
||||
) : ListAdapter<AmwayListItemData>(context), IExposable {
|
||||
|
||||
@ -102,6 +103,7 @@ class AmwayAdapter(
|
||||
mViewModel,
|
||||
mEntityList[position],
|
||||
mEntityList[position].blockPosition,
|
||||
mUseAlternativeLayout,
|
||||
mBasicExposureSource
|
||||
)
|
||||
}
|
||||
@ -203,6 +205,7 @@ class AmwayAdapter(
|
||||
viewModel: AmwayViewModel,
|
||||
itemData: AmwayListItemData,
|
||||
blockPosition: Int,
|
||||
useAlternativeLayout: Boolean,
|
||||
basicExposureSource: List<ExposureSource>
|
||||
) {
|
||||
val context = binding.root.context
|
||||
@ -269,9 +272,22 @@ class AmwayAdapter(
|
||||
}
|
||||
|
||||
binding.commentContainer.setOnClickListener {
|
||||
val exposureSource = if (useAlternativeLayout) {
|
||||
arrayListOf(ExposureSource("新首页"), ExposureSource("安利墙"))
|
||||
} else {
|
||||
arrayListOf(ExposureSource("安利墙"))
|
||||
}.toJson()
|
||||
|
||||
val intent = RatingReplyActivity.getIntent(
|
||||
context, amway.game.id, amway.comment, false, viewModel.entrance
|
||||
?: "", EntranceConsts.ENTRANCE_AMWAY
|
||||
context = context,
|
||||
gameId = amway.game.id,
|
||||
gameEntity = null,
|
||||
comment = amway.comment,
|
||||
commentId = amway.comment.id,
|
||||
showKeyboardIfReplyListIsEmpty = false,
|
||||
exposureSource = exposureSource,
|
||||
entrance = viewModel.entrance ?: "",
|
||||
path = EntranceConsts.ENTRANCE_AMWAY
|
||||
)
|
||||
SyncDataBetweenPageHelper.startActivityForResult(
|
||||
binding.root.context,
|
||||
|
||||
@ -145,7 +145,8 @@ class AmwayFragment : LazyListFragment<AmwayListItemData, AmwayViewModel>() {
|
||||
}
|
||||
add(ExposureSource("安利墙", ""))
|
||||
}
|
||||
mAdapter = AmwayAdapter(requireContext(), mViewModel, basicExposureSource, mLayoutManager)
|
||||
mAdapter =
|
||||
AmwayAdapter(requireContext(), mViewModel, basicExposureSource, mUseAlternativeLayout, mLayoutManager)
|
||||
}
|
||||
return mAdapter!!
|
||||
}
|
||||
|
||||
@ -193,6 +193,8 @@ class CategoryV2ListAdapter(
|
||||
true,
|
||||
"star&brief"
|
||||
)
|
||||
|
||||
holder.binding.downloadBtn.putWidgetBusinessName("分类列表")
|
||||
} else if (holder is FooterViewHolder) {
|
||||
holder.run {
|
||||
initItemPadding()
|
||||
|
||||
@ -4,6 +4,7 @@ import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.graphics.drawable.ColorDrawable
|
||||
import android.util.SparseArray
|
||||
import android.view.Gravity
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
@ -13,6 +14,7 @@ import android.widget.PopupWindow
|
||||
import android.widget.TextView
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.gh.common.exposure.IExposable
|
||||
import com.gh.gamecenter.common.constant.ItemViewType
|
||||
import com.gh.gamecenter.common.syncpage.ISyncAdapterHandler
|
||||
import com.gh.common.util.*
|
||||
@ -30,6 +32,10 @@ import com.gh.gamecenter.databinding.ItemGameCollectionFlexTagBinding
|
||||
import com.gh.gamecenter.databinding.PopupHistoryOptionBinding
|
||||
import com.gh.gamecenter.entity.GamesCollectionEntity
|
||||
import com.gh.gamecenter.entity.TagInfoEntity
|
||||
import com.gh.gamecenter.feature.entity.GameEntity
|
||||
import com.gh.gamecenter.feature.exposure.ExposureEvent
|
||||
import com.gh.gamecenter.feature.exposure.ExposureSource
|
||||
import com.gh.gamecenter.feature.exposure.ExposureType
|
||||
import com.gh.gamecenter.gamecollection.detail.GameCollectionDetailActivity
|
||||
import com.gh.gamecenter.gamecollection.publish.GameCollectionEditActivity
|
||||
import com.gh.gamecenter.history.ManageOption
|
||||
@ -39,12 +45,19 @@ import com.google.android.flexbox.FlexboxLayout
|
||||
class GamesCollectionAdapter(
|
||||
context: Context,
|
||||
private val mViewModel: GamesCollectionViewModel,
|
||||
) : ListAdapter<GamesCollectionEntity>(context), ISyncAdapterHandler {
|
||||
) : ListAdapter<GamesCollectionEntity>(context), ISyncAdapterHandler, IExposable {
|
||||
|
||||
private var mCurrentOption = ManageOption.OPTION_MANAGER
|
||||
private var mPopWindow: PopupWindow? = null
|
||||
private var mPopupBinding: PopupHistoryOptionBinding? = null
|
||||
var selectItems = arrayListOf<String>()
|
||||
private var mExposureEventArray: SparseArray<ExposureEvent>? = null
|
||||
|
||||
|
||||
override fun setListData(updateData: MutableList<GamesCollectionEntity>?) {
|
||||
mExposureEventArray = SparseArray(updateData?.size ?: 0)
|
||||
super.setListData(updateData)
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int {
|
||||
return if (mEntityList == null || mEntityList.isEmpty()) return 0 else mEntityList.size + 1
|
||||
@ -102,6 +115,19 @@ class GamesCollectionAdapter(
|
||||
when (holder) {
|
||||
is GameCollectionItemViewHolder -> {
|
||||
val itemEntity = mEntityList[position]
|
||||
val exposureEvent = ExposureEvent.createEvent(
|
||||
GameEntity().apply {
|
||||
sequence = position
|
||||
},
|
||||
listOf(
|
||||
ExposureSource("个人主页", ""),
|
||||
ExposureSource("游戏单", "${itemEntity.title}+${itemEntity.id}")
|
||||
),
|
||||
null,
|
||||
ExposureType.EXPOSURE
|
||||
)
|
||||
mExposureEventArray?.put(position, exposureEvent)
|
||||
|
||||
holder.binding.run {
|
||||
ImageUtils.display(poster, itemEntity.cover)
|
||||
nameTv.text = itemEntity.title
|
||||
@ -117,7 +143,7 @@ class GamesCollectionAdapter(
|
||||
gameThree.goneIf(it < 3)
|
||||
}
|
||||
|
||||
moreNumTv.goneIf((itemEntity.count?.game ?: 0) < 4)
|
||||
moreNumTv.goneIf((itemEntity.count?.game ?: 0) < 4 || itemEntity.games?.size == 0)
|
||||
moreNumTv.text = "+ " + ((itemEntity.count?.game ?: 0) - 3)
|
||||
tagContainer.goneIf(itemEntity.count?.game != 0)
|
||||
timeTv.text = TimeUtils.getFormatTime(itemEntity.time?.update ?: 0, "MM - dd")
|
||||
@ -235,7 +261,8 @@ class GamesCollectionAdapter(
|
||||
GameCollectionDetailActivity.getIntent(
|
||||
mContext,
|
||||
itemEntity.id,
|
||||
isScrollToCommentArea = true
|
||||
isScrollToCommentArea = true,
|
||||
exposureSourceList = ArrayList(exposureEvent.source)
|
||||
)
|
||||
)
|
||||
}
|
||||
@ -294,7 +321,13 @@ class GamesCollectionAdapter(
|
||||
} else {
|
||||
if (mCurrentOption == ManageOption.OPTION_MANAGER) {
|
||||
NewLogUtils.logEnterGameCollectionDetail(itemEntity.title, itemEntity.id)
|
||||
mContext.startActivity(GameCollectionDetailActivity.getIntent(mContext, itemEntity.id))
|
||||
mContext.startActivity(
|
||||
GameCollectionDetailActivity.getIntent(
|
||||
mContext,
|
||||
itemEntity.id,
|
||||
exposureSourceList = ArrayList(exposureEvent.source)
|
||||
)
|
||||
)
|
||||
} else {
|
||||
if (selectItems.contains(itemEntity.id)) {
|
||||
selectItems.remove(itemEntity.id)
|
||||
@ -459,4 +492,8 @@ class GamesCollectionAdapter(
|
||||
checkAllCb.isChecked = selectItems.size == mEntityList.size
|
||||
}
|
||||
}
|
||||
|
||||
override fun getEventByPosition(pos: Int): ExposureEvent? = mExposureEventArray!!.get(pos)
|
||||
|
||||
override fun getEventListByPosition(pos: Int): List<ExposureEvent>? = null
|
||||
}
|
||||
@ -3,6 +3,7 @@ package com.gh.gamecenter.collection
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import androidx.core.content.ContextCompat
|
||||
import com.gh.common.exposure.ExposureListener
|
||||
import com.gh.gamecenter.common.constant.EntranceConsts.*
|
||||
import com.gh.gamecenter.common.view.SpacingItemDecoration
|
||||
import com.gh.gamecenter.R
|
||||
@ -76,6 +77,8 @@ class GamesCollectionFragment : ListFragment<GamesCollectionEntity, GamesCollect
|
||||
mListViewModel.publishLiveData.observe(viewLifecycleOwner) {
|
||||
mListViewModel.load(LoadType.REFRESH)
|
||||
}
|
||||
|
||||
mListRv.addOnScrollListener(ExposureListener(this, provideListAdapter()))
|
||||
}
|
||||
|
||||
override fun onLoadEmpty() {
|
||||
|
||||
@ -137,8 +137,7 @@ public class GameDownloadFragment extends BaseFragment implements View.OnClickLi
|
||||
}
|
||||
}
|
||||
|
||||
adapter.getUrlMap().put(PackageUtils.getPackageNameByPath(HaloApp.getInstance().getApplication(),
|
||||
downloadEntity.getPath()), downloadEntity.getUrl());
|
||||
adapter.getUrlMap().put(downloadEntity.getPackageName(), downloadEntity.getUrl());
|
||||
|
||||
// 用户焦点在下载管理页面时有任务完成,直接把所有下载完成的任务标记为已读
|
||||
DownloadManager.getInstance().markDownloadedTaskAsRead();
|
||||
|
||||
@ -16,6 +16,7 @@ import androidx.recyclerview.widget.RecyclerView.ViewHolder;
|
||||
|
||||
import com.gh.common.util.DialogUtils;
|
||||
import com.gh.common.util.PackageInstaller;
|
||||
import com.gh.common.util.PackageLauncher;
|
||||
import com.gh.common.util.PackageUtils;
|
||||
import com.gh.common.xapk.XapkDialogHelper;
|
||||
import com.gh.gamecenter.common.entity.IconFloat;
|
||||
@ -210,7 +211,11 @@ class GameDownloadFragmentAdapter extends BaseRecyclerAdapter<ViewHolder> {
|
||||
} else if (XapkUnzipStatus.SUCCESS.name().equals(xapkStatus)) {
|
||||
viewHolder.binding.dmItemTvStartorpause.setButtonStyle(DownloadButton.ButtonStyle.XAPK_SUCCESS);
|
||||
viewHolder.binding.dmItemTvStartorpause.setProgress(1000);
|
||||
viewHolder.binding.dmItemTvStartorpause.setText(R.string.hundred_percent);
|
||||
if (XapkInstaller.INSTANCE.isInstalling(downloadEntity.getPath())) {
|
||||
viewHolder.binding.dmItemTvStartorpause.setText(R.string.installing);
|
||||
} else {
|
||||
viewHolder.binding.dmItemTvStartorpause.setText(R.string.install);
|
||||
}
|
||||
}
|
||||
if (xapkStatus != null && !xapkStatus.isEmpty()) {
|
||||
xapkStatusMap.put(downloadEntity.getUrl(), xapkStatus);
|
||||
@ -264,12 +269,15 @@ class GameDownloadFragmentAdapter extends BaseRecyclerAdapter<ViewHolder> {
|
||||
viewHolder.binding.dmItemTvStartorpause.setOnClickListener(v -> {
|
||||
String str = ((DownloadButton) v).getText();
|
||||
final String url = downloadEntity.getUrl();
|
||||
final String currentXApkStatus = downloadEntity.getMeta().get(XapkInstaller.XAPK_UNZIP_STATUS);
|
||||
DownloadManager.getInstance().put(url, System.currentTimeMillis());
|
||||
if (XapkUnzipStatus.UNZIPPING.name().equals(xapkStatus)) {
|
||||
if (XapkUnzipStatus.SUCCESS.name().equals(currentXApkStatus) && XapkInstaller.INSTANCE.isInstalling(downloadEntity.getPath())) {
|
||||
return;
|
||||
} else if (XapkUnzipStatus.UNZIPPING.name().equals(currentXApkStatus)) {
|
||||
XapkInstaller.cancelUnzipTask(downloadEntity);
|
||||
return;
|
||||
} else if (XapkUnzipStatus.FAILURE.name().equals(xapkStatus)
|
||||
|| XapkUnzipStatus.SUCCESS.name().equals(xapkStatus)) {
|
||||
} else if (XapkUnzipStatus.FAILURE.name().equals(currentXApkStatus)
|
||||
|| XapkUnzipStatus.SUCCESS.name().equals(currentXApkStatus)) {
|
||||
PermissionHelper.checkStoragePermissionBeforeAction(mContext, () -> {
|
||||
final String path = downloadEntity.getPath();
|
||||
if (downloadEntity.isPluggable()
|
||||
@ -334,7 +342,7 @@ class GameDownloadFragmentAdapter extends BaseRecyclerAdapter<ViewHolder> {
|
||||
}
|
||||
});
|
||||
} else if (str.equals(mContext.getString(R.string.launch))) {
|
||||
PackageUtils.launchApplicationByPackageName(mContext, downloadEntity.getPackageName());
|
||||
PackageLauncher.launchApp(mContext, null, downloadEntity.getPackageName());
|
||||
}
|
||||
break;
|
||||
case redirected:
|
||||
@ -629,8 +637,7 @@ class GameDownloadFragmentAdapter extends BaseRecyclerAdapter<ViewHolder> {
|
||||
statusMap.put(downloadEntity.getUrl(), downloadEntity.getStatus().name());
|
||||
if (DownloadStatus.done.equals(downloadEntity.getStatus())) {
|
||||
if (!ExtensionsKt.isSimulatorGame(downloadEntity)) {
|
||||
urlMap.put(PackageUtils.getPackageNameByPath(mContext,
|
||||
downloadEntity.getPath()), downloadEntity.getUrl());
|
||||
urlMap.put(downloadEntity.getPackageName(), downloadEntity.getUrl());
|
||||
mDownloadedList.add(downloadEntity);
|
||||
}
|
||||
} else {
|
||||
|
||||
@ -15,12 +15,11 @@ import com.gh.gamecenter.feature.exposure.ExposureType
|
||||
import com.gh.common.exposure.IExposable
|
||||
import com.gh.common.simulator.SimulatorGameManager.isSimulatorGame
|
||||
import com.gh.common.util.*
|
||||
import com.gh.common.util.DownloadItemUtils.setOnClickListener
|
||||
import com.gh.common.util.DownloadItemUtils.updateItem
|
||||
import com.gh.gamecenter.GameDetailActivity
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.viewholder.FooterViewHolder
|
||||
import com.gh.gamecenter.adapter.viewholder.GameViewHolder
|
||||
import com.gh.gamecenter.common.utils.putWidgetBusinessName
|
||||
import com.gh.gamecenter.common.utils.safelyGetInRelease
|
||||
import com.gh.gamecenter.feature.databinding.GameItemBinding
|
||||
import com.gh.gamecenter.feature.entity.GameEntity
|
||||
@ -92,17 +91,18 @@ class NewInstalledGameFragmentAdapter(context: Context, private var mViewModel:
|
||||
}
|
||||
binding.gameName.text = name
|
||||
generateExposureEvent(gameEntity)
|
||||
setOnClickListener(
|
||||
DownloadItemUtils.setOnClickListener(
|
||||
binding.root.context,
|
||||
binding.downloadBtn,
|
||||
gameEntity,
|
||||
1,
|
||||
this@NewInstalledGameFragmentAdapter,
|
||||
"(我的光环-已安装)", "我的光环-已安装" + ":" + gameEntity.name,
|
||||
gameEntity.exposureEvent // , () -> MtaHelper.onEvent("下载管理", "已安装", binding.downloadBtn.getText().toString())
|
||||
gameEntity.exposureEvent
|
||||
)
|
||||
updateItem(binding.root.context, gameEntity, GameViewHolder(binding), !gameEntity.isPluggable)
|
||||
holder.itemView.setOnClickListener { v: View? ->
|
||||
binding.downloadBtn.putWidgetBusinessName("下载管理")
|
||||
DownloadItemUtils.updateItem(binding.root.context, gameEntity, GameViewHolder(binding), !gameEntity.isPluggable)
|
||||
holder.itemView.setOnClickListener {
|
||||
DataCollectionUtils.uploadClick(binding.root.context, "列表", "我的光环-我的游戏", gameEntity.name)
|
||||
GameDetailActivity.startGameDetailActivity(
|
||||
binding.root.context,
|
||||
|
||||
@ -19,8 +19,6 @@ import com.gh.download.DownloadManager
|
||||
import com.gh.download.dialog.DownloadDialog
|
||||
import com.gh.gamecenter.DownloadManagerActivity
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.base.GlobalActivityManager
|
||||
import com.gh.gamecenter.common.constant.Constants
|
||||
import com.gh.gamecenter.common.utils.*
|
||||
import com.gh.gamecenter.common.view.BugFixedPopupWindow
|
||||
import com.gh.gamecenter.core.utils.CurrentActivityHolder
|
||||
@ -335,6 +333,8 @@ class UpdatableGameAdapter(private var mViewModel: UpdatableGameViewModel) :
|
||||
}
|
||||
}
|
||||
|
||||
updateBtn.putWidgetBusinessName("下载管理")
|
||||
updateBtn.putObject(update)
|
||||
updateBtn.setOnClickListener {
|
||||
val str: String = updateBtn.text.toString()
|
||||
if ("更新" == str || str.contains("化")) {
|
||||
@ -380,7 +380,7 @@ class UpdatableGameAdapter(private var mViewModel: UpdatableGameViewModel) :
|
||||
}
|
||||
}
|
||||
} else if (updateBtn.context.getString(R.string.launch) == str) {
|
||||
PackageUtils.launchApplicationByPackageName(updateBtn.context, update.packageName)
|
||||
PackageLauncher.launchApp(updateBtn.context, packageName = update.packageName)
|
||||
} else if (updateBtn.context.getString(R.string.resume) == str) {
|
||||
if (downloadEntity != null) {
|
||||
DownloadManager.getInstance().resume(downloadEntity, true)
|
||||
@ -401,21 +401,6 @@ class UpdatableGameAdapter(private var mViewModel: UpdatableGameViewModel) :
|
||||
updateBtn.buttonStyle = DownloadButton.ButtonStyle.NORMAL
|
||||
}
|
||||
}
|
||||
|
||||
SensorsBridge.trackEvent(
|
||||
"DownLoadbuttonClick",
|
||||
"game_id", update.id,
|
||||
"game_name", update.name ?: "",
|
||||
"game_type", update.categoryChinese,
|
||||
"download_status", update.downloadStatusChinese,
|
||||
"button_name", str,
|
||||
"page_name", GlobalActivityManager.getCurrentPageEntity().pageName,
|
||||
"page_id", GlobalActivityManager.getCurrentPageEntity().pageId,
|
||||
"page_business_id", GlobalActivityManager.getCurrentPageEntity().pageBusinessId,
|
||||
"last_page_name", GlobalActivityManager.getLastPageEntity().pageName,
|
||||
"last_page_id", GlobalActivityManager.getLastPageEntity().pageId,
|
||||
"last_page_business_id", GlobalActivityManager.getLastPageEntity().pageBusinessId
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -16,11 +16,8 @@ import com.gh.gamecenter.common.base.GlobalActivityManager.getCurrentPageEntity
|
||||
import com.gh.gamecenter.common.base.GlobalActivityManager.getLastPageEntity
|
||||
import com.gh.gamecenter.common.constant.Constants
|
||||
import com.gh.gamecenter.common.retrofit.Response
|
||||
import com.gh.gamecenter.common.utils.*
|
||||
import com.gh.gamecenter.common.utils.SensorsBridge.trackEvent
|
||||
import com.gh.gamecenter.common.utils.addMetaExtra
|
||||
import com.gh.gamecenter.common.utils.secondOrNull
|
||||
import com.gh.gamecenter.common.utils.toProperReadableSize
|
||||
import com.gh.gamecenter.common.utils.tryCatchInRelease
|
||||
import com.gh.gamecenter.core.utils.GsonUtils.toJson
|
||||
import com.gh.gamecenter.core.utils.SPUtils
|
||||
import com.gh.gamecenter.core.utils.UrlFilterUtils
|
||||
@ -78,7 +75,9 @@ class UpdatableGameViewModel(
|
||||
// 有闪退日志说这个 update 实体可能为空,实在看不原因 :(
|
||||
if (update == null) continue
|
||||
// 筛选仅下载管理出现的插件化更新
|
||||
if (update.isShowPlugin(PluginLocation.only_index) && update.downloadStatus != "smooth") {
|
||||
if (update.isShowPlugin(PluginLocation.only_index)
|
||||
&& update.downloadStatus != Constants.V_GAME
|
||||
&& update.downloadStatus != Constants.V_GAME_32) {
|
||||
val platform =
|
||||
PlatformUtils.getInstance(getApplication()).getPlatformName(update.platform)
|
||||
if (!platform.isNullOrEmpty() && "官方版" != platform) {
|
||||
@ -590,7 +589,8 @@ class UpdatableGameViewModel(
|
||||
downloadEntity.addMetaExtra(Constants.DOWNLOAD_ID, downloadId)
|
||||
downloadEntity.addMetaExtra(Constants.APK_MD5, update.md5)
|
||||
downloadEntity.addMetaExtra(Constants.GAME_NAME, update.name)
|
||||
downloadEntity.addMetaExtra(Constants.GAME_TYPE, update.categoryChinese)
|
||||
downloadEntity.addMetaExtra(Constants.GAME_CATEGORY_IN_CHINESE, update.categoryChinese)
|
||||
downloadEntity.putGameCategory(update.category ?: "")
|
||||
if (update.iconFloat != null) {
|
||||
downloadEntity.addMetaExtra(Constants.GAME_ICON_FLOAT_TOP_TEXT, update.iconFloat?.upperLeftText)
|
||||
downloadEntity.addMetaExtra(Constants.GAME_ICON_FLOAT_TOP_COLOR, update.iconFloat?.upperLeftColor)
|
||||
|
||||
@ -0,0 +1,27 @@
|
||||
package com.gh.gamecenter.entity
|
||||
|
||||
import android.os.Parcelable
|
||||
import com.gh.gamecenter.common.entity.LinkEntity
|
||||
import com.gh.gamecenter.feature.entity.PersonalEntity
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import kotlinx.parcelize.Parcelize
|
||||
|
||||
data class GameCollectionPlayerCreationEntity(
|
||||
@SerializedName("tip_link")
|
||||
val tipLink: LinkEntity? = null,
|
||||
val data: List<PlayerCreationItem>? = ArrayList()
|
||||
)
|
||||
|
||||
@Parcelize
|
||||
data class GameCollectionHotListTab(
|
||||
@SerializedName("_id")
|
||||
val id: String = "",
|
||||
val name: String = "",
|
||||
var position: Int = -1
|
||||
) : Parcelable
|
||||
|
||||
data class PlayerCreationItem(
|
||||
val user: PersonalEntity? = null,
|
||||
@SerializedName("game_list")
|
||||
val gameList: GamesCollectionEntity? = null
|
||||
)
|
||||
@ -18,6 +18,8 @@ data class GameInstall(
|
||||
var installTime: Long = 0,
|
||||
var version: String = "",
|
||||
var isSmoothGame: Boolean = false, // 是否是畅玩游戏
|
||||
var downloadStatus: String? = "", // 下载状态,对应 GameEntity 的 downloadStatus
|
||||
var category: String? = "", // 类型,对应 GameEntity 的 category
|
||||
var tag: Any? = null
|
||||
) {
|
||||
|
||||
@ -35,6 +37,8 @@ data class GameInstall(
|
||||
gameInstall.version = PackageUtils.getVersionNameByPackageName(installedPkgName) ?: "unknown"
|
||||
gameInstall.packageName = installedPkgName
|
||||
gameInstall.isSmoothGame = game.isVGame()
|
||||
gameInstall.downloadStatus = game.downloadStatus
|
||||
gameInstall.category = game.category
|
||||
return gameInstall
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
package com.gh.gamecenter.entity
|
||||
|
||||
import com.gh.gamecenter.common.constant.Constants
|
||||
import com.gh.gamecenter.common.entity.IconFloat
|
||||
import com.gh.gamecenter.feature.exposure.ExposureEvent
|
||||
import com.gh.gamecenter.feature.entity.*
|
||||
@ -60,7 +61,7 @@ data class GameUpdateEntity(
|
||||
val downloadStatusChinese: String
|
||||
get() = when (downloadStatus) {
|
||||
"on" -> "开启"
|
||||
"smooth" -> "畅玩"
|
||||
Constants.V_GAME, Constants.V_GAME_32 -> "畅玩"
|
||||
"appointment" -> "预约"
|
||||
"demo" -> "试玩"
|
||||
else -> ""
|
||||
|
||||
@ -83,7 +83,7 @@ class ForumArticleAskListFragment : LazyListFragment<AnswerEntity, ForumArticleA
|
||||
mListRv.setBackgroundColor(R.color.background_white.toColor(requireContext()))
|
||||
mScrollCalculatorHelper = ForumScrollCalculatorHelper(R.id.horizontalVideoView, R.id.verticalVideoView, 0)
|
||||
|
||||
requireView().setBackgroundColor(R.color.background_white.toColor(requireContext()))
|
||||
view?.setBackgroundColor(R.color.background_white.toColor(requireContext()))
|
||||
|
||||
mSkeletonScreen = Skeleton.bind(mBinding.listSkeleton)
|
||||
.shimmer(true)
|
||||
@ -142,13 +142,16 @@ class ForumArticleAskListFragment : LazyListFragment<AnswerEntity, ForumArticleA
|
||||
|
||||
override fun onLoadRefresh() {
|
||||
super.onLoadRefresh()
|
||||
requireView().setBackgroundColor(R.color.background_white.toColor(requireContext()))
|
||||
// Fix:https://sentry.shanqu.cc/organizations/lightgame/issues/288994/?project=22&query=LazyListFragment&statsPeriod=14d
|
||||
// Fragment在内存泄露的情况下,调用requireView()会触发崩溃,这里替换为getView()方法
|
||||
// TODO 解决Fragment内存泄露的问题
|
||||
view?.setBackgroundColor(R.color.background_white.toColor(requireContext()))
|
||||
}
|
||||
|
||||
override fun onLoadDone() {
|
||||
super.onLoadDone()
|
||||
requireView().setBackgroundColor(Color.TRANSPARENT)
|
||||
AppExecutor.uiExecutor.executeWithDelay(Runnable {
|
||||
view?.setBackgroundColor(Color.TRANSPARENT)
|
||||
mBaseHandler.postDelayed(Runnable {
|
||||
tryCatchInRelease {
|
||||
scroll()
|
||||
mScrollCalculatorHelper?.onScrollStateChanged(mListRv, RecyclerView.SCROLL_STATE_IDLE)
|
||||
@ -158,12 +161,12 @@ class ForumArticleAskListFragment : LazyListFragment<AnswerEntity, ForumArticleA
|
||||
|
||||
override fun onLoadError() {
|
||||
super.onLoadError()
|
||||
requireView().setBackgroundColor(Color.TRANSPARENT)
|
||||
view?.setBackgroundColor(Color.TRANSPARENT)
|
||||
}
|
||||
|
||||
override fun onLoadEmpty() {
|
||||
super.onLoadEmpty()
|
||||
requireView().setBackgroundColor(Color.TRANSPARENT)
|
||||
view?.setBackgroundColor(Color.TRANSPARENT)
|
||||
}
|
||||
|
||||
override fun hideRefreshingLayout() {
|
||||
|
||||
@ -773,7 +773,18 @@ class HomeSearchToolWrapperFragment : SearchToolWrapperFragment() {
|
||||
}
|
||||
|
||||
// 这里的 selectedPosition 指的是应该被高亮显示的 position
|
||||
val selectedPosition = (position + positionOffset).roundToInt()
|
||||
val selectedPosition = try {
|
||||
(position + positionOffset).roundToInt()
|
||||
} catch (e: IllegalArgumentException) {
|
||||
// roundToInt() 方法有时候会报 Cannot round NaN value. 错误
|
||||
// https://sentry.shanqu.cc/organizations/lightgame/issues/301377/?project=22
|
||||
SentryHelper.onEvent(
|
||||
"HOME_NAN_POSITION",
|
||||
"value",
|
||||
"$position+$positionOffset=(${position + positionOffset})"
|
||||
)
|
||||
position
|
||||
}
|
||||
val positionOffsetOnRealSelectedPosition = if (positionOffset >= 0.5) {
|
||||
positionOffset - 1
|
||||
} else {
|
||||
@ -797,8 +808,8 @@ class HomeSearchToolWrapperFragment : SearchToolWrapperFragment() {
|
||||
// positionOffset 小于零,表示 indicator 当前位置处于选中的 tab 的左边
|
||||
val indicatorOnLeft = positionOffset < 0F
|
||||
|
||||
val selectedTabBinding = mTabBindingList[selectedPosition]
|
||||
val selectedTabImageStyle = mTabImageStyleList[selectedPosition]
|
||||
val selectedTabBinding = mTabBindingList.safelyGetInRelease(selectedPosition) ?: return
|
||||
val selectedTabImageStyle = mTabImageStyleList.safelyGetInRelease(selectedPosition) ?: return
|
||||
|
||||
// 前一个 tab、当前选中的 tab、后一个 tab 的显示比例
|
||||
val preScaleRatio = 1 + abs(positionOffset) / 4
|
||||
|
||||
@ -58,7 +58,7 @@ class WelcomeDialogFragment : BaseDialogFragment() {
|
||||
DirectUtils.directToGameDetail(
|
||||
requireContext(),
|
||||
mWelcomeEntity?.link!!,
|
||||
EntranceConsts.ENTRANCE_WELCOME
|
||||
entrance = EntranceConsts.ENTRANCE_WELCOME
|
||||
)
|
||||
}
|
||||
EntranceConsts.HOST_COLUMN -> {
|
||||
|
||||
@ -1140,7 +1140,9 @@ class GameFragmentAdapter(
|
||||
DirectUtils.directToGameCollectionSquare(
|
||||
mContext,
|
||||
"版块内容列表",
|
||||
mViewModel.blockData?.name ?: ""
|
||||
mViewModel.blockData?.name ?: "",
|
||||
collectionName = column.name ?: "",
|
||||
collectionId = column.id ?: ""
|
||||
)
|
||||
}
|
||||
"column_test_v2" -> {
|
||||
@ -1231,7 +1233,13 @@ class GameFragmentAdapter(
|
||||
}
|
||||
}
|
||||
gameItemData.exposureEventList = exposureList
|
||||
holder.bindGameCollectionList(gameCollectionItemDataList, "版块内容列表")
|
||||
holder.bindGameCollectionList(
|
||||
gameCollectionItemDataList,
|
||||
"版块内容列表",
|
||||
mBasicExposureSource,
|
||||
mViewModel.blockData?.link ?: "",
|
||||
mViewModel.blockData?.name ?: ""
|
||||
)
|
||||
}
|
||||
|
||||
private fun bindGameDoubleCard(holder: DoubleCardViewHolder, position: Int) {
|
||||
|
||||
@ -961,7 +961,9 @@ class GameViewModel(application: Application, var blockData: SubjectRecommendEnt
|
||||
GameCollectionListItemData(
|
||||
gameCollectionItem = item,
|
||||
gameStartPosition = position,
|
||||
outerSequence = subjectEntity.outerSequence + 1
|
||||
outerSequence = subjectEntity.outerSequence + 1,
|
||||
collectionId = subjectEntity.id ?: "",
|
||||
collectionName = subjectEntity.name ?: "",
|
||||
)
|
||||
)
|
||||
position += if (item.count?.game!! > 2) 3 else if (item.games?.size == 0) 0 else
|
||||
|
||||
@ -105,6 +105,8 @@ class GameHorizontalSlideAdapter(
|
||||
},
|
||||
true
|
||||
)
|
||||
|
||||
holder.binding.simpleGameContainer.downloadBtn.putWidgetBusinessName("横向专题列表")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -61,14 +61,12 @@ class RankGameItem(val rankItemUi: RankGameItemUi) {
|
||||
"专题合集-排行榜-$columnName:${gameEntity.name}",
|
||||
exposureEvent,
|
||||
clickCallback = null,
|
||||
refreshCallback = object : EmptyCallback {
|
||||
override fun onCallback() {
|
||||
DownloadItemUtils.updateItem(root.context, gameEntity, GameViewHolder(root).also {
|
||||
it.gameDownloadBtn = downloadTv
|
||||
it.gameDownloadTips = downloadTipsLottie
|
||||
it.multiVersionDownloadTv = multiVersionDownloadTv
|
||||
}, true)
|
||||
}
|
||||
refreshCallback = {
|
||||
DownloadItemUtils.updateItem(root.context, gameEntity, GameViewHolder(root).also {
|
||||
it.gameDownloadBtn = downloadTv
|
||||
it.gameDownloadTips = downloadTipsLottie
|
||||
it.multiVersionDownloadTv = multiVersionDownloadTv
|
||||
}, true)
|
||||
},
|
||||
allStateClickCallback = null
|
||||
)
|
||||
@ -78,6 +76,8 @@ class RankGameItem(val rankItemUi: RankGameItemUi) {
|
||||
it.gameDownloadTips = downloadTipsLottie
|
||||
it.multiVersionDownloadTv = multiVersionDownloadTv
|
||||
}, true)
|
||||
|
||||
downloadTv.putWidgetBusinessName("专题合集")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -120,6 +120,9 @@ class GameVerticalAdapter(
|
||||
gameRatingTv.setTextColor(gameRatingTextColor)
|
||||
gameRatingTv.text = gameRatingText
|
||||
|
||||
// 没错,产品就把这个通用样式叫推荐榜单专题
|
||||
downloadTv.putWidgetBusinessName("推荐榜单专题")
|
||||
|
||||
// Fuck this view holder
|
||||
val tempViewHolder =
|
||||
holder.placeholderGameViewHolder ?: GameViewHolder(this@run.root).apply {
|
||||
|
||||
@ -15,7 +15,6 @@ class GameVerticalSlideViewHolder(val binding: GameVerticalSlideItemBinding) :
|
||||
verticalSlide: SubjectEntity,
|
||||
itemClick: (Int, GameEntity) -> Unit,
|
||||
transparentBackground: Boolean = false,
|
||||
showGameIconGif: Boolean = true
|
||||
): SpanCountPagerSnapHelper {
|
||||
val context = binding.root.context
|
||||
val spanCount = verticalSlide.list
|
||||
|
||||
@ -8,6 +8,8 @@ import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.base.activity.ToolBarActivity
|
||||
import com.gh.gamecenter.common.constant.EntranceConsts
|
||||
import com.gh.gamecenter.core.utils.DisplayUtils
|
||||
import com.gh.gamecenter.feature.exposure.ExposureEvent
|
||||
import com.gh.gamecenter.feature.exposure.ExposureSource
|
||||
|
||||
class GameCollectionDetailActivity : ToolBarActivity() {
|
||||
|
||||
@ -69,13 +71,17 @@ class GameCollectionDetailActivity : ToolBarActivity() {
|
||||
gameCollectionId: String,
|
||||
topCommentId: String = "",
|
||||
isFromSquare: Boolean = false,
|
||||
isScrollToCommentArea: Boolean = false
|
||||
isScrollToCommentArea: Boolean = false,
|
||||
exposureSourceList: ArrayList<ExposureSource>? = null
|
||||
): Intent {
|
||||
val bundle = Bundle()
|
||||
bundle.putString(EntranceConsts.KEY_GAME_COLLECTION_ID, gameCollectionId)
|
||||
bundle.putString(EntranceConsts.KEY_TOP_COMMENT_ID, topCommentId)
|
||||
bundle.putBoolean(EntranceConsts.KEY_IS_FROM_SQUARE, isFromSquare)
|
||||
bundle.putBoolean(EntranceConsts.KEY_SCROLL_TO_COMMENT_AREA, isScrollToCommentArea)
|
||||
if (exposureSourceList != null) {
|
||||
bundle.putParcelableArrayList(EntranceConsts.KEY_EXPOSURE_SOURCE_LIST, exposureSourceList)
|
||||
}
|
||||
return getTargetIntent(
|
||||
context,
|
||||
GameCollectionDetailActivity::class.java,
|
||||
|
||||
@ -54,6 +54,7 @@ open class GameCollectionDetailAdapter(
|
||||
private val type: AdapterType,
|
||||
val mEntrance: String,
|
||||
val mViewModel: GameCollectionDetailViewModel,
|
||||
private val mBasicExposureSource: List<ExposureSource>? = null,
|
||||
commentClosure: ((CommentEntity) -> Unit)? = null
|
||||
) : BaseCommentAdapter(context, mViewModel, type, mEntrance, commentClosure), IExposable {
|
||||
|
||||
@ -121,7 +122,6 @@ open class GameCollectionDetailAdapter(
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
else -> super.onCreateViewHolder(parent, viewType)
|
||||
}
|
||||
}
|
||||
@ -607,10 +607,16 @@ open class GameCollectionDetailAdapter(
|
||||
initServerType(gameEntity)
|
||||
|
||||
val exposureSources = ArrayList<ExposureSource>().apply {
|
||||
add(ExposureSource("游戏单", "${mViewModel.gameCollectionTitle}+${mViewModel.gameCollectionId}"))
|
||||
add(
|
||||
ExposureSource(
|
||||
"游戏单详情",
|
||||
"${mViewModel.gameCollectionTitle}+${mViewModel.gameCollectionId}"
|
||||
)
|
||||
)
|
||||
}
|
||||
val exposureEvent = ExposureEvent.createEvent(
|
||||
val exposureEvent = ExposureEvent.createEventWithSourceConcat(
|
||||
gameEntity,
|
||||
mBasicExposureSource ?: arrayListOf(),
|
||||
exposureSources,
|
||||
null,
|
||||
ExposureType.EXPOSURE
|
||||
@ -637,6 +643,7 @@ open class GameCollectionDetailAdapter(
|
||||
exposureEvent
|
||||
)
|
||||
}
|
||||
binding.gameItemIncluded.downloadBtn.putWidgetBusinessName("游戏单")
|
||||
|
||||
DownloadItemUtils.setOnClickListener(
|
||||
mContext,
|
||||
|
||||
@ -44,6 +44,7 @@ import com.gh.gamecenter.entity.GamesCollectionDetailEntity
|
||||
import com.gh.gamecenter.eventbus.EBDownloadStatus
|
||||
import com.gh.gamecenter.eventbus.EBPackage
|
||||
import com.gh.gamecenter.eventbus.EBUserFollow
|
||||
import com.gh.gamecenter.feature.exposure.ExposureSource
|
||||
import com.gh.gamecenter.gamedetail.GameDetailFragment
|
||||
import com.gh.gamecenter.home.video.ScrollCalculatorHelper
|
||||
import com.gh.gamecenter.login.user.UserManager
|
||||
@ -111,13 +112,18 @@ class GameCollectionDetailFragment :
|
||||
)
|
||||
)
|
||||
|
||||
override fun provideListAdapter() =
|
||||
mAdapter ?: GameCollectionDetailAdapter(
|
||||
override fun provideListAdapter(): GameCollectionDetailAdapter {
|
||||
val basicExposureSource =
|
||||
requireArguments().getParcelableArrayList<ExposureSource>(EntranceConsts.KEY_EXPOSURE_SOURCE_LIST)
|
||||
?: arrayListOf()
|
||||
return mAdapter ?: GameCollectionDetailAdapter(
|
||||
requireContext(),
|
||||
BaseCommentAdapter.AdapterType.COMMENT,
|
||||
mEntrance,
|
||||
mListViewModel
|
||||
mListViewModel,
|
||||
basicExposureSource
|
||||
).apply { mAdapter = this }
|
||||
}
|
||||
|
||||
override fun getItemDecoration() = null
|
||||
|
||||
@ -768,6 +774,7 @@ class GameCollectionDetailFragment :
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
mElapsedHelper?.resetCounting()
|
||||
mElapsedHelper?.resumeCounting()
|
||||
DownloadManager.getInstance().addObserver(mDataWatcher)
|
||||
|
||||
if (!mIsPauseTopVideo) {
|
||||
@ -808,6 +815,7 @@ class GameCollectionDetailFragment :
|
||||
com.gh.common.util.NewFlatLogUtils.logGameCollectStayTime(stayTime, it.id, it.title)
|
||||
}
|
||||
|
||||
mElapsedHelper?.pauseCounting()
|
||||
mElapsedHelper?.elapsedTime?.let {
|
||||
if (it >= 3) {
|
||||
val trackEvent = JSONObject()
|
||||
|
||||
@ -23,7 +23,7 @@ class GameCollectionCommentConversationAdapter(
|
||||
type: AdapterType,
|
||||
mEntrance: String,
|
||||
commentClosure: ((CommentEntity) -> Unit)? = null
|
||||
) : GameCollectionDetailAdapter(context, type, mEntrance, mViewModel, commentClosure) {
|
||||
) : GameCollectionDetailAdapter(context, type, mEntrance, mViewModel, null, commentClosure) {
|
||||
|
||||
var topCommentVH: TopCommentItemViewHolder? = null
|
||||
|
||||
|
||||
@ -0,0 +1,26 @@
|
||||
package com.gh.gamecenter.gamecollection.hotlist
|
||||
|
||||
import android.os.Bundle
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.base.activity.BaseActivity
|
||||
import com.gh.gamecenter.core.utils.DisplayUtils
|
||||
|
||||
class GameCollectionHotListActivity : BaseActivity() {
|
||||
override fun getLayoutId(): Int {
|
||||
return R.layout.activity_amway
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
DisplayUtils.transparentStatusBar(this)
|
||||
|
||||
val containerFragment = supportFragmentManager.findFragmentByTag(
|
||||
GameCollectionHotListWrapperFragment::class.java.name
|
||||
)
|
||||
?: GameCollectionHotListWrapperFragment().with(intent.extras)
|
||||
supportFragmentManager.beginTransaction()
|
||||
.replace(R.id.placeholder, containerFragment, GameCollectionHotListWrapperFragment::class.java.name)
|
||||
.commitAllowingStateLoss()
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,197 @@
|
||||
package com.gh.gamecenter.gamecollection.hotlist
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.Typeface
|
||||
import android.view.ViewGroup
|
||||
import androidx.constraintlayout.widget.ConstraintLayout
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.recyclerview.widget.GridLayoutManager
|
||||
import androidx.recyclerview.widget.GridLayoutManager.SpanSizeLookup
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.gh.common.exposure.IExposable
|
||||
import com.gh.common.util.DirectUtils
|
||||
import com.gh.common.util.NewFlatLogUtils
|
||||
import com.gh.gamecenter.GameDetailActivity
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.base.BaseRecyclerViewHolder
|
||||
import com.gh.gamecenter.common.base.activity.BaseActivity
|
||||
import com.gh.gamecenter.common.baselist.ListAdapter
|
||||
import com.gh.gamecenter.common.constant.ItemViewType
|
||||
import com.gh.gamecenter.common.utils.*
|
||||
import com.gh.gamecenter.common.viewholder.FooterViewHolder
|
||||
import com.gh.gamecenter.core.utils.DisplayUtils
|
||||
import com.gh.gamecenter.databinding.ItemGameCollectionHotListBinding
|
||||
import com.gh.gamecenter.entity.GameCollectionHotListTab
|
||||
import com.gh.gamecenter.feature.entity.GameEntity
|
||||
import com.gh.gamecenter.feature.exposure.ExposureEvent
|
||||
import com.gh.gamecenter.feature.exposure.ExposureSource
|
||||
import com.gh.gamecenter.gamecollection.square.GameCollectionListItemData
|
||||
|
||||
class GameCollectionHotListAdapter(
|
||||
context: Context,
|
||||
private val mTabEntity: GameCollectionHotListTab? = null,
|
||||
private val mViewModel: GameCollectionHotListViewModel,
|
||||
private val mEntrance: String,
|
||||
private val mPath: String,
|
||||
private val mBasicExposureSource: List<ExposureSource>
|
||||
) : ListAdapter<GameCollectionListItemData>(context), IExposable {
|
||||
private val mCoverWidth = (DisplayUtils.getScreenWidth() - 40F.dip2px()) / 2
|
||||
override fun getItemViewType(position: Int): Int {
|
||||
return if (position == itemCount - 1) ItemViewType.ITEM_FOOTER else ItemViewType.ITEM_BODY
|
||||
}
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
|
||||
return if (viewType == ItemViewType.ITEM_FOOTER) {
|
||||
FooterViewHolder(
|
||||
mLayoutInflater.inflate(
|
||||
R.layout.refresh_footerview,
|
||||
parent,
|
||||
false
|
||||
)
|
||||
)
|
||||
} else {
|
||||
GameCollectionHotListItemViewHolder(parent.toBinding())
|
||||
}
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
|
||||
if (holder is GameCollectionHotListItemViewHolder) {
|
||||
val itemData = mEntityList[position]
|
||||
itemData.exposureEvent = ExposureEvent.createEventWithSourceConcat(
|
||||
GameEntity().apply {
|
||||
outerSequence = mTabEntity?.position
|
||||
sequence = position
|
||||
},
|
||||
mBasicExposureSource,
|
||||
listOf(
|
||||
ExposureSource(
|
||||
"游戏单",
|
||||
"${itemData.gameCollectionItem?.title} + ${itemData.gameCollectionItem?.id}"
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
val entity = itemData.gameCollectionItem
|
||||
holder.binding.run {
|
||||
root.background = R.drawable.background_shape_white_radius_8.toDrawable(mContext)
|
||||
titleTv.setTextColor(R.color.text_title.toColor(mContext))
|
||||
userTv.setTextColor(R.color.text_subtitle.toColor(mContext))
|
||||
gameCountTv.setTextColor(R.color.text_subtitleDesc.toColor(mContext))
|
||||
|
||||
rankIv.goneIf(position > 2) {
|
||||
rankIv.setImageResource(
|
||||
when (position) {
|
||||
0 -> R.drawable.icon_leaderboard_1
|
||||
1 -> R.drawable.icon_leaderboard_2
|
||||
else -> R.drawable.icon_leaderboard_3
|
||||
}
|
||||
)
|
||||
}
|
||||
rankTv.goneIf(position < 3) {
|
||||
rankTv.typeface = Typeface.createFromAsset(mContext.assets, "fonts/d_din_bold_only_number.ttf")
|
||||
rankTv.text = "${position + 1}"
|
||||
}
|
||||
stampIv.goneIf(entity?.stamp.isNullOrEmpty())
|
||||
stampIv.setBackgroundResource(if (entity?.stamp == "official") R.drawable.label_game_collection_official else R.drawable.label_game_collection_special_choice)
|
||||
titleTv.text = entity?.title
|
||||
userTv.text = entity?.user?.name
|
||||
coverImage.setTag(ImageUtils.TAG_TARGET_WIDTH, mCoverWidth)
|
||||
ImageUtils.display(coverImage, entity?.cover)
|
||||
ImageUtils.display(userIv, entity?.user?.icon)
|
||||
|
||||
val gameIcons = arrayListOf(gameImage1, gameImage2, gameImage3)
|
||||
val games = entity?.games ?: arrayListOf()
|
||||
gameIcons.forEachIndexed { index, gameIcon ->
|
||||
gameIcon.goneIf(games.size < index + 1) {
|
||||
val gameEntity = games[index].toGameEntity()
|
||||
gameIcon.displayGameIcon(gameEntity)
|
||||
gameIcon.setBorderColor(R.color.background_white)
|
||||
gameIcon.setOnClickListener {
|
||||
NewFlatLogUtils.logGameCollectionHotListClick(
|
||||
mTabEntity?.name ?: "",
|
||||
mTabEntity?.id ?: "",
|
||||
mTabEntity?.name ?: "",
|
||||
"游戏"
|
||||
)
|
||||
GameDetailActivity.startGameDetailActivity(
|
||||
mContext,
|
||||
gameEntity.id,
|
||||
BaseActivity.mergeEntranceAndPath(mEntrance, mPath),
|
||||
itemData.exposureEvent
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
gameCountTv.goneIf(games.isEmpty())
|
||||
titleTv.maxLines = if (games.isEmpty()) 2 else 1
|
||||
titleTv.layoutParams = (titleTv.layoutParams as ConstraintLayout.LayoutParams).apply {
|
||||
topMargin = if (games.isEmpty()) 10F.dip2px() else 32F.dip2px()
|
||||
}
|
||||
entity?.count?.let { gameCountTv.text = "+${it.game - games.size}" }
|
||||
listOf(userIv, userTv).forEach {
|
||||
it.setOnClickListener {
|
||||
NewFlatLogUtils.logGameCollectionHotListClick(
|
||||
mTabEntity?.name ?: "",
|
||||
mTabEntity?.id ?: "",
|
||||
mTabEntity?.name ?: "",
|
||||
"个人主页"
|
||||
)
|
||||
DirectUtils.directToHomeActivity(mContext, entity?.user?.id, 0, mEntrance, mPath)
|
||||
}
|
||||
}
|
||||
root.setOnClickListener {
|
||||
NewFlatLogUtils.logGameCollectionHotListClick(
|
||||
mTabEntity?.name ?: "",
|
||||
mTabEntity?.id ?: "",
|
||||
mTabEntity?.name ?: "",
|
||||
"游戏单"
|
||||
)
|
||||
DirectUtils.directToGameCollectionDetail(
|
||||
it.context,
|
||||
entity?.id ?: "",
|
||||
mEntrance,
|
||||
mPath,
|
||||
itemData.exposureEvent
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
if (holder is FooterViewHolder) {
|
||||
holder.initItemPadding()
|
||||
holder.initFooterViewHolder(mViewModel, mIsLoading, mIsNetworkError, mIsOver)
|
||||
holder.hint.setTextColor(ContextCompat.getColor(mContext, R.color.text_B3B3B3))
|
||||
val lp = holder.itemView.layoutParams as RecyclerView.LayoutParams
|
||||
lp.height = DisplayUtils.dip2px(48F)
|
||||
lp.width = ViewGroup.LayoutParams.MATCH_PARENT
|
||||
holder.itemView.layoutParams = lp
|
||||
}
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int = if (mEntityList.isNotEmpty()) mEntityList.size + 1 else 0
|
||||
|
||||
override fun getEventByPosition(pos: Int): ExposureEvent? {
|
||||
return mEntityList[pos].exposureEvent
|
||||
}
|
||||
|
||||
override fun getEventListByPosition(pos: Int): List<ExposureEvent>? {
|
||||
return mEntityList[pos].exposureEventList
|
||||
}
|
||||
|
||||
override fun onAttachedToRecyclerView(recyclerView: RecyclerView) {
|
||||
super.onAttachedToRecyclerView(recyclerView)
|
||||
val layoutManager = recyclerView.layoutManager
|
||||
if (layoutManager is GridLayoutManager) {
|
||||
layoutManager.spanSizeLookup = object : SpanSizeLookup() {
|
||||
override fun getSpanSize(position: Int): Int {
|
||||
if (getItemViewType(position) == ItemViewType.ITEM_FOOTER) {
|
||||
return layoutManager.spanCount
|
||||
}
|
||||
return 1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class GameCollectionHotListItemViewHolder(val binding: ItemGameCollectionHotListBinding) :
|
||||
BaseRecyclerViewHolder<Any>(binding.root)
|
||||
}
|
||||
@ -0,0 +1,109 @@
|
||||
package com.gh.gamecenter.gamecollection.hotlist
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import androidx.recyclerview.widget.DefaultItemAnimator
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.gh.common.exposure.ExposureListener
|
||||
import com.gh.common.util.NewFlatLogUtils
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.baselist.ListFragment
|
||||
import com.gh.gamecenter.common.constant.EntranceConsts
|
||||
import com.gh.gamecenter.common.utils.dip2px
|
||||
import com.gh.gamecenter.common.utils.viewModelProvider
|
||||
import com.gh.gamecenter.common.view.FixGridLayoutManager
|
||||
import com.gh.gamecenter.common.view.GridSpacingItemDecoration
|
||||
import com.gh.gamecenter.core.utils.TimeElapsedHelper
|
||||
import com.gh.gamecenter.entity.GameCollectionHotListTab
|
||||
import com.gh.gamecenter.feature.exposure.ExposureSource
|
||||
import com.gh.gamecenter.gamecollection.square.GameCollectionListItemData
|
||||
|
||||
class GameCollectionHotListFragment : ListFragment<GameCollectionListItemData, GameCollectionHotListViewModel>() {
|
||||
private lateinit var mBasicExposureSource: List<ExposureSource>
|
||||
private lateinit var mExposureListener: ExposureListener
|
||||
private lateinit var mViewModel: GameCollectionHotListViewModel
|
||||
private var mAdapter: GameCollectionHotListAdapter? = null
|
||||
private var mTabEntity: GameCollectionHotListTab? = null
|
||||
private val mElapsedHelper by lazy { TimeElapsedHelper() }
|
||||
private var mIsLoadDone = false
|
||||
|
||||
override fun provideListAdapter(): GameCollectionHotListAdapter {
|
||||
if (mAdapter == null) {
|
||||
mAdapter = GameCollectionHotListAdapter(
|
||||
requireContext(),
|
||||
mTabEntity,
|
||||
mViewModel,
|
||||
mEntrance,
|
||||
arguments?.getString(EntranceConsts.KEY_PATH) ?: "",
|
||||
mBasicExposureSource
|
||||
)
|
||||
}
|
||||
return mAdapter as GameCollectionHotListAdapter
|
||||
}
|
||||
|
||||
override fun provideListViewModel(): GameCollectionHotListViewModel {
|
||||
mViewModel = viewModelProvider(GameCollectionHotListViewModel.Factory(mTabEntity?.id ?: ""))
|
||||
return mViewModel
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
mTabEntity = requireArguments().getParcelable(EntranceConsts.KEY_TAB)
|
||||
mBasicExposureSource =
|
||||
listOf(ExposureSource("游戏单热榜", ""), ExposureSource("游戏单合集", mTabEntity?.id ?: ""))
|
||||
super.onCreate(savedInstanceState)
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
if (mListRefresh != null) {
|
||||
mListRefresh!!.setColorSchemeResources(R.color.theme)
|
||||
mListRefresh!!.setOnRefreshListener(this)
|
||||
}
|
||||
mLayoutManager = FixGridLayoutManager(requireContext(), 2)
|
||||
mListRv.setPadding(16F.dip2px(), 0, 16F.dip2px(), 0)
|
||||
(mListRv.itemAnimator as DefaultItemAnimator?)!!.supportsChangeAnimations = false
|
||||
mListRv.layoutManager = mLayoutManager
|
||||
mListRv.adapter = provideListAdapter()
|
||||
mExposureListener = ExposureListener(this, provideListAdapter())
|
||||
mListRv.addOnScrollListener(mExposureListener)
|
||||
|
||||
if (mReuseNoConn != null) mReuseNoConn!!.setOnClickListener { view1: View? -> onLoadRefresh() }
|
||||
}
|
||||
|
||||
override fun getItemDecoration(): RecyclerView.ItemDecoration {
|
||||
return GridSpacingItemDecoration(2, 8F.dip2px(), false, 0)
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
mElapsedHelper.pauseCounting()
|
||||
NewFlatLogUtils.logGameCollectionHotListTabView(
|
||||
mElapsedHelper.elapsedTime,
|
||||
mTabEntity?.name ?: "",
|
||||
mTabEntity?.id ?: "",
|
||||
mTabEntity?.name ?: ""
|
||||
)
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
mElapsedHelper.resetCounting()
|
||||
mElapsedHelper.resumeCounting()
|
||||
|
||||
if (mIsLoadDone) {
|
||||
onChanged(mViewModel.obsListData.value)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onChanged(ts: MutableList<GameCollectionListItemData>?) {
|
||||
if (ts != null) {
|
||||
if (mIsLoadDone) {
|
||||
super.onChanged(ts)
|
||||
}
|
||||
mIsLoadDone = true
|
||||
}
|
||||
}
|
||||
|
||||
fun setListRefreshEnable(enable: Boolean) {
|
||||
mListRefresh?.isEnabled = enable
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,48 @@
|
||||
package com.gh.gamecenter.gamecollection.hotlist
|
||||
|
||||
import android.app.Application
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import com.gh.common.filter.RegionSettingHelper
|
||||
import com.gh.gamecenter.common.baselist.ListViewModel
|
||||
import com.gh.gamecenter.common.baselist.LoadStatus
|
||||
import com.gh.gamecenter.entity.GamesCollectionEntity
|
||||
import com.gh.gamecenter.gamecollection.square.GameCollectionListItemData
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager
|
||||
import com.halo.assistant.HaloApp
|
||||
import io.reactivex.Observable
|
||||
|
||||
class GameCollectionHotListViewModel(application: Application, private val mCollectionId: String) :
|
||||
ListViewModel<GamesCollectionEntity, GameCollectionListItemData>(application) {
|
||||
private val mApi = RetrofitManager.getInstance().api
|
||||
|
||||
override fun provideDataObservable(page: Int): Observable<MutableList<GamesCollectionEntity>> {
|
||||
return mApi.getGameCollectionHotList(mCollectionId)
|
||||
}
|
||||
|
||||
override fun mergeResultLiveData() {
|
||||
mResultLiveData.addSource(mListLiveData) {
|
||||
var position = 0
|
||||
val itemDataList = ArrayList<GameCollectionListItemData>()
|
||||
for (item in it) {
|
||||
item.games = RegionSettingHelper.filterSimpleGame(item.games)
|
||||
itemDataList.add(
|
||||
GameCollectionListItemData(
|
||||
gameCollectionItem = item,
|
||||
gameStartPosition = position,
|
||||
isGameCollectionItem = true
|
||||
)
|
||||
)
|
||||
position += if (item.count?.game!! > 2) 3 else if (item.games?.size == 0) 0 else item.count?.game ?: 0
|
||||
}
|
||||
mResultLiveData.postValue(itemDataList)
|
||||
mLoadStatusLiveData.postValue(LoadStatus.INIT_OVER)
|
||||
}
|
||||
}
|
||||
|
||||
class Factory(private val mCollectionId: String) : ViewModelProvider.NewInstanceFactory() {
|
||||
override fun <T : ViewModel> create(modelClass: Class<T>): T {
|
||||
return GameCollectionHotListViewModel(HaloApp.getInstance().application, mCollectionId) as T
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,241 @@
|
||||
package com.gh.gamecenter.gamecollection.hotlist
|
||||
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.TextView
|
||||
import androidx.constraintlayout.widget.ConstraintLayout
|
||||
import androidx.core.os.bundleOf
|
||||
import androidx.core.view.ViewCompat
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.viewpager2.adapter.FragmentStateAdapter
|
||||
import androidx.viewpager2.widget.ViewPager2.OnPageChangeCallback
|
||||
import com.gh.common.util.DirectUtils
|
||||
import com.gh.common.util.NewFlatLogUtils
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.base.fragment.LazyFragment
|
||||
import com.gh.gamecenter.common.constant.EntranceConsts
|
||||
import com.gh.gamecenter.common.utils.*
|
||||
import com.gh.gamecenter.core.utils.DisplayUtils
|
||||
import com.gh.gamecenter.core.utils.TimeElapsedHelper
|
||||
import com.gh.gamecenter.databinding.FragmentGameCollectionHotListWrapperBinding
|
||||
import com.gh.gamecenter.entity.GameCollectionHotListTab
|
||||
import com.google.android.material.tabs.TabLayout
|
||||
import com.google.android.material.tabs.TabLayoutMediator
|
||||
import kotlin.math.abs
|
||||
|
||||
class GameCollectionHotListWrapperFragment : LazyFragment() {
|
||||
|
||||
private lateinit var mBinding: FragmentGameCollectionHotListWrapperBinding
|
||||
private lateinit var mViewModel: GameCollectionHotListWrapperViewModel
|
||||
|
||||
private val mTabEntityList = arrayListOf<GameCollectionHotListTab>()
|
||||
|
||||
private var mAdapter: FragmentStateAdapter? = null
|
||||
|
||||
private var mIsCollapsed = false
|
||||
|
||||
override fun getRealLayoutId(): Int = R.layout.fragment_game_collection_hot_list_wrapper
|
||||
|
||||
override fun onFragmentPause() {
|
||||
super.onFragmentPause()
|
||||
val stayTime = (System.currentTimeMillis() - startPageTime) / 1000
|
||||
if (mTabEntityList.isNotEmpty()) {
|
||||
NewFlatLogUtils.logGameCollectionHotListExit(
|
||||
stayTime,
|
||||
mTabEntityList.safelyGetInRelease(mBinding.viewPager.currentItem)?.name ?: ""
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onFragmentFirstVisible() {
|
||||
super.onFragmentFirstVisible()
|
||||
mViewModel = viewModelProvider()
|
||||
|
||||
mViewModel.hotListTabListLiveData.observe(this) {
|
||||
if (it != null) {
|
||||
mTabEntityList.clear()
|
||||
mTabEntityList.add(GameCollectionHotListTab(name = PLAYER_CREATION_TAB_NAME, position = 0))
|
||||
mTabEntityList.addAll(it)
|
||||
|
||||
initViewPager()
|
||||
initTabLayout()
|
||||
} else {
|
||||
mBinding.reuseNoConnection.root.visibility = View.VISIBLE
|
||||
}
|
||||
}
|
||||
|
||||
NewFlatLogUtils.logGameCollectionHotListEnter(mEntrance)
|
||||
}
|
||||
|
||||
override fun onRealLayoutInflated(inflatedView: View) {
|
||||
super.onRealLayoutInflated(inflatedView)
|
||||
mBinding = FragmentGameCollectionHotListWrapperBinding.bind(inflatedView)
|
||||
}
|
||||
|
||||
override fun initRealView() {
|
||||
super.initRealView()
|
||||
mBinding.run {
|
||||
ViewCompat.setOnApplyWindowInsetsListener(appbar) { _, insets ->
|
||||
(toolbar.layoutParams as ViewGroup.MarginLayoutParams).topMargin =
|
||||
insets.systemWindowInsetTop
|
||||
insets.consumeSystemWindowInsets()
|
||||
}
|
||||
val collapsingTrigger = 66F.dip2px() + DisplayUtils.getStatusBarHeight(requireContext().resources)
|
||||
|
||||
toolbar.setNavigationOnClickListener { requireActivity().finish() }
|
||||
|
||||
collapsingToolbar.scrimVisibleHeightTrigger = collapsingTrigger
|
||||
collapsingToolbar.scrimShownAction = {
|
||||
mIsCollapsed = it
|
||||
DisplayUtils.setLightStatusBar(requireActivity(), !mIsDarkModeOn && it)
|
||||
changeToolbarStyle(it)
|
||||
}
|
||||
|
||||
appbar.addOnOffsetChangedListener { _, verticalOffset ->
|
||||
val absOffset = abs(verticalOffset)
|
||||
val invisibleOffset = DisplayUtils.dip2px(30F)
|
||||
|
||||
if (absOffset <= invisibleOffset) {
|
||||
titleTv.alpha = 1 - (absOffset.toFloat() / invisibleOffset)
|
||||
} else {
|
||||
titleTv.alpha = 0F
|
||||
}
|
||||
|
||||
val currentFragment = childFragmentManager.findFragmentByTag("f${mBinding.viewPager.currentItem}")
|
||||
if (currentFragment is GameCollectionPlayerCreationFragment) {
|
||||
currentFragment.setListRefreshEnable(absOffset <= 2)
|
||||
} else if (currentFragment is GameCollectionHotListFragment) {
|
||||
currentFragment.setListRefreshEnable(absOffset <= 2)
|
||||
}
|
||||
}
|
||||
|
||||
reuseNoConnection.connectionReloadTv.setOnClickListener {
|
||||
reuseNoConnection.root.visibility = View.GONE
|
||||
mViewModel.getGameCollectionHotListTab()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun changeToolbarStyle(isCollapsed: Boolean) {
|
||||
if (isCollapsed) {
|
||||
mBinding.titleTv.alpha = 1F
|
||||
mBinding.titleTv.visibility = View.VISIBLE
|
||||
mBinding.titleTv.setTextColor(R.color.text_black.toColor(requireContext()))
|
||||
mBinding.toolbar.setNavigationIcon(R.drawable.ic_bar_back)
|
||||
mBinding.collapsingToolbar.setContentScrimColor(R.color.background_white.toColor(requireContext()))
|
||||
mBinding.tabContainer.setBackgroundColor(R.color.background_white.toColor(requireContext()))
|
||||
mBinding.tabLayout.layoutParams = (mBinding.tabLayout.layoutParams as ConstraintLayout.LayoutParams).apply {
|
||||
topMargin = 12F.dip2px()
|
||||
}
|
||||
} else {
|
||||
mBinding.titleTv.visibility = View.GONE
|
||||
mBinding.toolbar.setNavigationIcon(R.drawable.ic_bar_back_light)
|
||||
mBinding.collapsingToolbar.setContentScrimColor(R.color.background.toColor(requireContext()))
|
||||
mBinding.tabContainer.background = null
|
||||
mBinding.tabLayout.layoutParams = (mBinding.tabLayout.layoutParams as ConstraintLayout.LayoutParams).apply {
|
||||
topMargin = 8F.dip2px()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun initTabLayout() {
|
||||
mBinding.tabLayout.run {
|
||||
TabLayoutMediator(this, mBinding.viewPager) { tab, position ->
|
||||
val tabEntity = mTabEntityList.safelyGetInRelease(position)
|
||||
val view = LayoutInflater.from(context).inflate(R.layout.game_collection_hot_list_tab_item, null)
|
||||
view.findViewById<TextView>(R.id.tab_title)?.text = tabEntity?.name
|
||||
tab.customView = view
|
||||
updateTabStyle(tab, position == mBinding.viewPager.currentItem)
|
||||
}.attach()
|
||||
val firstTabView = (getChildAt(0) as ViewGroup).getChildAt(0)
|
||||
firstTabView.layoutParams = (firstTabView.layoutParams as LinearLayout.LayoutParams).also {
|
||||
it.leftMargin = 16F.dip2px()
|
||||
}
|
||||
val lastTabView = (getChildAt(0) as ViewGroup).getChildAt(mTabEntityList.size - 1)
|
||||
lastTabView.layoutParams = (lastTabView.layoutParams as LinearLayout.LayoutParams).also {
|
||||
it.rightMargin = 8F.dip2px()
|
||||
}
|
||||
addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener {
|
||||
override fun onTabSelected(tab: TabLayout.Tab) {
|
||||
updateTabStyle(tab, true)
|
||||
|
||||
val tabEntity = mTabEntityList.safelyGetInRelease(tab.position)
|
||||
NewFlatLogUtils.logGameCollectionHotListTabClick(
|
||||
tabEntity?.name ?: "",
|
||||
tabEntity?.id ?: "",
|
||||
tabEntity?.name ?: ""
|
||||
)
|
||||
}
|
||||
|
||||
override fun onTabUnselected(tab: TabLayout.Tab) {
|
||||
updateTabStyle(tab, false)
|
||||
}
|
||||
|
||||
override fun onTabReselected(tab: TabLayout.Tab) {
|
||||
updateTabStyle(tab, true)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateTabStyle(tab: TabLayout.Tab, isChecked: Boolean) {
|
||||
tab.customView?.background =
|
||||
if (isChecked) R.drawable.bg_game_collection_hot_list_tab_selected.toDrawable(requireContext()) else R.drawable.bg_game_collection_hot_list_tab_unselected.toDrawable(
|
||||
requireContext()
|
||||
)
|
||||
tab.customView?.findViewById<TextView>(R.id.tab_title)?.run {
|
||||
setTextColor(
|
||||
if (isChecked) R.color.theme_font.toColor(requireContext()) else R.color.text_subtitleDesc.toColor(
|
||||
requireContext()
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun initViewPager() {
|
||||
mAdapter = object : FragmentStateAdapter(this) {
|
||||
override fun getItemCount(): Int = mTabEntityList.size
|
||||
|
||||
override fun createFragment(position: Int): Fragment {
|
||||
val tabEntity = mTabEntityList.safelyGetInRelease(position)
|
||||
return if (position == 0) {
|
||||
GameCollectionPlayerCreationFragment().with(
|
||||
bundleOf(
|
||||
EntranceConsts.KEY_ENTRANCE to mEntrance,
|
||||
EntranceConsts.KEY_PATH to "游戏单热榜"
|
||||
)
|
||||
)
|
||||
} else {
|
||||
GameCollectionHotListFragment().with(
|
||||
bundleOf(
|
||||
EntranceConsts.KEY_TAB to tabEntity,
|
||||
EntranceConsts.KEY_ENTRANCE to mEntrance,
|
||||
EntranceConsts.KEY_PATH to "游戏单热榜"
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
mBinding.viewPager.adapter = mAdapter
|
||||
mBinding.viewPager.isUserInputEnabled = false
|
||||
mBinding.viewPager.offscreenPageLimit = 3
|
||||
}
|
||||
|
||||
override fun onDarkModeChanged() {
|
||||
super.onDarkModeChanged()
|
||||
DisplayUtils.setLightStatusBar(requireActivity(), !mIsDarkModeOn && mIsCollapsed)
|
||||
for (i in 0 until mBinding.tabLayout.tabCount) {
|
||||
val tab = mBinding.tabLayout.getTabAt(i)
|
||||
if (tab != null) {
|
||||
updateTabStyle(tab, tab.isSelected)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val PLAYER_CREATION_TAB_NAME = "#玩家创作榜"
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,46 @@
|
||||
package com.gh.gamecenter.gamecollection.hotlist
|
||||
|
||||
import android.app.Application
|
||||
import androidx.lifecycle.AndroidViewModel
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import com.gh.gamecenter.common.entity.LinkEntity
|
||||
import com.gh.gamecenter.common.retrofit.Response
|
||||
import com.gh.gamecenter.common.utils.observableToMain
|
||||
import com.gh.gamecenter.entity.GameCollectionHotListTab
|
||||
import com.gh.gamecenter.entity.GameCollectionPlayerCreationEntity
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager
|
||||
import retrofit2.HttpException
|
||||
|
||||
class GameCollectionHotListWrapperViewModel(application: Application) : AndroidViewModel(application) {
|
||||
private val mApi = RetrofitManager.getInstance().api
|
||||
|
||||
val hotListTabListLiveData = MutableLiveData<List<GameCollectionHotListTab>?>()
|
||||
|
||||
init {
|
||||
getGameCollectionHotListTab()
|
||||
}
|
||||
|
||||
fun getGameCollectionHotListTab() {
|
||||
mApi.gameCollectionHotListTab
|
||||
.compose(observableToMain())
|
||||
.subscribe(object : Response<List<GameCollectionHotListTab>>() {
|
||||
override fun onResponse(response: List<GameCollectionHotListTab>?) {
|
||||
super.onResponse(response)
|
||||
response?.let {
|
||||
val hotListTabList = ArrayList<GameCollectionHotListTab>()
|
||||
it.forEachIndexed { index, entity ->
|
||||
hotListTabList.add(entity.apply {
|
||||
position = index + 1
|
||||
})
|
||||
}
|
||||
hotListTabListLiveData.postValue(hotListTabList)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onFailure(e: HttpException?) {
|
||||
super.onFailure(e)
|
||||
hotListTabListLiveData.postValue(null)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,210 @@
|
||||
package com.gh.gamecenter.gamecollection.hotlist
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.Typeface
|
||||
import android.view.ViewGroup
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.gh.common.util.DialogUtils
|
||||
import com.gh.common.util.DirectUtils
|
||||
import com.gh.common.util.NewFlatLogUtils
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.base.BaseRecyclerViewHolder
|
||||
import com.gh.gamecenter.common.baselist.ListAdapter
|
||||
import com.gh.gamecenter.common.constant.ItemViewType
|
||||
import com.gh.gamecenter.common.entity.LinkEntity
|
||||
import com.gh.gamecenter.common.utils.*
|
||||
import com.gh.gamecenter.common.viewholder.FooterViewHolder
|
||||
import com.gh.gamecenter.core.utils.DisplayUtils
|
||||
import com.gh.gamecenter.databinding.ItemGameCollectionPlayerCreationBinding
|
||||
import com.gh.gamecenter.databinding.ItemGameCollectionPlayerCreationHeaderBinding
|
||||
import com.gh.gamecenter.entity.PlayerCreationItem
|
||||
import com.gh.gamecenter.feature.exposure.ExposureEvent
|
||||
import com.gh.gamecenter.feature.exposure.ExposureSource
|
||||
import com.gh.gamecenter.login.user.UserManager
|
||||
|
||||
class GameCollectionPlayerCreationAdapter(
|
||||
context: Context,
|
||||
private val mViewModel: GameCollectionPlayerCreationViewModel,
|
||||
private val mEntrance: String,
|
||||
private val mPath: String,
|
||||
) : ListAdapter<PlayerCreationItem>(context) {
|
||||
|
||||
private var mTipLinkEntity: LinkEntity? = null
|
||||
|
||||
fun setTipData(linkEntity: LinkEntity) {
|
||||
mTipLinkEntity = linkEntity
|
||||
notifyItemChanged(0)
|
||||
}
|
||||
|
||||
override fun getItemViewType(position: Int): Int {
|
||||
return if (position == 0) ItemViewType.ITEM_HEADER else if (position == itemCount - 1) ItemViewType.ITEM_FOOTER else ItemViewType.ITEM_BODY
|
||||
}
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
|
||||
return when (viewType) {
|
||||
ItemViewType.ITEM_FOOTER ->
|
||||
FooterViewHolder(
|
||||
mLayoutInflater.inflate(
|
||||
R.layout.refresh_footerview,
|
||||
parent,
|
||||
false
|
||||
)
|
||||
)
|
||||
|
||||
ItemViewType.ITEM_HEADER -> GameCollectionPlayerCreationHeaderItemViewHolder(parent.toBinding())
|
||||
|
||||
else -> GameCollectionPlayerCreationItemViewHolder(parent.toBinding())
|
||||
}
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
|
||||
if (holder is GameCollectionPlayerCreationHeaderItemViewHolder) {
|
||||
mTipLinkEntity?.let { link ->
|
||||
holder.binding.run {
|
||||
tipsTv.text = link.text
|
||||
tipsTv.setTextColor(R.color.text_subtitleDesc.toColor(mContext))
|
||||
tipsIv.setOnClickListener {
|
||||
DirectUtils.directToLinkPage(mContext, link, "", "")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (holder is GameCollectionPlayerCreationItemViewHolder) {
|
||||
val realPosition = position - 1
|
||||
val entity = mEntityList[realPosition]
|
||||
holder.binding.run {
|
||||
root.setCardBackgroundColor(R.color.background_white.toColor(mContext))
|
||||
gameCollectionCv.setCardBackgroundColor(R.color.background_space.toColor(mContext))
|
||||
rankTv.setTextColor(R.color.text_subtitleDesc.toColor(mContext))
|
||||
userNameTv.setTextColor(R.color.text_title.toColor(mContext))
|
||||
userFansAndVoteCountTv.setTextColor(R.color.text_subtitleDesc.toColor(mContext))
|
||||
gameCollectionCountTv.setTextColor(R.color.text_subtitle.toColor(mContext))
|
||||
gameCollectionTitleTv.setTextColor(R.color.text_subtitle.toColor(mContext))
|
||||
|
||||
rankIv.goneIf(realPosition > 2) {
|
||||
rankIv.setImageResource(
|
||||
when (realPosition) {
|
||||
0 -> R.drawable.icon_leaderboard_1
|
||||
1 -> R.drawable.icon_leaderboard_2
|
||||
else -> R.drawable.icon_leaderboard_3
|
||||
}
|
||||
)
|
||||
}
|
||||
rankTv.goneIf(realPosition < 3) {
|
||||
rankTv.typeface = Typeface.createFromAsset(mContext.assets, "fonts/d_din_bold_only_number.ttf")
|
||||
rankTv.text = "${realPosition + 1}"
|
||||
}
|
||||
userNameTv.text = entity.user?.name
|
||||
userFansAndVoteCountTv.text = "${entity.user?.count?.fans}粉丝 ${entity.user?.count?.vote}赞同"
|
||||
userAvatar.display(entity.user?.iconBorder?.url, entity.user?.icon)
|
||||
followTv.goneIf(entity.user?.id == UserManager.getInstance().userId)
|
||||
badgeIv.goneIf(entity?.user?.badge == null) {
|
||||
ImageUtils.display(badgeIv, entity.user?.badge?.icon)
|
||||
}
|
||||
badgeIv.setOnClickListener {
|
||||
DialogUtils.showViewBadgeDialog(mContext, entity?.user?.badge) {
|
||||
DirectUtils.directToBadgeWall(
|
||||
mContext,
|
||||
entity?.user?.id,
|
||||
entity?.user?.name,
|
||||
entity?.user?.icon
|
||||
)
|
||||
}
|
||||
}
|
||||
entity?.user?.me?.let {
|
||||
followTv.text = if (it.isFollower) "已关注" else "关注"
|
||||
followTv.setTextColor(
|
||||
if (it.isFollower) R.color.text_subtitleDesc.toColor(mContext) else R.color.theme_font.toColor(
|
||||
mContext
|
||||
)
|
||||
)
|
||||
followTv.background =
|
||||
if (it.isFollower) R.drawable.button_round_gray_light.toDrawable(mContext) else R.drawable.button_round_primary_light.toDrawable(
|
||||
mContext
|
||||
)
|
||||
followTv.setOnClickListener { view ->
|
||||
mContext.ifLogin("板块成员") {
|
||||
if (entity.user.id == UserManager.getInstance().userId) return@ifLogin
|
||||
debounceActionWithInterval(view.id) {
|
||||
NewFlatLogUtils.logGameCollectionHotListClick(
|
||||
GameCollectionHotListWrapperFragment.PLAYER_CREATION_TAB_NAME,
|
||||
"",
|
||||
"",
|
||||
"关注"
|
||||
)
|
||||
if (it.isFollower) {
|
||||
mViewModel.followingCommand(entity.user.id, false) {
|
||||
it.isFollower = false
|
||||
notifyItemChanged(position)
|
||||
}
|
||||
} else {
|
||||
mViewModel.followingCommand(entity.user.id, true) {
|
||||
it.isFollower = true
|
||||
notifyItemChanged(position)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
gameCollectionCountTv.text = "${entity.user?.count?.gameList}"
|
||||
gameCollectionTitleTv.text = entity?.gameList?.title
|
||||
|
||||
listOf(
|
||||
userAvatar,
|
||||
userNameTv,
|
||||
userFansAndVoteCountTv,
|
||||
gameCollectionCountTv,
|
||||
gameCollectionIv
|
||||
).forEach {
|
||||
it.setOnClickListener {
|
||||
NewFlatLogUtils.logGameCollectionHotListClick(
|
||||
GameCollectionHotListWrapperFragment.PLAYER_CREATION_TAB_NAME,
|
||||
"",
|
||||
"",
|
||||
"个人主页"
|
||||
)
|
||||
DirectUtils.directToHomeActivity(mContext, entity?.user?.id, 0, mEntrance, mPath)
|
||||
}
|
||||
}
|
||||
listOf(gameCollectionTitleTv, moreIv).forEach {
|
||||
it.setOnClickListener {
|
||||
NewFlatLogUtils.logGameCollectionHotListClick(
|
||||
GameCollectionHotListWrapperFragment.PLAYER_CREATION_TAB_NAME,
|
||||
"",
|
||||
"",
|
||||
"游戏单"
|
||||
)
|
||||
DirectUtils.directToGameCollectionDetail(
|
||||
mContext,
|
||||
entity?.gameList?.id ?: "",
|
||||
mEntrance,
|
||||
mPath,
|
||||
ExposureEvent.createEvent(null, listOf(ExposureSource("游戏单热榜-玩家创作榜")))
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (holder is FooterViewHolder) {
|
||||
holder.initItemPadding()
|
||||
holder.initFooterViewHolder(mViewModel, mIsLoading, mIsNetworkError, mIsOver)
|
||||
holder.hint.setTextColor(ContextCompat.getColor(mContext, R.color.text_B3B3B3))
|
||||
val lp = holder.itemView.layoutParams as RecyclerView.LayoutParams
|
||||
lp.height = DisplayUtils.dip2px(48F)
|
||||
lp.width = ViewGroup.LayoutParams.MATCH_PARENT
|
||||
holder.itemView.layoutParams = lp
|
||||
}
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int = if (mEntityList.isNotEmpty()) mEntityList.size + 2 else 0
|
||||
|
||||
class GameCollectionPlayerCreationItemViewHolder(val binding: ItemGameCollectionPlayerCreationBinding) :
|
||||
BaseRecyclerViewHolder<Any>(binding.root)
|
||||
|
||||
class GameCollectionPlayerCreationHeaderItemViewHolder(val binding: ItemGameCollectionPlayerCreationHeaderBinding) :
|
||||
BaseRecyclerViewHolder<Any>(binding.root)
|
||||
}
|
||||
@ -0,0 +1,71 @@
|
||||
package com.gh.gamecenter.gamecollection.hotlist
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.gh.common.util.NewFlatLogUtils
|
||||
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.viewModelProvider
|
||||
import com.gh.gamecenter.common.view.VerticalItemDecoration
|
||||
import com.gh.gamecenter.core.utils.TimeElapsedHelper
|
||||
import com.gh.gamecenter.entity.GamesCollectionEntity
|
||||
|
||||
class GameCollectionPlayerCreationFragment :
|
||||
ListFragment<GamesCollectionEntity, GameCollectionPlayerCreationViewModel>() {
|
||||
private val mElapsedHelper by lazy { TimeElapsedHelper() }
|
||||
private lateinit var mViewModel: GameCollectionPlayerCreationViewModel
|
||||
private var mAdapter: GameCollectionPlayerCreationAdapter? = null
|
||||
|
||||
override fun provideListAdapter(): GameCollectionPlayerCreationAdapter {
|
||||
if (mAdapter == null) {
|
||||
mAdapter =
|
||||
GameCollectionPlayerCreationAdapter(
|
||||
requireContext(),
|
||||
provideListViewModel(),
|
||||
mEntrance,
|
||||
arguments?.getString(EntranceConsts.KEY_PATH) ?: ""
|
||||
)
|
||||
}
|
||||
return mAdapter as GameCollectionPlayerCreationAdapter
|
||||
}
|
||||
|
||||
override fun provideListViewModel(): GameCollectionPlayerCreationViewModel {
|
||||
mViewModel = viewModelProvider()
|
||||
return mViewModel
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
mViewModel.topLinkLiveData.observeNonNull(this) {
|
||||
mAdapter?.setTipData(it)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
mElapsedHelper.pauseCounting()
|
||||
NewFlatLogUtils.logGameCollectionHotListTabView(
|
||||
mElapsedHelper.elapsedTime,
|
||||
GameCollectionHotListWrapperFragment.PLAYER_CREATION_TAB_NAME,
|
||||
"",
|
||||
""
|
||||
)
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
mElapsedHelper.resetCounting()
|
||||
mElapsedHelper.resumeCounting()
|
||||
}
|
||||
|
||||
override fun getItemDecoration(): RecyclerView.ItemDecoration {
|
||||
mItemDecoration = VerticalItemDecoration(context, 8F, false)
|
||||
return mItemDecoration
|
||||
}
|
||||
|
||||
fun setListRefreshEnable(enable: Boolean) {
|
||||
mListRefresh?.isEnabled = enable
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,95 @@
|
||||
package com.gh.gamecenter.gamecollection.hotlist
|
||||
|
||||
import android.app.Application
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.baselist.ListViewModel
|
||||
import com.gh.gamecenter.common.baselist.LoadStatus
|
||||
import com.gh.gamecenter.common.entity.LinkEntity
|
||||
import com.gh.gamecenter.common.retrofit.Response
|
||||
import com.gh.gamecenter.common.utils.observableToMain
|
||||
import com.gh.gamecenter.entity.AmwayCommentEntity
|
||||
import com.gh.gamecenter.entity.GameCollectionPlayerCreationEntity
|
||||
import com.gh.gamecenter.entity.PlayerCreationItem
|
||||
import com.gh.gamecenter.eventbus.EBUserFollow
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager
|
||||
import com.lightgame.utils.Utils
|
||||
import io.reactivex.Observable
|
||||
import io.reactivex.Single
|
||||
import io.reactivex.SingleEmitter
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
import okhttp3.ResponseBody
|
||||
import org.greenrobot.eventbus.EventBus
|
||||
import retrofit2.HttpException
|
||||
|
||||
class GameCollectionPlayerCreationViewModel(application: Application) :
|
||||
ListViewModel<PlayerCreationItem, PlayerCreationItem>(application) {
|
||||
private val mApi = RetrofitManager.getInstance().api
|
||||
val topLinkLiveData = MutableLiveData<LinkEntity>()
|
||||
|
||||
override fun provideDataObservable(page: Int): Observable<MutableList<PlayerCreationItem>>? = null
|
||||
|
||||
override fun provideDataSingle(page: Int): Single<MutableList<PlayerCreationItem>> {
|
||||
return Single.create {
|
||||
if (page == 1) {
|
||||
getGameCollectionPlayerCreation(it)
|
||||
} else {
|
||||
it.onSuccess(arrayListOf())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun getGameCollectionPlayerCreation(emitter: SingleEmitter<MutableList<PlayerCreationItem>>) {
|
||||
mApi.gameCollectionPlayerCreation
|
||||
.compose(observableToMain())
|
||||
.subscribe(object : Response<GameCollectionPlayerCreationEntity>() {
|
||||
override fun onResponse(response: GameCollectionPlayerCreationEntity?) {
|
||||
super.onResponse(response)
|
||||
response?.run {
|
||||
tipLink?.let { topLinkLiveData.postValue(it) }
|
||||
data?.let { emitter.onSuccess(ArrayList(it)) }
|
||||
}
|
||||
}
|
||||
|
||||
override fun onFailure(e: HttpException?) {
|
||||
super.onFailure(e)
|
||||
mLoadStatusLiveData.postValue(LoadStatus.INIT_FAILED)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
override fun mergeResultLiveData() {
|
||||
mResultLiveData.addSource(mListLiveData) {
|
||||
mResultLiveData.postValue(it)
|
||||
}
|
||||
}
|
||||
|
||||
fun followingCommand(userId: String, isFollow: Boolean, onSuccess: () -> Unit) {
|
||||
val observable = if (isFollow) {
|
||||
mApi.postFollowing(userId)
|
||||
} else {
|
||||
mApi.deleteFollowing(userId)
|
||||
}
|
||||
observable
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(object : Response<ResponseBody>() {
|
||||
override fun onResponse(response: ResponseBody?) {
|
||||
super.onResponse(response)
|
||||
onSuccess.invoke()
|
||||
if (isFollow) {
|
||||
Utils.toast(getApplication(), R.string.concern_success)
|
||||
} else {
|
||||
Utils.toast(getApplication(), R.string.concern_cancel)
|
||||
}
|
||||
EventBus.getDefault().post(EBUserFollow(userId, isFollow))
|
||||
}
|
||||
|
||||
override fun onFailure(e: HttpException?) {
|
||||
super.onFailure(e)
|
||||
Utils.toast(getApplication(), R.string.loading_failed_hint)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -22,7 +22,7 @@ class GameCollectionAmwayViewHolder(var binding: GameCollectionSquareAmwayItemBi
|
||||
private val mLooperHandle = LooperHandle(this)
|
||||
private val mSlideLooperKey = 333
|
||||
|
||||
fun bindAmway(amwayList: List<AmwayCommentEntity>) {
|
||||
fun bindAmway(amwayList: List<AmwayCommentEntity>, viewModel: GameCollectionSquareViewModel) {
|
||||
mAdapter.setAmwayList(amwayList)
|
||||
binding.amwayVp.run {
|
||||
if (adapter is GameCollectionAmwayAdapter) return
|
||||
@ -32,7 +32,7 @@ class GameCollectionAmwayViewHolder(var binding: GameCollectionSquareAmwayItemBi
|
||||
startAutoPlay()
|
||||
}
|
||||
binding.root.setOnClickListener {
|
||||
NewLogUtils.logClickGameCollectionAmway()
|
||||
NewLogUtils.logClickGameCollectionAmway(GameCollectionSquareViewModel.getOrderChineseByName(viewModel.view))
|
||||
DirectUtils.directToAmway(binding.root.context)
|
||||
NewLogUtils.logEnterGameCollectionAmway()
|
||||
}
|
||||
|
||||
@ -21,7 +21,7 @@ import com.lightgame.adapter.BaseRecyclerAdapter
|
||||
|
||||
class GameCollectionBannerAdapter(
|
||||
context: Context,
|
||||
private val isHome: Boolean = false,
|
||||
private val mViewModel: GameCollectionSquareViewModel,
|
||||
var mBannerList: List<CarouselEntity> = emptyList(),
|
||||
private var mAmwayListItem: List<AmwayCommentEntity>? = null,
|
||||
private val mEntrance: String = "",
|
||||
@ -29,15 +29,15 @@ class GameCollectionBannerAdapter(
|
||||
) :
|
||||
BaseRecyclerAdapter<RecyclerView.ViewHolder>(context) {
|
||||
|
||||
fun submitList(updateList: List<CarouselEntity>?, amwayList: List<AmwayCommentEntity>? = null) {
|
||||
mBannerList = if (updateList.isNullOrEmpty()) emptyList() else ArrayList(updateList)
|
||||
mAmwayListItem = if (amwayList.isNullOrEmpty()) emptyList() else ArrayList(amwayList)
|
||||
fun submitList(updateList: List<CarouselEntity>? = null, amwayList: List<AmwayCommentEntity>? = null) {
|
||||
updateList?.let { mBannerList = ArrayList(it) }
|
||||
amwayList?.let { mAmwayListItem = ArrayList(it) }
|
||||
AppExecutor.uiExecutor.execute {
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
}
|
||||
|
||||
private fun shouldShowAmway(position: Int) = isHome && getActualPosition(position) == getActualSize() - 1
|
||||
private fun shouldShowAmway(position: Int) = getActualPosition(position) == getActualSize() - 1
|
||||
|
||||
override fun getItemViewType(position: Int) = if (shouldShowAmway(position)) ITEM_AMWAY else ITEM_BANNER
|
||||
|
||||
@ -53,7 +53,7 @@ class GameCollectionBannerAdapter(
|
||||
holder.bindBanner(entity, getActualPosition(position))
|
||||
}
|
||||
} else if (holder is GameCollectionAmwayViewHolder) {
|
||||
mAmwayListItem?.let { holder.bindAmway(it) }
|
||||
mAmwayListItem?.let { holder.bindAmway(it, mViewModel) }
|
||||
}
|
||||
}
|
||||
|
||||
@ -68,7 +68,7 @@ class GameCollectionBannerAdapter(
|
||||
return actualPosition
|
||||
}
|
||||
|
||||
fun getActualSize() = if (isHome) mBannerList.size + 1 else mBannerList.size
|
||||
fun getActualSize() = mBannerList.size + 1
|
||||
|
||||
fun getActualFirstPositionInCenter(): Int {
|
||||
var index = itemCount / 2
|
||||
|
||||
@ -9,7 +9,13 @@ data class GameCollectionListItemData(
|
||||
var gameCollectionItem: GamesCollectionEntity? = null,
|
||||
var amwayListItem: List<AmwayCommentEntity>? = null,
|
||||
var carouselListItem: List<CarouselEntity>? = null,
|
||||
var hotListTabName: String = "",
|
||||
var gameStartPosition: Int = 0,
|
||||
var outerSequence: Int = -1
|
||||
var outerSequence: Int = -1,
|
||||
var isHeaderItem: Boolean = false,
|
||||
var isFilterItem: Boolean = false,
|
||||
var isGameCollectionItem: Boolean = false,
|
||||
var collectionId: String = "",
|
||||
var collectionName: String = ""
|
||||
) :
|
||||
LegacyHomeItemData()
|
||||
@ -16,78 +16,130 @@ import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.PagerSnapHelper
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import androidx.viewpager2.widget.ViewPager2
|
||||
import com.gh.gamecenter.common.base.activity.BaseActivity
|
||||
import com.gh.gamecenter.common.constant.ItemViewType
|
||||
import com.gh.gamecenter.feature.exposure.ExposureEvent
|
||||
import com.gh.gamecenter.feature.exposure.ExposureSource
|
||||
import com.gh.common.exposure.IExposable
|
||||
import com.gh.common.util.*
|
||||
import com.gh.gamecenter.common.utils.ImageUtils.display
|
||||
import com.gh.common.exposure.*
|
||||
import com.gh.common.util.*
|
||||
import com.gh.common.util.NewLogUtils
|
||||
import com.gh.gamecenter.GameDetailActivity
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.viewholder.FooterViewHolder
|
||||
import com.gh.gamecenter.common.base.activity.BaseActivity
|
||||
import com.gh.gamecenter.common.baselist.ListAdapter
|
||||
import com.gh.gamecenter.common.baselist.LoadStatus
|
||||
import com.gh.gamecenter.common.constant.ItemViewType
|
||||
import com.gh.gamecenter.common.entity.ExposureEntity
|
||||
import com.gh.gamecenter.common.utils.*
|
||||
import com.gh.gamecenter.common.utils.ImageUtils.display
|
||||
import com.gh.gamecenter.common.view.ScrollEventListener
|
||||
import com.gh.gamecenter.common.viewholder.FooterViewHolder
|
||||
import com.gh.gamecenter.core.utils.DisplayUtils
|
||||
import com.gh.gamecenter.databinding.GameCollectionSquareItemBinding
|
||||
import com.gh.gamecenter.databinding.ItemGameCollectionBannerBinding
|
||||
import com.gh.gamecenter.databinding.ItemGameCollectionFilterBinding
|
||||
import com.gh.gamecenter.databinding.ItemGameCollectionHeaderBinding
|
||||
import com.gh.gamecenter.entity.AmwayCommentEntity
|
||||
import com.gh.gamecenter.entity.CarouselEntity
|
||||
import com.gh.gamecenter.entity.GamesCollectionEntity
|
||||
import com.gh.gamecenter.feature.exposure.ExposureEvent
|
||||
import com.gh.gamecenter.feature.exposure.ExposureSource
|
||||
import com.gh.gamecenter.feature.exposure.ExposureType
|
||||
import com.gh.gamecenter.gamecollection.detail.GameCollectionDetailActivity
|
||||
import com.gh.gamecenter.gamecollection.tag.GameCollectionTagSelectActivity
|
||||
import com.lightgame.view.NoScrollableViewPager
|
||||
import java.lang.ref.WeakReference
|
||||
|
||||
class GameCollectionSquareAdapter(
|
||||
context: Context,
|
||||
private val isHome: Boolean = false,
|
||||
private val mFragment: GameCollectionSquareFragment,
|
||||
private val mViewModel: GameCollectionSquareViewModel,
|
||||
private var mBasicExposureSource: List<ExposureSource>,
|
||||
private val mOuterSequence: Int = -1
|
||||
private val mOuterSequence: Int = -1,
|
||||
private val mRefreshCallback: () -> Unit
|
||||
) :
|
||||
ListAdapter<GameCollectionListItemData>(context), IExposable {
|
||||
private val mPosterWidth = DisplayUtils.getScreenWidth() - 32F.dip2px()
|
||||
|
||||
override fun setListData(updateData: MutableList<GameCollectionListItemData>?) {
|
||||
if (updateData == null) {
|
||||
mEntityList = ArrayList()
|
||||
notifyDataSetChanged()
|
||||
return
|
||||
}
|
||||
|
||||
// 避免首页游戏单广场刷新列表后出现异常跳转位置
|
||||
if (isHome && mEntityList.size == 2 && updateData.size > mEntityList.size) {
|
||||
mEntityList = ArrayList(updateData)
|
||||
notifyItemRangeInserted(2, updateData.size - 1)
|
||||
return
|
||||
}
|
||||
|
||||
// 避免手动刷新列表时出现异常动画
|
||||
if (mEntityList != null && mEntityList.size > updateData.size) {
|
||||
mEntityList = ArrayList(updateData)
|
||||
notifyDataSetChanged()
|
||||
return
|
||||
}
|
||||
|
||||
calculateDiff(updateData)
|
||||
}
|
||||
|
||||
fun setAmwayList(amwayList: List<AmwayCommentEntity>) {
|
||||
if (isHome && mEntityList.isNotEmpty() && mEntityList[0].amwayListItem == null) {
|
||||
if (isHome && mEntityList.isNotEmpty() && mEntityList[0].amwayListItem.isNullOrEmpty()) {
|
||||
mEntityList[0].amwayListItem = amwayList
|
||||
notifyItemChanged(0)
|
||||
}
|
||||
}
|
||||
|
||||
fun setBannerList(bannerList: List<CarouselEntity>) {
|
||||
if (isHome && mEntityList.isNotEmpty() && mEntityList[0].carouselListItem == null) {
|
||||
if (isHome && mEntityList.isNotEmpty() && mEntityList[0].carouselListItem.isNullOrEmpty()) {
|
||||
mEntityList[0].carouselListItem = bannerList
|
||||
notifyItemChanged(0)
|
||||
}
|
||||
}
|
||||
|
||||
override fun areItemsTheSame(oldItem: GameCollectionListItemData?, newItem: GameCollectionListItemData?) =
|
||||
oldItem == newItem
|
||||
fun setHotListTabName(tabName: String) {
|
||||
if (isHome && mEntityList.isNotEmpty() && mEntityList[0].hotListTabName.isEmpty()) {
|
||||
mEntityList[0].hotListTabName = tabName
|
||||
notifyItemChanged(0)
|
||||
}
|
||||
}
|
||||
|
||||
override fun areItemsTheSame(oldItem: GameCollectionListItemData?, newItem: GameCollectionListItemData?): Boolean {
|
||||
if (oldItem?.isHeaderItem == newItem?.isHeaderItem) return true
|
||||
if (oldItem?.isFilterItem == newItem?.isFilterItem) return true
|
||||
if (oldItem?.isGameCollectionItem == newItem?.isGameCollectionItem) return true
|
||||
return false
|
||||
}
|
||||
|
||||
override fun areContentsTheSame(
|
||||
oldItem: GameCollectionListItemData?,
|
||||
newItem: GameCollectionListItemData?
|
||||
): Boolean {
|
||||
if (oldItem?.isHeaderItem == newItem?.isHeaderItem) {
|
||||
return (oldItem?.carouselListItem == newItem?.carouselListItem) && (oldItem?.amwayListItem == newItem?.amwayListItem)
|
||||
}
|
||||
if (oldItem?.isFilterItem == newItem?.isFilterItem) return true
|
||||
if (oldItem?.isGameCollectionItem == newItem?.isGameCollectionItem) {
|
||||
return oldItem?.gameCollectionItem == newItem?.gameCollectionItem
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
override fun areContentsTheSame(oldItem: GameCollectionListItemData?, newItem: GameCollectionListItemData?) =
|
||||
oldItem == newItem
|
||||
|
||||
override fun getItemViewType(position: Int): Int {
|
||||
return if (position == itemCount - 1) {
|
||||
ItemViewType.ITEM_FOOTER
|
||||
if (isHome) {
|
||||
if (position == 0) return ItemViewType.ITEM_HEADER
|
||||
if (position == 1) return ITEM_FILTER
|
||||
if (position == itemCount - 1) return ItemViewType.ITEM_FOOTER
|
||||
return ItemViewType.ITEM_BODY
|
||||
} else {
|
||||
when {
|
||||
isHome && position == 0 -> ItemViewType.ITEM_HEADER
|
||||
|
||||
else -> ItemViewType.ITEM_BODY
|
||||
}
|
||||
if (position == itemCount - 1) return ItemViewType.ITEM_FOOTER
|
||||
return ItemViewType.ITEM_BODY
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
|
||||
return when (viewType) {
|
||||
ItemViewType.ITEM_HEADER -> GameCollectionBannerItemViewHolder(parent.toBinding())
|
||||
ItemViewType.ITEM_HEADER -> GameCollectionHeaderItemViewHolder(parent.toBinding())
|
||||
ITEM_FILTER -> GameCollectionFilterItemViewHolder(parent.toBinding())
|
||||
ItemViewType.ITEM_BODY -> GameCollectionSquareItemViewHolder(parent.toBinding())
|
||||
ItemViewType.ITEM_FOOTER -> FooterViewHolder(
|
||||
mLayoutInflater.inflate(
|
||||
@ -96,42 +148,52 @@ class GameCollectionSquareAdapter(
|
||||
false
|
||||
)
|
||||
)
|
||||
|
||||
else -> GameCollectionSquareItemViewHolder(parent.toBinding())
|
||||
}
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
|
||||
when (holder) {
|
||||
is GameCollectionBannerItemViewHolder -> {
|
||||
is GameCollectionHeaderItemViewHolder -> {
|
||||
val itemData = mEntityList[position]
|
||||
holder.bindBanner(itemData, mBasicExposureSource)
|
||||
holder.bindHeader(itemData, mBasicExposureSource, mViewModel)
|
||||
}
|
||||
|
||||
is GameCollectionFilterItemViewHolder -> holder.bindFilter(mFragment, mViewModel, mRefreshCallback)
|
||||
is GameCollectionSquareItemViewHolder -> {
|
||||
val itemData = mEntityList[position]
|
||||
val filterTagName = mViewModel.selectedTagName
|
||||
val exposureEventList = arrayListOf<ExposureEvent>()
|
||||
val exposureSource = listOf(
|
||||
ExposureSource(
|
||||
"游戏单",
|
||||
"${itemData.gameCollectionItem?.title} + ${itemData.gameCollectionItem?.id} + ${
|
||||
GameCollectionSquareViewModel.getOrderChineseByName(
|
||||
mViewModel.view
|
||||
)
|
||||
} + $filterTagName"
|
||||
)
|
||||
)
|
||||
|
||||
itemData.gameCollectionItem?.games?.take(3)?.forEachIndexed { index, game ->
|
||||
exposureEventList.add(
|
||||
ExposureEvent.createEventWithSourceConcat(
|
||||
game.toGameEntity().apply {
|
||||
isAdData = itemData.gameCollectionItem?.adIconActive ?: false
|
||||
outerSequence = mOuterSequence;
|
||||
outerSequence = mOuterSequence
|
||||
sequence = itemData.gameStartPosition + index + 1
|
||||
},
|
||||
mBasicExposureSource,
|
||||
listOf(
|
||||
ExposureSource(
|
||||
"游戏单",
|
||||
if (isHome) "${itemData.gameCollectionItem?.title} + ${itemData.gameCollectionItem?.id}" else "${itemData.gameCollectionItem?.title} + ${itemData.gameCollectionItem?.id} + $filterTagName"
|
||||
)
|
||||
)
|
||||
exposureSource
|
||||
)
|
||||
)
|
||||
}
|
||||
itemData.exposureEventList = exposureEventList
|
||||
itemData.gameCollectionItem?.let {
|
||||
holder.bindGameCollection(mViewModel, it, itemData, isHome)
|
||||
holder.bindGameCollection(mViewModel, it, itemData, isHome, ArrayList(mBasicExposureSource).apply {
|
||||
addAll(exposureSource)
|
||||
})
|
||||
}
|
||||
}
|
||||
is FooterViewHolder -> {
|
||||
@ -146,9 +208,10 @@ class GameCollectionSquareAdapter(
|
||||
}
|
||||
}
|
||||
|
||||
override fun getItemCount() = if (mEntityList.isNullOrEmpty()) 0 else mEntityList.size + 1
|
||||
override fun getItemCount() =
|
||||
if (mEntityList.isNullOrEmpty()) 0 else if (isHome && mEntityList.size == 2) mEntityList.size else mEntityList.size + 1
|
||||
|
||||
class GameCollectionBannerItemViewHolder(val binding: ItemGameCollectionBannerBinding) :
|
||||
class GameCollectionHeaderItemViewHolder(val binding: ItemGameCollectionHeaderBinding) :
|
||||
RecyclerView.ViewHolder(binding.root) {
|
||||
private lateinit var mBannerAdapter: GameCollectionBannerAdapter
|
||||
private lateinit var mSnapHelper: PagerSnapHelper
|
||||
@ -156,18 +219,23 @@ class GameCollectionSquareAdapter(
|
||||
private val mLooperHandle = LooperHandle(this)
|
||||
private val mSlideLooperKey = 111
|
||||
|
||||
fun bindBanner(itemData: GameCollectionListItemData, mBasicExposureSource: List<ExposureSource>) {
|
||||
fun bindHeader(
|
||||
itemData: GameCollectionListItemData,
|
||||
mBasicExposureSource: List<ExposureSource>,
|
||||
viewModel: GameCollectionSquareViewModel
|
||||
) {
|
||||
val context = binding.root.context
|
||||
val bannerList = itemData.carouselListItem ?: emptyList()
|
||||
val amwayListItem = itemData.amwayListItem
|
||||
|
||||
if (::mBannerAdapter.isInitialized) {
|
||||
mBannerAdapter.submitList(bannerList, amwayListItem)
|
||||
binding.tabNameTv.text = itemData.hotListTabName
|
||||
itemData.exposureEventList = getExposureEventList(bannerList, mBasicExposureSource)
|
||||
|
||||
if (mBannerAdapter.mBannerList.size != bannerList.size) {
|
||||
binding.bannerIndicator.run {
|
||||
mPageSize = mBannerAdapter.getActualSize()
|
||||
pageSize = mBannerAdapter.getActualSize()
|
||||
notifyDataChanged()
|
||||
}
|
||||
if (mBannerAdapter.getActualSize() > 1) {
|
||||
@ -181,14 +249,14 @@ class GameCollectionSquareAdapter(
|
||||
mBannerLayoutManager = LinearLayoutManager(context, RecyclerView.HORIZONTAL, false)
|
||||
mBannerAdapter = GameCollectionBannerAdapter(
|
||||
context,
|
||||
true,
|
||||
viewModel,
|
||||
bannerList,
|
||||
amwayListItem,
|
||||
"顶部tab-游戏单广场",
|
||||
mBasicExposureSource
|
||||
)
|
||||
binding.bannerIndicator.run {
|
||||
mPageSize = mBannerAdapter.getActualSize()
|
||||
pageSize = mBannerAdapter.getActualSize()
|
||||
notifyDataChanged()
|
||||
}
|
||||
binding.bannerRv.run {
|
||||
@ -232,6 +300,10 @@ class GameCollectionSquareAdapter(
|
||||
}
|
||||
startAutoPlay()
|
||||
}
|
||||
binding.tabNameTv.text = itemData.hotListTabName
|
||||
binding.hotListCv.setOnClickListener {
|
||||
DirectUtils.directToGameCollectionHotList(context, "首页tab栏")
|
||||
}
|
||||
itemData.exposureEventList = getExposureEventList(bannerList, mBasicExposureSource)
|
||||
}
|
||||
|
||||
@ -273,8 +345,8 @@ class GameCollectionSquareAdapter(
|
||||
mLooperHandle.removeMessages(mSlideLooperKey)
|
||||
}
|
||||
|
||||
class LooperHandle(viewHolder: GameCollectionBannerItemViewHolder) : Handler(Looper.getMainLooper()) {
|
||||
private val mWeakReference: WeakReference<GameCollectionBannerItemViewHolder> = WeakReference(viewHolder)
|
||||
class LooperHandle(viewHolder: GameCollectionHeaderItemViewHolder) : Handler(Looper.getMainLooper()) {
|
||||
private val mWeakReference: WeakReference<GameCollectionHeaderItemViewHolder> = WeakReference(viewHolder)
|
||||
|
||||
override fun handleMessage(msg: Message) {
|
||||
super.handleMessage(msg)
|
||||
@ -287,17 +359,70 @@ class GameCollectionSquareAdapter(
|
||||
}
|
||||
}
|
||||
|
||||
class GameCollectionSquareItemViewHolder(val binding: GameCollectionSquareItemBinding) :
|
||||
class GameCollectionFilterItemViewHolder(val binding: ItemGameCollectionFilterBinding) :
|
||||
RecyclerView.ViewHolder(binding.root) {
|
||||
fun bindFilter(
|
||||
fragment: GameCollectionSquareFragment,
|
||||
viewModel: GameCollectionSquareViewModel,
|
||||
refreshCallback: () -> Unit
|
||||
) {
|
||||
binding.orderSfv.run {
|
||||
setContainerBackground(R.drawable.button_round_f5f5f5.toDrawable(context))
|
||||
setIndicatorBackground(R.drawable.bg_game_collection_sfv_indicator.toDrawable(context))
|
||||
setTextColor(
|
||||
R.color.text_subtitle.toColor(context),
|
||||
R.color.text_subtitleDesc.toColor(context)
|
||||
)
|
||||
}
|
||||
binding.orderSfv.post {
|
||||
// 防止标签文字过长
|
||||
binding.tagTv.maxWidth =
|
||||
DisplayUtils.getScreenWidth() - 80F.dip2px() - binding.orderSfv.width
|
||||
}
|
||||
|
||||
val orderPosition = GameCollectionSquareViewModel.getOrderPositionByName(viewModel.view)
|
||||
if (binding.orderSfv.getItemList().isEmpty()) {
|
||||
binding.orderSfv.setItemList(listOf("推荐", "热门", "最新"), orderPosition)
|
||||
} else if (binding.orderSfv.getCurrentPosition() != orderPosition) {
|
||||
binding.orderSfv.setChecked(orderPosition)
|
||||
}
|
||||
|
||||
binding.orderSfv.setOnCheckedCallback { position ->
|
||||
viewModel.view = GameCollectionSquareViewModel.getOrderNameByPosition(position)
|
||||
refreshCallback()
|
||||
}
|
||||
|
||||
binding.tagTv.text = viewModel.selectedTagEntity?.name ?: "全部标签"
|
||||
binding.tagFilter.background =
|
||||
if (viewModel.selectedTagEntity != null) R.drawable.bg_game_collection_tag_select.toDrawable() else R.drawable.bg_game_collection_tag_unselect.toDrawable()
|
||||
|
||||
binding.tagFilter.setOnClickListener {
|
||||
NewLogUtils.logEnterGameCollectionTag("首页tab栏")
|
||||
fragment.startActivityForResult(
|
||||
GameCollectionTagSelectActivity.getIntent(
|
||||
fragment.requireContext(),
|
||||
true,
|
||||
viewModel.selectedTagEntity
|
||||
),
|
||||
GameCollectionSquareFragment.REQUEST_SELECT_TAG
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inner class GameCollectionSquareItemViewHolder(val binding: GameCollectionSquareItemBinding) :
|
||||
RecyclerView.ViewHolder(binding.root) {
|
||||
@SuppressLint("SetTextI18n")
|
||||
fun bindGameCollection(
|
||||
viewModel: GameCollectionSquareViewModel,
|
||||
gamesCollectionEntity: GamesCollectionEntity,
|
||||
itemData: GameCollectionListItemData,
|
||||
isHome: Boolean
|
||||
isHome: Boolean,
|
||||
exposureSource: List<ExposureSource>
|
||||
) {
|
||||
binding.run {
|
||||
val context = root.context
|
||||
poster.setTag(ImageUtils.TAG_TARGET_WIDTH, mPosterWidth)
|
||||
display(poster, gamesCollectionEntity.cover)
|
||||
display(userIv, gamesCollectionEntity.user?.icon)
|
||||
titleTv.text = gamesCollectionEntity.title
|
||||
@ -418,7 +543,8 @@ class GameCollectionSquareAdapter(
|
||||
GameCollectionDetailActivity.getIntent(
|
||||
context,
|
||||
gamesCollectionEntity.id,
|
||||
!isHome
|
||||
isFromSquare = !isHome,
|
||||
exposureSourceList = ArrayList(exposureSource)
|
||||
)
|
||||
)
|
||||
}
|
||||
@ -457,13 +583,14 @@ class GameCollectionSquareAdapter(
|
||||
mIsLoading = true
|
||||
}
|
||||
LoadStatus.INIT -> {
|
||||
if (mEntityList != null) mEntityList.clear()
|
||||
if (mEntityList != null) mEntityList.removeAll { it.isGameCollectionItem }
|
||||
mIsNetworkError = false
|
||||
mIsOver = false
|
||||
mIsLoading = false
|
||||
notifyDataSetChanged()
|
||||
return
|
||||
}
|
||||
|
||||
else -> {
|
||||
//do nothing
|
||||
}
|
||||
@ -471,4 +598,8 @@ class GameCollectionSquareAdapter(
|
||||
|
||||
if (itemCount > 0 && status != LoadStatus.LIST_LOADED) notifyItemChanged(itemCount - 1)
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val ITEM_FILTER = 103
|
||||
}
|
||||
}
|
||||
@ -2,25 +2,32 @@ package com.gh.gamecenter.gamecollection.square
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Intent
|
||||
import android.graphics.Color
|
||||
import android.graphics.drawable.ColorDrawable
|
||||
import android.os.Bundle
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.os.Message
|
||||
import android.view.Gravity
|
||||
import android.view.MotionEvent
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.animation.AnimationUtils
|
||||
import android.widget.FrameLayout
|
||||
import android.widget.ImageView
|
||||
import android.widget.RelativeLayout
|
||||
import android.widget.LinearLayout
|
||||
import androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||
import androidx.core.view.ViewCompat
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.PagerSnapHelper
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import androidx.viewpager2.widget.ViewPager2
|
||||
import com.airbnb.lottie.LottieAnimationView
|
||||
import com.airbnb.lottie.LottieDrawable
|
||||
import com.ethanhua.skeleton.Skeleton
|
||||
import com.gh.common.exposure.*
|
||||
import com.gh.common.exposure.ExposureListener
|
||||
import com.gh.common.exposure.ExposureManager
|
||||
import com.gh.common.util.DirectUtils
|
||||
import com.gh.common.util.NewFlatLogUtils
|
||||
import com.gh.common.util.NewLogUtils
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.base.GlobalActivityManager
|
||||
@ -34,13 +41,14 @@ import com.gh.gamecenter.common.entity.ExposureEntity
|
||||
import com.gh.gamecenter.common.eventbus.EBReuse
|
||||
import com.gh.gamecenter.common.utils.*
|
||||
import com.gh.gamecenter.common.view.ScrollEventListener
|
||||
import com.gh.gamecenter.common.view.SegmentedFilterView
|
||||
import com.gh.gamecenter.common.view.VerticalItemDecoration
|
||||
import com.gh.gamecenter.core.utils.ClickUtils
|
||||
import com.gh.gamecenter.core.utils.DisplayUtils
|
||||
import com.gh.gamecenter.core.utils.SPUtils
|
||||
import com.gh.gamecenter.core.utils.TimeElapsedHelper
|
||||
import com.gh.gamecenter.databinding.FragmentGameCollectionSquareAlBinding
|
||||
import com.gh.gamecenter.databinding.FragmentGameCollectionSquareBinding
|
||||
import com.gh.gamecenter.databinding.LayoutGameCollectionFilterGuideBinding
|
||||
import com.gh.gamecenter.entity.GamesCollectionEntity
|
||||
import com.gh.gamecenter.entity.TagInfoEntity
|
||||
import com.gh.gamecenter.feature.exposure.ExposureEvent
|
||||
@ -69,6 +77,7 @@ class GameCollectionSquareFragment : LazyListFragment<GamesCollectionEntity, Gam
|
||||
private lateinit var mBannerLayoutManager: LinearLayoutManager
|
||||
|
||||
private var mAdapter: GameCollectionSquareAdapter? = null
|
||||
private var mGuideContainer: LinearLayout? = null
|
||||
private val mElapsedHelper by lazy { TimeElapsedHelper() }
|
||||
|
||||
private val mLooperHandle = LooperHandle(this)
|
||||
@ -77,6 +86,7 @@ class GameCollectionSquareFragment : LazyListFragment<GamesCollectionEntity, Gam
|
||||
|
||||
private var mUseAlternativeLayout = false
|
||||
private var mIsCollapsed = false
|
||||
private var mIsLoadDone = false
|
||||
private var mForumName = ""
|
||||
private var mGameCollectionTitle = ""
|
||||
private var mGameCollectionId = ""
|
||||
@ -100,19 +110,30 @@ class GameCollectionSquareFragment : LazyListFragment<GamesCollectionEntity, Gam
|
||||
mViewModel.isHome = mUseAlternativeLayout
|
||||
mListViewModel.load(LoadType.NORMAL)
|
||||
|
||||
NewLogUtils.logEnterGameCollectionSquare(mEntrance, mForumName, mGameCollectionTitle, mGameCollectionId)
|
||||
val collectionId = arguments?.getString(EntranceConsts.KEY_COLLECTION_ID, "") ?: ""
|
||||
val collectionName = arguments?.getString(EntranceConsts.KEY_COLLECTION_NAME, "") ?: ""
|
||||
NewLogUtils.logEnterGameCollectionSquare(
|
||||
mEntrance,
|
||||
mForumName,
|
||||
mGameCollectionTitle,
|
||||
mGameCollectionId,
|
||||
collectionName,
|
||||
collectionId
|
||||
)
|
||||
}
|
||||
|
||||
override fun onFragmentPause() {
|
||||
super.onFragmentPause()
|
||||
if (mUseAlternativeLayout) {
|
||||
val rootView = (parentFragment as? HomeSearchToolWrapperFragment)?.view
|
||||
rootView?.findViewById<ImageView>(R.id.fab)?.visibility = View.GONE
|
||||
rootView?.findViewById<ImageView>(R.id.postFab)?.visibility = View.GONE
|
||||
rootView?.findViewById<FrameLayout>(R.id.refreshFab)?.visibility = View.GONE
|
||||
mGuideContainer?.visibility = View.GONE
|
||||
} else {
|
||||
if (mExposureEventList.isNotEmpty()) ExposureManager.log(mExposureEventList)
|
||||
}
|
||||
val stayTime = (System.currentTimeMillis() - startPageTime) / 1000
|
||||
com.gh.common.util.NewFlatLogUtils.logGameCollectSquareStayTime(stayTime)
|
||||
NewFlatLogUtils.logGameCollectSquareStayTime(stayTime, if (mUseAlternativeLayout) "首页tab栏" else "游戏单广场")
|
||||
|
||||
mElapsedHelper.pauseCounting()
|
||||
if (mElapsedHelper.elapsedTime >= 3) {
|
||||
@ -138,7 +159,16 @@ class GameCollectionSquareFragment : LazyListFragment<GamesCollectionEntity, Gam
|
||||
super.onFragmentResume()
|
||||
if (mUseAlternativeLayout) {
|
||||
val rootView = (parentFragment as? HomeSearchToolWrapperFragment)?.view
|
||||
rootView?.findViewById<ImageView>(R.id.fab)?.visibility = View.VISIBLE
|
||||
rootView?.findViewById<ImageView>(R.id.postFab)?.visibility = View.VISIBLE
|
||||
rootView?.findViewById<FrameLayout>(R.id.refreshFab)?.visibility = View.VISIBLE
|
||||
if (mIsLoadDone) {
|
||||
mGuideContainer?.goneIf(
|
||||
!SPUtils.getBoolean(
|
||||
Constants.SP_SHOW_GAME_COLLECTION_SQUARE_FILTER_GUIDE,
|
||||
true
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
mElapsedHelper.resetCounting()
|
||||
mElapsedHelper.resumeCounting()
|
||||
@ -173,13 +203,25 @@ class GameCollectionSquareFragment : LazyListFragment<GamesCollectionEntity, Gam
|
||||
if (data == null || resultCode != Activity.RESULT_OK) return
|
||||
if (requestCode == REQUEST_SELECT_TAG) {
|
||||
val tagInfoEntity = data.getParcelableExtra<TagInfoEntity>(GameCollectionTagSelectFragment.SELECTED_TAG)
|
||||
val tagCategory = data.getStringExtra(GameCollectionTagSelectFragment.SELECTED_TAG_CATEGORY)
|
||||
if (tagInfoEntity != null) {
|
||||
NewLogUtils.logFilterGameCollectionTag(
|
||||
tagCategory ?: "",
|
||||
tagInfoEntity.name,
|
||||
if (mUseAlternativeLayout) "首页tab栏" else "游戏单广场"
|
||||
)
|
||||
}
|
||||
if (tagInfoEntity != mViewModel.selectedTagEntity) {
|
||||
mDefaultBinding.tagTv.text = tagInfoEntity?.name ?: "全部标签"
|
||||
mViewModel.selectedTagEntity = tagInfoEntity
|
||||
mViewModel.selectedTagId = tagInfoEntity?.id ?: ""
|
||||
mViewModel.selectedTagName = tagInfoEntity?.name ?: "全部标签"
|
||||
mDefaultBinding.tagFilter.background =
|
||||
if (tagInfoEntity != null) R.drawable.bg_game_collection_tag_select.toDrawable() else R.drawable.bg_game_collection_tag_unselect.toDrawable()
|
||||
if (mUseAlternativeLayout) {
|
||||
mAdapter?.notifyItemChanged(HOME_FILTER_ITEM_POSITION)
|
||||
} else {
|
||||
mDefaultBinding.tagFilterContainer.tagTv.text = tagInfoEntity?.name ?: "全部标签"
|
||||
mDefaultBinding.tagFilterContainer.tagFilter.background =
|
||||
if (tagInfoEntity != null) R.drawable.bg_game_collection_tag_select.toDrawable() else R.drawable.bg_game_collection_tag_unselect.toDrawable()
|
||||
}
|
||||
refresh()
|
||||
}
|
||||
}
|
||||
@ -218,24 +260,22 @@ class GameCollectionSquareFragment : LazyListFragment<GamesCollectionEntity, Gam
|
||||
GameCollectionSquareAdapter(
|
||||
requireContext(),
|
||||
mUseAlternativeLayout,
|
||||
this,
|
||||
mViewModel,
|
||||
mBasicExposureSource,
|
||||
outerSequence ?: (-1)
|
||||
)
|
||||
) {
|
||||
refresh()
|
||||
}
|
||||
}
|
||||
return mAdapter!!
|
||||
}
|
||||
|
||||
|
||||
private fun initDefaultLayout() {
|
||||
mDefaultBinding.nightMaskView.goneIf(!mIsDarkModeOn)
|
||||
mDefaultBinding.bannerBackground.background =
|
||||
if (mIsDarkModeOn) ColorDrawable(R.color.background_white.toColor(requireContext())) else R.drawable.bg_game_collection_square_banner.toDrawable(
|
||||
requireContext()
|
||||
)
|
||||
|
||||
// toolbar 消费 fitsSystemWindows 避免在 collapsingToolbar 下面出现多出来的 padding
|
||||
// [https://stackoverflow.com/questions/48137666/viewgroup-inside-collapsingtoolbarlayout-show-extra-bottom-padding-when-set-fits]
|
||||
DisplayUtils.setLightStatusBar(requireActivity(), !mIsDarkModeOn)
|
||||
ViewCompat.setOnApplyWindowInsetsListener(mDefaultBinding.appbar) { _, insets ->
|
||||
(mDefaultBinding.toolbar.layoutParams as ViewGroup.MarginLayoutParams).topMargin =
|
||||
insets.systemWindowInsetTop
|
||||
@ -254,7 +294,6 @@ class GameCollectionSquareFragment : LazyListFragment<GamesCollectionEntity, Gam
|
||||
mDefaultBinding.collapsingToolbar.scrimVisibleHeightTrigger = collapsingTrigger
|
||||
mDefaultBinding.collapsingToolbar.scrimShownAction = {
|
||||
mIsCollapsed = it
|
||||
DisplayUtils.setLightStatusBar(requireActivity(), !mIsDarkModeOn && it)
|
||||
changeToolbarStyle(it)
|
||||
}
|
||||
|
||||
@ -264,7 +303,7 @@ class GameCollectionSquareFragment : LazyListFragment<GamesCollectionEntity, Gam
|
||||
}
|
||||
}
|
||||
|
||||
mDefaultBinding.appbar.addOnOffsetChangedListener(AppBarLayout.OnOffsetChangedListener { _, verticalOffset ->
|
||||
mDefaultBinding.appbar.addOnOffsetChangedListener { _, verticalOffset ->
|
||||
val absOffset = abs(verticalOffset)
|
||||
val invisibleOffset = DisplayUtils.dip2px(30F)
|
||||
|
||||
@ -275,28 +314,22 @@ class GameCollectionSquareFragment : LazyListFragment<GamesCollectionEntity, Gam
|
||||
}
|
||||
|
||||
mListRefresh?.isEnabled = absOffset <= 2
|
||||
})
|
||||
}
|
||||
|
||||
// mReuseNoData?.findViewById<TextView>(R.id.reuseNoneDataTv)?.text = "哎呀,没有找到相关内容~"
|
||||
|
||||
mDefaultBinding.orderSfv.post {
|
||||
mDefaultBinding.tagFilterContainer.orderSfv.post {
|
||||
// 防止标签文字过长
|
||||
mDefaultBinding.tagTv.maxWidth =
|
||||
DisplayUtils.getScreenWidth() - 80F.dip2px() - mDefaultBinding.orderSfv.width
|
||||
mDefaultBinding.tagFilterContainer.tagTv.maxWidth =
|
||||
DisplayUtils.getScreenWidth() - 80F.dip2px() - mDefaultBinding.tagFilterContainer.orderSfv.width
|
||||
}
|
||||
mDefaultBinding.tagFilterContainer.orderSfv.setItemList(listOf("推荐", "热门", "最新"), 0)
|
||||
mDefaultBinding.tagFilterContainer.orderSfv.setOnCheckedCallback { position ->
|
||||
mViewModel.view = GameCollectionSquareViewModel.getOrderNameByPosition(position)
|
||||
refresh()
|
||||
}
|
||||
mDefaultBinding.orderSfv.setItemList(listOf("推荐", "热门", "最新"), 0)
|
||||
mDefaultBinding.orderSfv.setOnCheckedCallback(object : SegmentedFilterView.OnCheckedCallback {
|
||||
override fun onItemCheck(position: Int) {
|
||||
when (position) {
|
||||
0 -> mViewModel.view = "recommend"
|
||||
1 -> mViewModel.view = "hot"
|
||||
2 -> mViewModel.view = "new"
|
||||
}
|
||||
refresh()
|
||||
}
|
||||
})
|
||||
|
||||
mDefaultBinding.fab.setOnClickListener {
|
||||
mDefaultBinding.postFab.setOnClickListener {
|
||||
// 创建游戏单
|
||||
ifLogin(mEntrance) {
|
||||
showRegulationTestDialogIfNeeded {
|
||||
@ -305,26 +338,36 @@ class GameCollectionSquareFragment : LazyListFragment<GamesCollectionEntity, Gam
|
||||
}
|
||||
}
|
||||
|
||||
mDefaultBinding.refreshFab.setOnClickListener {
|
||||
if (!mDefaultBinding.refreshLottie.isAnimating) {
|
||||
NewFlatLogUtils.logGameCollectionSquareFlush("点击刷新按钮", ++mViewModel.refreshCount)
|
||||
mDefaultBinding.refreshLottie.playAnimation()
|
||||
refresh()
|
||||
}
|
||||
}
|
||||
|
||||
mDefaultBinding.listRv.addOnScrollListener(object : RecyclerView.OnScrollListener() {
|
||||
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
|
||||
super.onScrolled(recyclerView, dx, dy)
|
||||
if (dy > Constants.FOLLOW_HINT_TRIGGER_HEIGHT) {
|
||||
setFabStatus(mDefaultBinding.fab, View.GONE)
|
||||
} else if (dy < -Constants.FOLLOW_HINT_TRIGGER_HEIGHT) {
|
||||
setFabStatus(mDefaultBinding.fab, View.VISIBLE)
|
||||
override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
|
||||
super.onScrollStateChanged(recyclerView, newState)
|
||||
if (newState == RecyclerView.SCROLL_STATE_DRAGGING) {
|
||||
setFabStatus(mDefaultBinding.postFab, View.GONE)
|
||||
setFabStatus(mDefaultBinding.refreshFab, View.GONE)
|
||||
} else if (newState == RecyclerView.SCROLL_STATE_IDLE) {
|
||||
setFabStatus(mDefaultBinding.postFab, View.VISIBLE)
|
||||
setFabStatus(mDefaultBinding.refreshFab, View.VISIBLE)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
val bannerAdapter = GameCollectionBannerAdapter(
|
||||
requireContext(),
|
||||
false,
|
||||
mViewModel,
|
||||
mEntrance = "游戏单广场",
|
||||
mBasicExposureSource = mBasicExposureSource
|
||||
)
|
||||
mSnapHelper = PagerSnapHelper()
|
||||
mBannerLayoutManager = LinearLayoutManager(requireContext(), RecyclerView.HORIZONTAL, false)
|
||||
mDefaultBinding.bannerRv.run {
|
||||
mDefaultBinding.headerContainer.bannerRv.run {
|
||||
adapter = bannerAdapter
|
||||
layoutManager = mBannerLayoutManager
|
||||
mSnapHelper.attachToRecyclerView(this)
|
||||
@ -334,6 +377,7 @@ class GameCollectionSquareFragment : LazyListFragment<GamesCollectionEntity, Gam
|
||||
MotionEvent.ACTION_DOWN -> {
|
||||
mDefaultBinding.listRefresh.isEnabled = false
|
||||
}
|
||||
|
||||
MotionEvent.ACTION_UP -> {
|
||||
mDefaultBinding.listRefresh.isEnabled = true
|
||||
}
|
||||
@ -348,7 +392,7 @@ class GameCollectionSquareFragment : LazyListFragment<GamesCollectionEntity, Gam
|
||||
setOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
|
||||
override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {
|
||||
super.onPageScrolled(position, positionOffset, positionOffsetPixels)
|
||||
mDefaultBinding.bannerIndicator.onPageScrolled(
|
||||
mDefaultBinding.headerContainer.bannerIndicator.onPageScrolled(
|
||||
bannerAdapter.getActualPosition(position),
|
||||
positionOffset
|
||||
)
|
||||
@ -357,37 +401,19 @@ class GameCollectionSquareFragment : LazyListFragment<GamesCollectionEntity, Gam
|
||||
})
|
||||
}
|
||||
|
||||
mDefaultBinding.tagFilter.setOnClickListener {
|
||||
mDefaultBinding.headerContainer.hotListCv.setOnClickListener {
|
||||
DirectUtils.directToGameCollectionHotList(requireContext(), "游戏单广场")
|
||||
}
|
||||
|
||||
mDefaultBinding.tagFilterContainer.tagFilter.setOnClickListener {
|
||||
NewLogUtils.logEnterGameCollectionTag("游戏单广场")
|
||||
startActivityForResult(
|
||||
GameCollectionTagSelectActivity.getIntent(requireContext(), true, mViewModel.selectedTagEntity),
|
||||
REQUEST_SELECT_TAG
|
||||
)
|
||||
}
|
||||
|
||||
mViewModel.mBannerList.observeNonNull(this) {
|
||||
mDefaultBinding.tagFilterContainer.layoutParams =
|
||||
(mDefaultBinding.tagFilterContainer.layoutParams as AppBarLayout.LayoutParams).apply {
|
||||
setMargins(
|
||||
0,
|
||||
if (it.isEmpty()) (-16F).dip2px() else 0,
|
||||
0,
|
||||
0
|
||||
)
|
||||
}
|
||||
mDefaultBinding.headIv.goneIf(it.isNotEmpty())
|
||||
mDefaultBinding.bannerContainer.goneIf(it.isEmpty())
|
||||
mDefaultBinding.titleIv.goneIf(it.isEmpty())
|
||||
mDefaultBinding.sloganTv.goneIf(it.isEmpty())
|
||||
mDefaultBinding.statusBar.setBackgroundColor(
|
||||
if (it.isEmpty()) Color.TRANSPARENT
|
||||
else if (mIsDarkModeOn) R.color.background_white.toColor(requireContext())
|
||||
else R.color.game_collection_square.toColor(requireContext())
|
||||
)
|
||||
mDefaultBinding.toolbar.setBackgroundColor(
|
||||
if (it.isEmpty()) Color.TRANSPARENT
|
||||
else if (mIsDarkModeOn) R.color.background_white.toColor(requireContext())
|
||||
else R.color.game_collection_square.toColor(requireContext())
|
||||
)
|
||||
mViewModel.bannerList.observeNonNull(this) {
|
||||
if (it.isNotEmpty()) {
|
||||
bannerAdapter.submitList(it)
|
||||
mExposureEventList.clear()
|
||||
@ -405,16 +431,24 @@ class GameCollectionSquareFragment : LazyListFragment<GamesCollectionEntity, Gam
|
||||
mExposureEventList.add(exposureEvent)
|
||||
}
|
||||
if (bannerAdapter.getActualSize() > 1) {
|
||||
mDefaultBinding.bannerRv.scrollToPosition(bannerAdapter.getActualFirstPositionInCenter())
|
||||
mDefaultBinding.headerContainer.bannerRv.scrollToPosition(bannerAdapter.getActualFirstPositionInCenter())
|
||||
}
|
||||
mDefaultBinding.bannerIndicator.run {
|
||||
mPageSize = bannerAdapter.getActualSize()
|
||||
mDefaultBinding.headerContainer.bannerIndicator.run {
|
||||
pageSize = bannerAdapter.getActualSize()
|
||||
notifyDataChanged()
|
||||
}
|
||||
startAutoPlay()
|
||||
}
|
||||
}
|
||||
|
||||
mViewModel.amwayCommentList.observeNonNull(this) {
|
||||
bannerAdapter.submitList(amwayList = it)
|
||||
}
|
||||
|
||||
mViewModel.hotListFirstTab.observeNonNull(this) {
|
||||
mDefaultBinding.headerContainer.tabNameTv.text = it
|
||||
}
|
||||
|
||||
mListRefresh?.setProgressViewOffset(
|
||||
false,
|
||||
0,
|
||||
@ -427,29 +461,12 @@ class GameCollectionSquareFragment : LazyListFragment<GamesCollectionEntity, Gam
|
||||
mDefaultBinding.titleTv.alpha = 1F
|
||||
mDefaultBinding.titleTv.visibility = View.VISIBLE
|
||||
mDefaultBinding.titleTv.setTextColor(R.color.text_black.toColor(requireContext()))
|
||||
mDefaultBinding.toolbar.setNavigationIcon(R.drawable.ic_bar_back)
|
||||
mDefaultBinding.tagFilterContainer.background = null
|
||||
mDefaultBinding.titleIv.visibility = View.GONE
|
||||
mDefaultBinding.sloganTv.visibility = View.GONE
|
||||
mDefaultBinding.statusBar.setBackgroundColor(Color.TRANSPARENT)
|
||||
mDefaultBinding.toolbar.setBackgroundColor(Color.TRANSPARENT)
|
||||
} else {
|
||||
mDefaultBinding.titleTv.visibility = View.GONE
|
||||
mDefaultBinding.toolbar.navigationIcon = R.drawable.ic_bar_back_light.toDrawable(requireContext())
|
||||
mDefaultBinding.tagFilterContainer.background =
|
||||
R.drawable.bg_game_collection_square.toDrawable(requireContext())
|
||||
mDefaultBinding.titleIv.goneIf(mViewModel.mBannerList.value.isNullOrEmpty())
|
||||
mDefaultBinding.sloganTv.goneIf(mViewModel.mBannerList.value.isNullOrEmpty())
|
||||
mDefaultBinding.statusBar.setBackgroundColor(
|
||||
if (mViewModel.mBannerList.value.isNullOrEmpty()) Color.TRANSPARENT
|
||||
else if (mIsDarkModeOn) R.color.background_white.toColor(requireContext())
|
||||
else R.color.game_collection_square.toColor(requireContext())
|
||||
)
|
||||
mDefaultBinding.toolbar.setBackgroundColor(
|
||||
if (mViewModel.mBannerList.value.isNullOrEmpty()) Color.TRANSPARENT
|
||||
else if (mIsDarkModeOn) R.color.background_white.toColor(requireContext())
|
||||
else R.color.game_collection_square.toColor(requireContext())
|
||||
)
|
||||
mDefaultBinding.titleIv.visibility = View.VISIBLE
|
||||
mDefaultBinding.sloganTv.visibility = View.VISIBLE
|
||||
}
|
||||
}
|
||||
|
||||
@ -457,7 +474,7 @@ class GameCollectionSquareFragment : LazyListFragment<GamesCollectionEntity, Gam
|
||||
val snapView = mSnapHelper.findSnapView(mBannerLayoutManager)
|
||||
if (snapView != null) {
|
||||
mBannerLayoutManager.smoothScrollToPosition(
|
||||
mDefaultBinding.bannerRv,
|
||||
mDefaultBinding.headerContainer.bannerRv,
|
||||
null,
|
||||
mBannerLayoutManager.getPosition(snapView) + 1
|
||||
)
|
||||
@ -465,7 +482,7 @@ class GameCollectionSquareFragment : LazyListFragment<GamesCollectionEntity, Gam
|
||||
}
|
||||
|
||||
private fun startAutoPlay() {
|
||||
if ((mDefaultBinding.bannerRv.adapter as GameCollectionBannerAdapter).getActualSize() <= 1) return
|
||||
if ((mDefaultBinding.headerContainer.bannerRv.adapter as GameCollectionBannerAdapter).getActualSize() <= 1) return
|
||||
stopAutoPlay()
|
||||
mLooperHandle.sendEmptyMessageDelayed(mSlideLooperKey, BANNER_LOOP_TIME)
|
||||
}
|
||||
@ -476,15 +493,10 @@ class GameCollectionSquareFragment : LazyListFragment<GamesCollectionEntity, Gam
|
||||
|
||||
private fun initAlternativeLayout() {
|
||||
if (parentFragment is HomeSearchToolWrapperFragment) {
|
||||
val rootView = (parentFragment as HomeSearchToolWrapperFragment).view
|
||||
if (rootView is RelativeLayout) {
|
||||
val fabView = ImageView(context).apply {
|
||||
id = R.id.fab
|
||||
layoutParams = RelativeLayout.LayoutParams(60F.dip2px(), 60F.dip2px()).apply {
|
||||
addRule(RelativeLayout.ALIGN_PARENT_BOTTOM)
|
||||
addRule(RelativeLayout.ALIGN_PARENT_RIGHT)
|
||||
setMargins(0, 0, 14F.dip2px(), 14F.dip2px())
|
||||
}
|
||||
val rootView = (parentFragment as HomeSearchToolWrapperFragment).view?.findViewById<CoordinatorLayout>(R.id.coordinator)
|
||||
if (rootView != null) {
|
||||
val postFabView = ImageView(context).apply {
|
||||
id = R.id.postFab
|
||||
background = R.drawable.community_edit_icon.toDrawable()
|
||||
setOnClickListener {
|
||||
ifLogin(mEntrance) {
|
||||
@ -500,14 +512,50 @@ class GameCollectionSquareFragment : LazyListFragment<GamesCollectionEntity, Gam
|
||||
}
|
||||
}
|
||||
}
|
||||
rootView.addView(fabView)
|
||||
val refreshLottieView = LottieAnimationView(requireContext()).apply {
|
||||
id = R.id.refreshLottie
|
||||
layoutParams = FrameLayout.LayoutParams(45F.dip2px(), 45F.dip2px()).apply {
|
||||
gravity = Gravity.CENTER
|
||||
}
|
||||
setAnimation("lottie/icon_fab_change.json")
|
||||
repeatMode = LottieDrawable.RESTART
|
||||
}
|
||||
val refreshFabView = FrameLayout(requireContext()).apply {
|
||||
id = R.id.refreshFab
|
||||
background = R.drawable.bg_fab_container.toDrawable()
|
||||
addView(refreshLottieView)
|
||||
setOnClickListener {
|
||||
if (!refreshLottieView.isAnimating) {
|
||||
NewFlatLogUtils.logGameCollectionSquareFlush("点击刷新按钮", ++mViewModel.refreshCount)
|
||||
refreshLottieView.playAnimation()
|
||||
refresh()
|
||||
}
|
||||
}
|
||||
}
|
||||
rootView.addView(postFabView, CoordinatorLayout.LayoutParams(60F.dip2px(), 60F.dip2px()).also {
|
||||
it.gravity = Gravity.BOTTOM.xor(Gravity.END)
|
||||
it.setMargins(0, 0, 8F.dip2px(), 32F.dip2px())
|
||||
})
|
||||
rootView.addView(refreshFabView, CoordinatorLayout.LayoutParams(60F.dip2px(), 60F.dip2px()).also {
|
||||
it.gravity = Gravity.BOTTOM.xor(Gravity.END)
|
||||
it.setMargins(0, 0, 8F.dip2px(), 92F.dip2px())
|
||||
})
|
||||
|
||||
mGuideContainer = LayoutGameCollectionFilterGuideBinding.inflate(layoutInflater).root
|
||||
rootView.addView(mGuideContainer, CoordinatorLayout.LayoutParams(CoordinatorLayout.LayoutParams.MATCH_PARENT, CoordinatorLayout.LayoutParams.MATCH_PARENT).apply {
|
||||
behavior = AppBarLayout.ScrollingViewBehavior()
|
||||
setMargins(0, 52F.dip2px(), 0, 0)
|
||||
})
|
||||
|
||||
mAlternativeBinding.listRv.addOnScrollListener(object : RecyclerView.OnScrollListener() {
|
||||
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
|
||||
super.onScrolled(recyclerView, dx, dy)
|
||||
if (dy > Constants.FOLLOW_HINT_TRIGGER_HEIGHT) {
|
||||
setFabStatus(fabView, View.GONE)
|
||||
} else if (dy < -Constants.FOLLOW_HINT_TRIGGER_HEIGHT) {
|
||||
setFabStatus(fabView, View.VISIBLE)
|
||||
override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
|
||||
super.onScrollStateChanged(recyclerView, newState)
|
||||
if (newState == RecyclerView.SCROLL_STATE_DRAGGING) {
|
||||
setFabStatus(postFabView, View.GONE)
|
||||
setFabStatus(refreshFabView, View.GONE)
|
||||
} else if (newState == RecyclerView.SCROLL_STATE_IDLE) {
|
||||
setFabStatus(postFabView, View.VISIBLE)
|
||||
setFabStatus(refreshFabView, View.VISIBLE)
|
||||
}
|
||||
}
|
||||
})
|
||||
@ -516,13 +564,17 @@ class GameCollectionSquareFragment : LazyListFragment<GamesCollectionEntity, Gam
|
||||
|
||||
// mReuseNoData?.findViewById<TextView>(R.id.reuseNoneDataTv)?.text = "哎呀,没有找到相关内容~"
|
||||
|
||||
mViewModel.mAmwayCommentList.observeNonNull(this) {
|
||||
mViewModel.amwayCommentList.observeNonNull(this) {
|
||||
mAdapter?.setAmwayList(it)
|
||||
}
|
||||
|
||||
mViewModel.mBannerList.observeNonNull(this) {
|
||||
mViewModel.bannerList.observeNonNull(this) {
|
||||
mAdapter?.setBannerList(it)
|
||||
}
|
||||
|
||||
mViewModel.hotListFirstTab.observeNonNull(this) {
|
||||
mAdapter?.setHotListTabName(it)
|
||||
}
|
||||
}
|
||||
|
||||
private fun setFabStatus(fab: View, visibility: Int) {
|
||||
@ -538,23 +590,43 @@ class GameCollectionSquareFragment : LazyListFragment<GamesCollectionEntity, Gam
|
||||
}
|
||||
|
||||
override fun onLoadEmpty() {
|
||||
super.onLoadEmpty()
|
||||
if (!mUseAlternativeLayout) mDefaultBinding.tagFilterContainer.visibility = View.VISIBLE
|
||||
showSkeleton(false)
|
||||
if (mReuseNoConn != null) mReuseNoConn!!.visibility = View.GONE
|
||||
if (mReuseNoData != null) mReuseNoData!!.visibility = View.VISIBLE
|
||||
if (mListLoading != null) mListLoading!!.visibility = View.GONE
|
||||
if (mDataExceptionView != null) mDataExceptionView!!.visibility = View.GONE
|
||||
mListRv.isVisible = mUseAlternativeLayout
|
||||
hideRefreshingLayout()
|
||||
if (!mUseAlternativeLayout) mDefaultBinding.tagFilterContainer.root.visibility = View.VISIBLE
|
||||
}
|
||||
|
||||
override fun onLoadDone() {
|
||||
super.onLoadDone()
|
||||
if (!mUseAlternativeLayout) mDefaultBinding.tagFilterContainer.visibility = View.VISIBLE
|
||||
mIsLoadDone = true
|
||||
if (!mUseAlternativeLayout) mDefaultBinding.tagFilterContainer.root.visibility = View.VISIBLE
|
||||
|
||||
val guideContainer =
|
||||
if (mUseAlternativeLayout) mGuideContainer else mDefaultBinding.guideContainer
|
||||
guideContainer?.goneIf(
|
||||
!SPUtils.getBoolean(
|
||||
Constants.SP_SHOW_GAME_COLLECTION_SQUARE_FILTER_GUIDE,
|
||||
true
|
||||
)
|
||||
) {
|
||||
guideContainer.setOnClickListener {
|
||||
SPUtils.setBoolean(Constants.SP_SHOW_GAME_COLLECTION_SQUARE_FILTER_GUIDE, false)
|
||||
guideContainer.visibility = View.GONE
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onLoadError() {
|
||||
super.onLoadError()
|
||||
if (!mUseAlternativeLayout) mDefaultBinding.tagFilterContainer.visibility = View.GONE
|
||||
if (!mUseAlternativeLayout) mDefaultBinding.tagFilterContainer.root.visibility = View.GONE
|
||||
}
|
||||
|
||||
override fun onLoadRefresh() {
|
||||
super.onLoadRefresh()
|
||||
if (!mUseAlternativeLayout) mDefaultBinding.tagFilterContainer.visibility = View.VISIBLE
|
||||
refresh(true)
|
||||
}
|
||||
|
||||
private fun initSkeleton() {
|
||||
@ -578,14 +650,21 @@ class GameCollectionSquareFragment : LazyListFragment<GamesCollectionEntity, Gam
|
||||
}
|
||||
}
|
||||
|
||||
private fun refresh() {
|
||||
private fun refresh(showSkeleton: Boolean = false) {
|
||||
showSkeleton(showSkeleton)
|
||||
if (mReuseNoConn != null) mReuseNoConn!!.visibility = View.GONE
|
||||
if (mListLoading != null) mListLoading!!.visibility =
|
||||
if (mListRefresh == null || !mListRefresh!!.isRefreshing) View.VISIBLE else View.GONE
|
||||
if (mReuseNoData != null) mReuseNoData!!.visibility = View.GONE
|
||||
if (mListRv != null) mListRv.visibility = View.GONE
|
||||
if (mListRv != null && (!mUseAlternativeLayout || showSkeleton)) mListRv.visibility = View.GONE
|
||||
if (!mUseAlternativeLayout) mDefaultBinding.tagFilterContainer.root.visibility = View.VISIBLE
|
||||
if (mUseAlternativeLayout) {
|
||||
mAdapter?.run {
|
||||
entityList?.removeAll { it.isGameCollectionItem }
|
||||
notifyItemRangeRemoved(2, itemCount)
|
||||
}
|
||||
}
|
||||
mBaseHandler.postDelayed({ mListViewModel.load(LoadType.REFRESH) }, 500)
|
||||
if (!mUseAlternativeLayout) mDefaultBinding.tagFilterContainer.visibility = View.VISIBLE
|
||||
}
|
||||
|
||||
private fun scrollToTop() {
|
||||
@ -607,6 +686,11 @@ class GameCollectionSquareFragment : LazyListFragment<GamesCollectionEntity, Gam
|
||||
}
|
||||
}
|
||||
|
||||
override fun onRefresh() {
|
||||
NewFlatLogUtils.logGameCollectionSquareFlush("下拉刷新", ++mViewModel.refreshCount)
|
||||
super.onRefresh()
|
||||
}
|
||||
|
||||
override fun onDarkModeChanged() {
|
||||
super.onDarkModeChanged()
|
||||
mItemDecoration?.let { mListRv?.removeItemDecoration(it) }
|
||||
@ -618,15 +702,11 @@ class GameCollectionSquareFragment : LazyListFragment<GamesCollectionEntity, Gam
|
||||
} else if (::mDefaultBinding.isInitialized) {
|
||||
initSkeleton()
|
||||
showSkeleton(mListViewModel.loadStatusLiveData.value == LoadStatus.INIT_LOADING)
|
||||
mDefaultBinding.nightMaskView.goneIf(!mIsDarkModeOn)
|
||||
mDefaultBinding.bannerBackground.background =
|
||||
if (mIsDarkModeOn) ColorDrawable(R.color.background_white.toColor(requireContext())) else R.drawable.bg_game_collection_square_banner.toDrawable(
|
||||
requireContext()
|
||||
)
|
||||
mDefaultBinding.listRefresh.setBackgroundColor(R.color.background_white.toColor(requireContext()))
|
||||
mDefaultBinding.appbar.setBackgroundColor(R.color.background_white.toColor(requireContext()))
|
||||
mDefaultBinding.toolbar.navigationIcon = R.drawable.ic_bar_back.toDrawable(requireContext())
|
||||
mDefaultBinding.collapsingToolbar.setContentScrimColor(R.color.background_white.toColor(requireContext()))
|
||||
mDefaultBinding.orderSfv.run {
|
||||
mDefaultBinding.tagFilterContainer.orderSfv.run {
|
||||
setContainerBackground(R.drawable.button_round_f5f5f5.toDrawable(requireContext()))
|
||||
setIndicatorBackground(R.drawable.bg_game_collection_sfv_indicator.toDrawable(requireContext()))
|
||||
setTextColor(
|
||||
@ -634,7 +714,7 @@ class GameCollectionSquareFragment : LazyListFragment<GamesCollectionEntity, Gam
|
||||
R.color.text_subtitleDesc.toColor(requireContext())
|
||||
)
|
||||
}
|
||||
DisplayUtils.setLightStatusBar(requireActivity(), !mIsDarkModeOn && mIsCollapsed)
|
||||
DisplayUtils.setLightStatusBar(requireActivity(), !mIsDarkModeOn)
|
||||
changeToolbarStyle(mIsCollapsed)
|
||||
}
|
||||
}
|
||||
@ -642,6 +722,7 @@ class GameCollectionSquareFragment : LazyListFragment<GamesCollectionEntity, Gam
|
||||
companion object {
|
||||
const val REQUEST_SELECT_TAG = 100
|
||||
const val BANNER_LOOP_TIME = 5000L
|
||||
const val HOME_FILTER_ITEM_POSITION = 1
|
||||
}
|
||||
|
||||
class LooperHandle(fragment: GameCollectionSquareFragment) : Handler(Looper.getMainLooper()) {
|
||||
|
||||
@ -7,8 +7,9 @@ import com.gh.common.filter.RegionSettingHelper
|
||||
import com.gh.gamecenter.common.baselist.ListViewModel
|
||||
import com.gh.gamecenter.common.baselist.LoadParams
|
||||
import com.gh.gamecenter.common.baselist.LoadStatus
|
||||
import com.gh.gamecenter.common.baselist.LoadType
|
||||
import com.gh.gamecenter.common.retrofit.BiResponse
|
||||
import com.gh.gamecenter.common.retrofit.Response
|
||||
import com.gh.gamecenter.common.utils.observableToMain
|
||||
import com.gh.gamecenter.entity.*
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager
|
||||
import io.reactivex.Observable
|
||||
@ -19,24 +20,25 @@ import java.util.*
|
||||
class GameCollectionSquareViewModel(application: Application) :
|
||||
ListViewModel<GamesCollectionEntity, GameCollectionListItemData>(application) {
|
||||
|
||||
private val mApi = RetrofitManager.getInstance().api
|
||||
private val mRandomId = UUID.randomUUID().toString()
|
||||
|
||||
var entrance: String? = null
|
||||
var selectedTagEntity: TagInfoEntity? = null
|
||||
var selectedTagId = ""
|
||||
var selectedTagName = "全部标签"
|
||||
var view = "recommend"
|
||||
var isHome = false
|
||||
var refreshCount = 0
|
||||
|
||||
val mAmwayCommentList = MutableLiveData<List<AmwayCommentEntity>>()
|
||||
val mBannerList = MutableLiveData<List<CarouselEntity>>()
|
||||
|
||||
override fun load(loadType: LoadType?) {
|
||||
if (loadType == LoadType.REFRESH) mResultLiveData.postValue(arrayListOf())
|
||||
super.load(loadType)
|
||||
}
|
||||
val amwayCommentList = MutableLiveData<List<AmwayCommentEntity>>()
|
||||
val bannerList = MutableLiveData<List<CarouselEntity>>()
|
||||
val hotListFirstTab = MutableLiveData<String>()
|
||||
|
||||
override fun loadData() {
|
||||
if (isHome) getAmwayCommentList()
|
||||
getAmwayCommentList()
|
||||
getBannerList()
|
||||
getGameCollectionHotListTab()
|
||||
super.loadData()
|
||||
}
|
||||
|
||||
@ -45,27 +47,51 @@ class GameCollectionSquareViewModel(application: Application) :
|
||||
mLoadStatusLiveData.value = LoadStatus.INIT
|
||||
}
|
||||
|
||||
override fun provideDataSingle(page: Int): Single<MutableList<GamesCollectionEntity>> =
|
||||
if (isHome)
|
||||
RetrofitManager.getInstance()
|
||||
.api.getHomeGameCollectionSquareList(UUID.randomUUID().toString(), page, PAGE_SIZE)
|
||||
else
|
||||
RetrofitManager.getInstance()
|
||||
.api.getGameCollectionSquareList(view, selectedTagId, page, PAGE_SIZE)
|
||||
override fun provideDataSingle(page: Int): Single<MutableList<GamesCollectionEntity>> {
|
||||
val paramsMap = if (selectedTagId.isNotEmpty()) {
|
||||
mutableMapOf("tag_id" to selectedTagId)
|
||||
} else {
|
||||
mutableMapOf()
|
||||
}
|
||||
if (view == "recommend") {
|
||||
paramsMap["random"] = mRandomId
|
||||
if (refreshCount == 0 && page == 1) {
|
||||
paramsMap["refresh"] = "true"
|
||||
}
|
||||
}
|
||||
return RetrofitManager.getInstance()
|
||||
.api.getGameCollectionSquareList(
|
||||
view,
|
||||
page,
|
||||
PAGE_SIZE,
|
||||
paramsMap.toMap()
|
||||
)
|
||||
}
|
||||
|
||||
override fun mergeResultLiveData() {
|
||||
mResultLiveData.addSource(mListLiveData) { list ->
|
||||
val itemDataList = arrayListOf<GameCollectionListItemData>().apply {
|
||||
var position = 0
|
||||
if (isHome) add(
|
||||
GameCollectionListItemData(
|
||||
amwayListItem = mAmwayCommentList.value,
|
||||
carouselListItem = mBannerList.value
|
||||
if (isHome) {
|
||||
add(
|
||||
GameCollectionListItemData(
|
||||
amwayListItem = amwayCommentList.value,
|
||||
carouselListItem = bannerList.value,
|
||||
hotListTabName = hotListFirstTab.value ?: "",
|
||||
isHeaderItem = true
|
||||
)
|
||||
)
|
||||
)
|
||||
add(GameCollectionListItemData(isFilterItem = true))
|
||||
}
|
||||
for (item in list) {
|
||||
item.games = RegionSettingHelper.filterSimpleGame(item.games)
|
||||
add(GameCollectionListItemData(gameCollectionItem = item, gameStartPosition = position))
|
||||
add(
|
||||
GameCollectionListItemData(
|
||||
gameCollectionItem = item,
|
||||
gameStartPosition = position,
|
||||
isGameCollectionItem = true
|
||||
)
|
||||
)
|
||||
position += if (item.count?.game!! > 2) 3 else if (item.games?.size == 0) 0 else item.count?.game
|
||||
?: 0
|
||||
}
|
||||
@ -78,33 +104,63 @@ class GameCollectionSquareViewModel(application: Application) :
|
||||
|
||||
@SuppressLint("CheckResult")
|
||||
fun getAmwayCommentList() {
|
||||
RetrofitManager.getInstance().api
|
||||
.getAmwayCommentList(1, 10)
|
||||
mApi.getAmwayCommentList(1, 10)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.subscribe(object : BiResponse<List<AmwayCommentEntity>>() {
|
||||
override fun onSuccess(data: List<AmwayCommentEntity>) {
|
||||
mAmwayCommentList.postValue(data)
|
||||
amwayCommentList.postValue(data)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@SuppressLint("CheckResult")
|
||||
fun getBannerList() {
|
||||
RetrofitManager.getInstance().api
|
||||
.gameCollectionSquareBanner
|
||||
mApi.gameCollectionSquareBanner
|
||||
.subscribeOn(Schedulers.io())
|
||||
.subscribe(object : BiResponse<List<CarouselEntity>>() {
|
||||
override fun onSuccess(data: List<CarouselEntity>) {
|
||||
mBannerList.postValue(data)
|
||||
bannerList.postValue(data)
|
||||
}
|
||||
|
||||
override fun onFailure(exception: Exception) {
|
||||
mBannerList.postValue(emptyList())
|
||||
bannerList.postValue(emptyList())
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private fun getGameCollectionHotListTab() {
|
||||
mApi.gameCollectionHotListTab
|
||||
.compose(observableToMain())
|
||||
.subscribe(object : Response<List<GameCollectionHotListTab>>() {
|
||||
override fun onResponse(response: List<GameCollectionHotListTab>?) {
|
||||
super.onResponse(response)
|
||||
response?.firstOrNull()?.let {
|
||||
hotListFirstTab.postValue(it.name)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val PAGE_SIZE = 15
|
||||
|
||||
fun getOrderNameByPosition(position: Int) = when (position) {
|
||||
1 -> "hot"
|
||||
2 -> "new"
|
||||
else -> "recommend"
|
||||
}
|
||||
|
||||
fun getOrderPositionByName(name: String) = when (name) {
|
||||
"hot" -> 1
|
||||
"new" -> 2
|
||||
else -> 0
|
||||
}
|
||||
|
||||
fun getOrderChineseByName(name: String) = when (name) {
|
||||
"recommend" -> "推荐"
|
||||
"hot" -> "热门"
|
||||
"new" -> "最新"
|
||||
else -> ""
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -86,13 +86,12 @@ class GameCollectionTagSelectFragment : ToolbarFragment() {
|
||||
mSingleChoice,
|
||||
mMaxSelectCount,
|
||||
mSelectedTag,
|
||||
updateSelectedTagView,
|
||||
{ back() })
|
||||
updateSelectedTagView
|
||||
) { back() }
|
||||
if (!mSelectedTags.isNullOrEmpty()) {
|
||||
mAdapter.selectedTagEntityList.addAll(mSelectedTags!!)
|
||||
}
|
||||
mViewModel = viewModelProvider()
|
||||
if (mSingleChoice) NewLogUtils.logEnterGameCollectionTag()
|
||||
mBinding.tagRv.run {
|
||||
layoutManager = LinearLayoutManager(requireContext())
|
||||
adapter = mAdapter
|
||||
@ -114,12 +113,12 @@ class GameCollectionTagSelectFragment : ToolbarFragment() {
|
||||
}
|
||||
|
||||
private fun back() {
|
||||
if (mAdapter.selectedTagEntity != null) {
|
||||
NewLogUtils.logFilterGameCollectionTag(mAdapter.selectedTagCategory, mAdapter.selectedTagEntity!!.name)
|
||||
}
|
||||
requireActivity().setResult(
|
||||
Activity.RESULT_OK,
|
||||
Intent().putExtra(SELECTED_TAG, mAdapter.selectedTagEntity)
|
||||
Intent().apply {
|
||||
putExtra(SELECTED_TAG, mAdapter.selectedTagEntity)
|
||||
putExtra(SELECTED_TAG_CATEGORY, mAdapter.selectedTagCategory)
|
||||
}
|
||||
)
|
||||
requireActivity().finish()
|
||||
}
|
||||
@ -135,5 +134,6 @@ class GameCollectionTagSelectFragment : ToolbarFragment() {
|
||||
|
||||
companion object {
|
||||
const val SELECTED_TAG = "selected_tag"
|
||||
const val SELECTED_TAG_CATEGORY = "selected_tag_category"
|
||||
}
|
||||
}
|
||||
@ -711,6 +711,7 @@ class GameDetailFragment : ToolbarFragment(), IScrollable {
|
||||
if (gameResource.status == Status.SUCCESS) {
|
||||
mViewModel.logHistory(gameResource.data!!)
|
||||
mGameEntity = gameResource.data
|
||||
showBrowserInstallHintIfNeeded()
|
||||
controlInstallHint()
|
||||
// 添加启动弹窗的相关信息
|
||||
if (mEntrance.contains(EntranceConsts.ENTRANCE_WELCOME) && mEntrance.countOccurrences("+") <= 1) {
|
||||
@ -1957,7 +1958,8 @@ class GameDetailFragment : ToolbarFragment(), IScrollable {
|
||||
}
|
||||
|
||||
private fun showBrowserInstallHintIfNeeded() {
|
||||
if (BrowserInstallHelper.shouldShowGameDetailUseBrowserToInstallHint()) {
|
||||
if (BrowserInstallHelper.shouldShowGameDetailUseBrowserToInstallHint()
|
||||
&& mGameEntity?.isSplitXApk() != true) {
|
||||
mDownloadBinding.browserInstallHintContainer.visibility = View.VISIBLE
|
||||
mDownloadBinding.browserInstallHintContainer.setOnClickListener {
|
||||
val intent = ShellActivity.getIntent(
|
||||
@ -2290,12 +2292,12 @@ class GameDetailFragment : ToolbarFragment(), IScrollable {
|
||||
mDownloadBinding.ivVmode.enlargeTouchArea()
|
||||
mDownloadBinding.ivVmode.setOnClickListener { _ ->
|
||||
val downloadStatus = when (entity.downloadStatus) {
|
||||
"smooth" -> "畅玩"
|
||||
Constants.V_GAME, Constants.V_GAME_32 -> "畅玩"
|
||||
"demo" -> "试玩"
|
||||
else -> "下载"
|
||||
}
|
||||
NewFlatLogUtils.logHaloFunGameDetailJumpClick(downloadStatus, simpleGame.id ?: "")
|
||||
DirectUtils.directToGameDetail(requireContext(), it.id ?: "", mEntrance)
|
||||
DirectUtils.directToGameDetail(requireContext(), it.id ?: "", entrance = mEntrance)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -141,6 +141,28 @@ class GameDetailViewModel(
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(object : BiResponse<NewGameDetailEntity>() {
|
||||
override fun onSuccess(data: NewGameDetailEntity) {
|
||||
if (data.newNotice != null) {
|
||||
// 存在new_notice字段时移除detail_tab里面type=notice的项并添加new_notice到detail_tab
|
||||
var noticePosition = -1
|
||||
data.detailEntity.forEachIndexed { index, it ->
|
||||
if (it.type == DetailEntity.Type.NOTICE.value) {
|
||||
noticePosition = index
|
||||
}
|
||||
}
|
||||
if (noticePosition != -1) {
|
||||
data.detailEntity.removeAt(noticePosition)
|
||||
data.detailEntity.add(
|
||||
noticePosition,
|
||||
DetailEntity(type = DetailEntity.Type.NOTICE.value, noticeList = data.newNotice)
|
||||
)
|
||||
} else {
|
||||
data.detailEntity.add(
|
||||
0,
|
||||
DetailEntity(type = DetailEntity.Type.NOTICE.value, noticeList = data.newNotice)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
filterGameTags(data)
|
||||
replaceWithMirrorInfoIfNeeded(data)
|
||||
// 4.4以下设备不显示顶部视频
|
||||
@ -164,7 +186,12 @@ class GameDetailViewModel(
|
||||
// 初始化礼包按钮状态
|
||||
for (entity in data.detailEntity) {
|
||||
if (entity.type == "libao") {
|
||||
val simpleGame = SimpleGame(gameId, mName = game?.name)
|
||||
val simpleGame = SimpleGame(
|
||||
gameId,
|
||||
mName = game?.name,
|
||||
mIcon = game?.icon,
|
||||
mRawIcon = game?.rawIcon
|
||||
)
|
||||
if (entity.libao != null) {
|
||||
loadLiBaoStatus(data, entity.libao!!)
|
||||
for (libaoEntity in entity.libao!!) {
|
||||
|
||||
@ -68,6 +68,7 @@ class DescAdapter(
|
||||
|
||||
var descItemList = arrayListOf<DetailEntity>()
|
||||
|
||||
private val mGameId = mViewModel.game?.id ?: ""
|
||||
private val mGameName = mViewModel.game?.name ?: "unknown"
|
||||
private val mExpandableTextViewMaxLinesSparseIntArray = SparseIntArray()
|
||||
private val mExpandableTextExpandStatusSparseBooleanArray = SparseBooleanArray()
|
||||
@ -178,11 +179,11 @@ class DescAdapter(
|
||||
|
||||
// 绑定公告
|
||||
private fun bindNoticeViewHolder(viewHolder: GameDetailNoticeViewHolder, itemData: DetailEntity) {
|
||||
val noticeList = itemData.noticeList!!
|
||||
val noticeList = itemData.noticeList ?: return
|
||||
val list = arrayListOf<String>()
|
||||
|
||||
for (newsEntity in noticeList) {
|
||||
list.add(newsEntity.title)
|
||||
list.add(newsEntity.title ?: "")
|
||||
}
|
||||
|
||||
viewHolder.binding.run {
|
||||
@ -202,12 +203,10 @@ class DescAdapter(
|
||||
gamedetailItemNotice.enableSingleLineText()
|
||||
gamedetailItemNotice.setOnClickListener {
|
||||
val index = gamedetailItemNotice.displayedChild
|
||||
DirectUtils.directToArticle(
|
||||
mContext,
|
||||
noticeList[index].id,
|
||||
StringUtils.buildString(mEntrance, "游戏详情[", mGameName, "]:公告")
|
||||
)
|
||||
val linkEntity = noticeList[index]
|
||||
DirectUtils.directToLinkPage(mContext, linkEntity, StringUtils.buildString(mEntrance, "游戏详情[", mGameName, "]:公告"), "")
|
||||
MtaHelper.onEvent(MTA_KEY_GAME_NEW, "详情_公告", "${mGameName}+${gamedetailItemNotice.notices[index]}")
|
||||
NewFlatLogUtils.logGameDetailNoticeClick(mGameId, mGameName, linkEntity.link ?: "", linkEntity.type ?: "", linkEntity.text ?: "")
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -755,8 +754,8 @@ class DescAdapter(
|
||||
sequence = index
|
||||
},
|
||||
source = listOf(
|
||||
ExposureSource("游戏详情", mGameName),
|
||||
ExposureSource("游戏单推荐", entity.id)
|
||||
ExposureSource("游戏详情", "$mGameName+$mGameId"),
|
||||
ExposureSource("游戏单", "${entity.title}+${entity.id}")
|
||||
)
|
||||
)
|
||||
exposureEventList.add(event)
|
||||
@ -765,7 +764,12 @@ class DescAdapter(
|
||||
|
||||
layoutManager = LinearLayoutManager(mContext, RecyclerView.HORIZONTAL, false)
|
||||
if (adapter == null) {
|
||||
adapter = GameCollectionAdapter(recommendGameList, mEntrance, "游戏详情[${mGameName}]:游戏单推荐")
|
||||
adapter = GameCollectionAdapter(
|
||||
recommendGameList,
|
||||
mEntrance,
|
||||
"游戏详情[${mGameName}]:游戏单推荐",
|
||||
listOf(ExposureSource("游戏详情", "$mGameName+$mGameId"))
|
||||
)
|
||||
} else {
|
||||
adapter?.notifyItemRangeChanged(0, itemCount)
|
||||
}
|
||||
|
||||
@ -25,6 +25,7 @@ import com.gh.gamecenter.core.utils.MtaHelper
|
||||
import com.gh.gamecenter.core.utils.SpanBuilder
|
||||
import com.gh.gamecenter.databinding.ItemGameDetailRatingCommentBinding
|
||||
import com.gh.gamecenter.entity.RatingComment
|
||||
import com.gh.gamecenter.feature.exposure.ExposureSource
|
||||
import com.gh.gamecenter.gamedetail.GameDetailFragment
|
||||
import com.gh.gamecenter.gamedetail.rating.RatingReplyActivity
|
||||
import com.gh.gamecenter.gamedetail.rating.edit.RatingEditActivity
|
||||
@ -165,12 +166,18 @@ class DescCommentsAdapter(
|
||||
isChildLongClick = false
|
||||
return@setOnClickListener
|
||||
}
|
||||
val exposureSource = arrayListOf(
|
||||
ExposureSource("游戏详情"),
|
||||
ExposureSource("详情tab"),
|
||||
ExposureSource("玩家评价"),
|
||||
).toJson()
|
||||
val intent = RatingReplyActivity.getIntent(
|
||||
mContext,
|
||||
mViewModel.game?.id ?: "",
|
||||
commentData.id,
|
||||
mEntrance,
|
||||
path
|
||||
context = mContext,
|
||||
gameId = mViewModel.game?.id ?: "",
|
||||
commentId = commentData.id,
|
||||
exposureSource = exposureSource,
|
||||
entrance = mEntrance,
|
||||
path = path
|
||||
)
|
||||
SyncDataBetweenPageHelper.startActivityForResult(mContext, intent, RATING_REPLY_REQUEST, position)
|
||||
MtaHelper.onEvent("游戏详情_新", "玩家评论_点击评论", mViewModel.game?.name)
|
||||
|
||||
@ -8,11 +8,14 @@ import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.utils.*
|
||||
import com.gh.gamecenter.databinding.GamedetailItemGameCollectionBinding
|
||||
import com.gh.gamecenter.entity.GameDetailRecommendGameEntity
|
||||
import com.gh.gamecenter.feature.exposure.ExposureEvent
|
||||
import com.gh.gamecenter.feature.exposure.ExposureSource
|
||||
|
||||
class GameCollectionAdapter(
|
||||
private val mRecommendGameList: ArrayList<GameDetailRecommendGameEntity>,
|
||||
private val mEntrance: String,
|
||||
private val mPath: String
|
||||
private val mPath: String,
|
||||
private val mBasicExposureSource: List<ExposureSource>
|
||||
) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
|
||||
|
||||
private val mDefaultHorizontalPadding by lazy { R.dimen.game_detail_item_horizontal_padding.toPx() }
|
||||
@ -43,7 +46,17 @@ class GameCollectionAdapter(
|
||||
}
|
||||
gameCountTv.text = "+${entity.count.game - games.size}"
|
||||
root.setOnClickListener {
|
||||
DirectUtils.directToGameCollectionDetail(it.context, entity.id, mEntrance, mPath)
|
||||
DirectUtils.directToGameCollectionDetail(
|
||||
it.context,
|
||||
entity.id,
|
||||
mEntrance,
|
||||
mPath,
|
||||
ExposureEvent.createEventWithSourceConcat(
|
||||
null,
|
||||
mBasicExposureSource,
|
||||
listOf(ExposureSource("游戏单", "${entity.title}+${entity.id}"))
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -118,6 +118,7 @@ class GameLibaoAdapter(
|
||||
holder.binding.libaoSchedulePb.visibility = View.VISIBLE
|
||||
holder.binding.remainingTv.visibility = View.VISIBLE
|
||||
holder.binding.libaoCodeTv.visibility = View.GONE
|
||||
holder.binding.copyLibaoCodeIv.visibility = View.GONE
|
||||
|
||||
initProgressUI(libaoEntity, holder)
|
||||
} else {
|
||||
@ -145,6 +146,7 @@ class GameLibaoAdapter(
|
||||
holder.binding.libaoSchedulePb.visibility = View.VISIBLE
|
||||
holder.binding.remainingTv.visibility = View.VISIBLE
|
||||
holder.binding.libaoCodeTv.visibility = View.GONE
|
||||
holder.binding.copyLibaoCodeIv.visibility = View.GONE
|
||||
|
||||
initProgressUI(libaoEntity, holder)
|
||||
}
|
||||
|
||||
@ -12,8 +12,8 @@ import kotlinx.parcelize.Parcelize
|
||||
@Keep
|
||||
class DetailEntity(
|
||||
var type: String = "",
|
||||
@SerializedName("notice")
|
||||
var noticeList: ArrayList<NoticeEntity>? = null,
|
||||
@SerializedName("new_notice")
|
||||
var noticeList: ArrayList<LinkEntity>? = null,
|
||||
var des: String? = null,// 介绍文案
|
||||
var gallery: ArrayList<String>? = null,
|
||||
@SerializedName("count")
|
||||
@ -122,17 +122,6 @@ class DetailEntity(
|
||||
}
|
||||
}
|
||||
|
||||
//公告文章
|
||||
@Keep
|
||||
class NoticeEntity(
|
||||
@SerializedName("_id")
|
||||
var id: String = "",
|
||||
var title: String = "",
|
||||
var type: String = "",
|
||||
var time: String = "",
|
||||
var overtime: String = ""
|
||||
)
|
||||
|
||||
@Keep
|
||||
class CustomColumn(
|
||||
@SerializedName("_id")
|
||||
|
||||
@ -57,7 +57,10 @@ class NewGameDetailEntity(
|
||||
@SerializedName("show_archive")
|
||||
var showArchive: Boolean = false, //云存档开关
|
||||
@SerializedName("archive_tab")
|
||||
var archiveTab: ArchiveTab = ArchiveTab()
|
||||
var archiveTab: ArchiveTab = ArchiveTab(),
|
||||
|
||||
@SerializedName("new_notice")
|
||||
var newNotice: ArrayList<LinkEntity>? = null,
|
||||
) {
|
||||
fun isShowContentCard(gameEntity: GameEntity?): Boolean {
|
||||
return contentCard.size > 1 && (gameEntity?.shouldUseMirrorInfo() == false || (gameEntity?.shouldUseMirrorInfo() == true && mirrorData?.contentCardStatus == "on"))
|
||||
|
||||
@ -10,14 +10,11 @@ import com.gh.common.util.*
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.viewholder.FooterViewHolder
|
||||
import com.gh.gamecenter.common.baselist.ListAdapter
|
||||
import com.gh.gamecenter.common.utils.copyTextAndToast
|
||||
import com.gh.gamecenter.common.utils.goneIf
|
||||
import com.gh.gamecenter.common.utils.ifLogin
|
||||
import com.gh.gamecenter.common.utils.setTextWithHighlightedTextWrappedInsideWrapper
|
||||
import com.gh.gamecenter.common.utils.TextHelper
|
||||
import com.gh.gamecenter.common.utils.*
|
||||
import com.gh.gamecenter.core.utils.*
|
||||
import com.gh.gamecenter.databinding.ItemMyGameRatingBinding
|
||||
import com.gh.gamecenter.feature.entity.TagStyleEntity
|
||||
import com.gh.gamecenter.feature.exposure.ExposureSource
|
||||
import com.gh.gamecenter.gamedetail.rating.RatingReplyActivity
|
||||
import com.gh.gamecenter.gamedetail.rating.edit.RatingEditActivity
|
||||
import com.gh.gamecenter.personalhome.rating.MyRating
|
||||
@ -112,7 +109,7 @@ class MyRatingAdapter(
|
||||
holder.binding.apply {
|
||||
gameInfo.setOnClickListener {
|
||||
MtaHelper.onEvent("我的光环_新", "我的游戏评论", "游戏详情")
|
||||
DirectUtils.directToGameDetail(mContext, rating.game.id, "我的游戏评论")
|
||||
DirectUtils.directToGameDetail(mContext, rating.game.id, entrance = "我的游戏评论")
|
||||
}
|
||||
commentInfo.setOnClickListener {
|
||||
if (isChildLongClick) {
|
||||
@ -121,7 +118,13 @@ class MyRatingAdapter(
|
||||
}
|
||||
MtaHelper.onEvent("我的光环_新", "我的游戏评论", "评论详情")
|
||||
val intent =
|
||||
RatingReplyActivity.getIntent(mContext, rating.game.id, rating.id, false, "我的游戏评论", "")
|
||||
RatingReplyActivity.getIntent(
|
||||
context = mContext,
|
||||
gameId = rating.game.id,
|
||||
commentId = rating.id,
|
||||
showKeyboardIfReplyListIsEmpty = false,
|
||||
entrance = "我的游戏评论",
|
||||
path = "")
|
||||
/* if(!rating.active){
|
||||
intent = RatingReplyActivity.getIntent(mContext, rating.transformGameEntity(), rating.transformCommentEntity(), "我的游戏评论", "")
|
||||
}else if(!rating.game.active){
|
||||
|
||||
@ -26,6 +26,7 @@ import com.gh.gamecenter.databinding.RatingItemBinding
|
||||
import com.gh.gamecenter.entity.Rating
|
||||
import com.gh.gamecenter.entity.RatingComment
|
||||
import com.gh.gamecenter.entity.Star
|
||||
import com.gh.gamecenter.feature.exposure.ExposureSource
|
||||
import com.gh.gamecenter.gamedetail.rating.edit.RatingEditActivity
|
||||
import com.lightgame.utils.Utils
|
||||
|
||||
@ -475,11 +476,20 @@ class RatingAdapter(
|
||||
}
|
||||
PageSwitchDataHelper.pushCurrentPageData(pageData)
|
||||
|
||||
val intent = if (isOpenKeyboard) {
|
||||
RatingReplyActivity.getOpenKeyboardIntent(mContext, mListViewModel.game, commentData, mEntrance, path)
|
||||
} else {
|
||||
RatingReplyActivity.getIntent(mContext, mListViewModel.game.id, commentData.id, mEntrance, path)
|
||||
}
|
||||
val exposureSource = arrayListOf(
|
||||
ExposureSource("游戏详情"),
|
||||
ExposureSource("评价tab"),
|
||||
).toJson()
|
||||
|
||||
val intent = RatingReplyActivity.getIntent(
|
||||
context = mContext,
|
||||
gameId = mListViewModel.game.id,
|
||||
commentId = commentData.id,
|
||||
forcedShowKeyboard = isOpenKeyboard,
|
||||
exposureSource = exposureSource,
|
||||
entrance = mEntrance,
|
||||
path = path
|
||||
)
|
||||
SyncDataBetweenPageHelper.startActivityForResult(
|
||||
mContext,
|
||||
intent,
|
||||
|
||||
@ -34,6 +34,7 @@ import com.gh.gamecenter.entity.RatingComment
|
||||
import com.gh.gamecenter.entity.RatingReplyEntity
|
||||
import com.gh.gamecenter.eventbus.EBDownloadStatus
|
||||
import com.gh.gamecenter.eventbus.EBPackage
|
||||
import com.gh.gamecenter.feature.exposure.ExposureSource
|
||||
import com.lightgame.download.DataWatcher
|
||||
import com.lightgame.download.DownloadEntity
|
||||
import com.lightgame.download.DownloadStatus
|
||||
@ -90,7 +91,10 @@ class RatingReplyActivity : ListActivity<RatingReplyEntity, RatingReplyViewModel
|
||||
|
||||
override fun provideListAdapter(): RatingReplyAdapter {
|
||||
if (mAdapter == null) {
|
||||
mAdapter = RatingReplyAdapter(this, mEntrance, mListViewModel, replyCallback = {
|
||||
val exposureSourceList: ArrayList<ExposureSource>? =
|
||||
intent.getStringExtra(EntranceConsts.KEY_EXPOSURE_SOURCE)?.toObject()
|
||||
|
||||
mAdapter = RatingReplyAdapter(this, mEntrance, mListViewModel, exposureSourceList, replyCallback = {
|
||||
if (it != null) {
|
||||
mInputBinding.answerCommentEt.hint = "回复 @${it.user.name}"
|
||||
} else {
|
||||
@ -196,14 +200,9 @@ class RatingReplyActivity : ListActivity<RatingReplyEntity, RatingReplyViewModel
|
||||
}
|
||||
}
|
||||
|
||||
TextHelper.limitTheLengthOfEditText(
|
||||
mInputBinding.answerCommentEt,
|
||||
140,
|
||||
object : TextHelper.ExceedTextLengthLimitCallback {
|
||||
override fun onExceed() {
|
||||
toast("最多140个字")
|
||||
}
|
||||
})
|
||||
TextHelper.limitTheLengthOfEditText(mInputBinding.answerCommentEt, 140) {
|
||||
toast("最多140个字")
|
||||
}
|
||||
|
||||
if (intent?.getBooleanExtra(EntranceConsts.KEY_OPEN_KEYBOARD, false) == true) {
|
||||
popInputLayout(true)
|
||||
@ -413,106 +412,83 @@ class RatingReplyActivity : ListActivity<RatingReplyEntity, RatingReplyViewModel
|
||||
}
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
fun getIntent(
|
||||
context: Context,
|
||||
game: GameEntity,
|
||||
comment: RatingComment,
|
||||
entrance: String,
|
||||
path: String
|
||||
): Intent {
|
||||
val intent = Intent(context, RatingReplyActivity::class.java)
|
||||
intent.putExtra(EntranceConsts.KEY_ENTRANCE, mergeEntranceAndPath(entrance, path))
|
||||
intent.putExtra(GameEntity::class.java.simpleName, game)
|
||||
intent.putExtra(RatingComment::class.java.simpleName, comment)
|
||||
return intent
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
/**
|
||||
* 获取评论详情的 Intent
|
||||
* @param showKeyboardIfReplyListIsEmpty 当回复列表为空时弹起软键盘
|
||||
* @param forcedShowKeyboard 默认弹起软键盘
|
||||
*/
|
||||
fun getIntent(
|
||||
context: Context,
|
||||
gameId: String,
|
||||
comment: RatingComment,
|
||||
showKeyboardIfReplyListIsEmpty: Boolean,
|
||||
gameEntity: GameEntity? = null,
|
||||
commentId: String,
|
||||
comment: RatingComment? = null,
|
||||
topCommentId: String? = null,
|
||||
showKeyboardIfReplyListIsEmpty: Boolean = false,
|
||||
forcedShowKeyboard: Boolean = false,
|
||||
exposureSource: String? = null,
|
||||
entrance: String,
|
||||
path: String
|
||||
): Intent {
|
||||
val intent = Intent(context, RatingReplyActivity::class.java)
|
||||
intent.putExtra(EntranceConsts.KEY_ENTRANCE, mergeEntranceAndPath(entrance, path))
|
||||
intent.putExtra(EntranceConsts.KEY_GAMEID, gameId)
|
||||
intent.putExtra(RatingComment::class.java.simpleName, comment)
|
||||
if (gameEntity != null) {
|
||||
intent.putExtra(GameEntity::class.java.simpleName, gameEntity)
|
||||
}
|
||||
intent.putExtra(EntranceConsts.KEY_COMMENTID, commentId)
|
||||
if (comment != null) {
|
||||
intent.putExtra(RatingComment::class.java.simpleName, comment)
|
||||
}
|
||||
intent.putExtra(EntranceConsts.KEY_SHOW_KEYBOARD_IF_NEEDED, showKeyboardIfReplyListIsEmpty)
|
||||
intent.putExtra(EntranceConsts.KEY_OPEN_KEYBOARD, forcedShowKeyboard)
|
||||
if (topCommentId != null) {
|
||||
intent.putExtra(EntranceConsts.KEY_TOP_COMMENT_ID, topCommentId)
|
||||
}
|
||||
intent.putExtra(EntranceConsts.KEY_EXPOSURE_SOURCE, exposureSource)
|
||||
return intent
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun getIntent(
|
||||
context: Context,
|
||||
gameId: String,
|
||||
commentId: String,
|
||||
entrance: String,
|
||||
path: String
|
||||
): Intent {
|
||||
return getIntent(context, gameId, commentId, "", false, entrance, path)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun getIntent(
|
||||
context: Context,
|
||||
gameId: String,
|
||||
commentId: String,
|
||||
showKeyboardIfReplyListIsEmpty: Boolean,
|
||||
entrance: String,
|
||||
path: String
|
||||
): Intent {
|
||||
return getIntent(context, gameId, commentId, "", showKeyboardIfReplyListIsEmpty, entrance, path)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun getSpecifiedCommentIntent(
|
||||
context: Context,
|
||||
gameId: String,
|
||||
commentId: String,
|
||||
topCommentId: String,
|
||||
exposureSource: ExposureSource,
|
||||
entrance: String,
|
||||
path: String
|
||||
): Intent {
|
||||
return getIntent(context, gameId, commentId, topCommentId, false, entrance, path)
|
||||
return getIntent(
|
||||
context = context,
|
||||
gameId = gameId,
|
||||
commentId = commentId,
|
||||
topCommentId = topCommentId,
|
||||
exposureSource = arrayListOf(exposureSource).toJson(),
|
||||
showKeyboardIfReplyListIsEmpty = false,
|
||||
entrance = entrance,
|
||||
path = path
|
||||
)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun getIntent(
|
||||
fun getSimpleIntent(
|
||||
context: Context,
|
||||
gameId: String,
|
||||
commentId: String,
|
||||
topCommentId: String,
|
||||
showKeyboardIfReplyListIsEmpty: Boolean,
|
||||
commentId: String?,
|
||||
exposureSource: ExposureSource,
|
||||
entrance: String,
|
||||
path: String
|
||||
): Intent {
|
||||
val intent = Intent(context, RatingReplyActivity::class.java)
|
||||
intent.putExtra(EntranceConsts.KEY_ENTRANCE, mergeEntranceAndPath(entrance, path))
|
||||
intent.putExtra(EntranceConsts.KEY_GAMEID, gameId)
|
||||
intent.putExtra(EntranceConsts.KEY_COMMENTID, commentId)
|
||||
intent.putExtra(EntranceConsts.KEY_TOP_COMMENT_ID, topCommentId)
|
||||
intent.putExtra(EntranceConsts.KEY_SHOW_KEYBOARD_IF_NEEDED, showKeyboardIfReplyListIsEmpty)
|
||||
return intent
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun getOpenKeyboardIntent(
|
||||
context: Context,
|
||||
game: GameEntity,
|
||||
comment: RatingComment,
|
||||
entrance: String,
|
||||
path: String
|
||||
): Intent {
|
||||
val intent = Intent(context, RatingReplyActivity::class.java)
|
||||
intent.putExtra(EntranceConsts.KEY_ENTRANCE, mergeEntranceAndPath(entrance, path))
|
||||
intent.putExtra(GameEntity::class.java.simpleName, game)
|
||||
intent.putExtra(RatingComment::class.java.simpleName, comment)
|
||||
intent.putExtra(EntranceConsts.KEY_OPEN_KEYBOARD, true)
|
||||
return intent
|
||||
return getIntent(
|
||||
context = context,
|
||||
gameId = gameId,
|
||||
commentId = commentId ?: "unknown",
|
||||
exposureSource = arrayListOf(exposureSource).toJson(),
|
||||
entrance = entrance,
|
||||
path = path
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -49,6 +49,7 @@ class RatingReplyAdapter(
|
||||
context: Context,
|
||||
val entrance: String,
|
||||
val viewModel: RatingReplyViewModel,
|
||||
private val mExposureSourceList: ArrayList<ExposureSource>?,
|
||||
val replyCallback: (RatingReplyEntity?) -> Unit
|
||||
) : ListAdapter<RatingReplyItem>(context), IExposable {
|
||||
|
||||
@ -58,6 +59,10 @@ class RatingReplyAdapter(
|
||||
private val path = "评论详情"
|
||||
private var mExposureEvent: ExposureEvent? = null
|
||||
|
||||
init {
|
||||
mExposureSourceList?.add(ExposureSource("评论详情", ""))
|
||||
}
|
||||
|
||||
override fun setListData(updateData: MutableList<RatingReplyItem>?) {
|
||||
if (mEntityList.size > 0 && mEntityList[mEntityList.size - 1].reply == null
|
||||
&& updateData != null && updateData.size > 0 && updateData[updateData.size - 1].reply != null
|
||||
@ -105,22 +110,27 @@ class RatingReplyAdapter(
|
||||
view = mLayoutInflater.inflate(R.layout.rating_reply_head_item, parent, false)
|
||||
RatingReplyHeadItemViewHolder(RatingReplyHeadItemBinding.bind(view))
|
||||
}
|
||||
|
||||
ITEM_COMMENT -> {
|
||||
view = mLayoutInflater.inflate(R.layout.item_article_detail_comment, parent, false)
|
||||
RatingDetailCommentItemViewHolder(ItemArticleDetailCommentBinding.bind(view))
|
||||
}
|
||||
|
||||
ITEM_SECTION_TITLE -> {
|
||||
view = mLayoutInflater.inflate(R.layout.piece_article_detail_comment_filter, parent, false)
|
||||
ListSectionItemViewHolder(PieceArticleDetailCommentFilterBinding.bind(view))
|
||||
}
|
||||
|
||||
ItemViewType.ITEM_BODY -> {
|
||||
view = mLayoutInflater.inflate(R.layout.item_article_detail_comment, parent, false)
|
||||
RatingReplyItemViewHolder(ItemArticleDetailCommentBinding.bind(view))
|
||||
}
|
||||
|
||||
ItemViewType.ITEM_FOOTER -> {
|
||||
view = mLayoutInflater.inflate(R.layout.refresh_footerview, parent, false)
|
||||
FooterViewHolder(view)
|
||||
}
|
||||
|
||||
else -> {
|
||||
throw IllegalStateException("item view type not found")
|
||||
}
|
||||
@ -135,12 +145,12 @@ class RatingReplyAdapter(
|
||||
when (holder) {
|
||||
is RatingReplyHeadItemViewHolder -> {
|
||||
val game = mEntityList[position].game!!
|
||||
val exposureSource = if (entrance.contains("安利墙")) {
|
||||
listOf(ExposureSource("安利墙", ""), ExposureSource("评论详情", ""))
|
||||
} else {
|
||||
listOf(ExposureSource("其他", ""), ExposureSource("评论详情", ""))
|
||||
}
|
||||
mExposureEvent = ExposureEvent.createEvent(game, exposureSource)
|
||||
// 构造 exposureSource
|
||||
val exposureSourceList = mExposureSourceList
|
||||
?: listOf(ExposureSource("其他", ""), ExposureSource("评论详情", ""))
|
||||
mExposureEvent = ExposureEvent.createEvent(game, exposureSourceList)
|
||||
// 记录评论 id
|
||||
mExposureEvent?.payload?.controlLinkDesc = viewModel.commentId
|
||||
holder.binding.gameIcon.displayGameIcon(game)
|
||||
holder.binding.gameName.text = game.name
|
||||
holder.binding.gameInfo.text = if (!game.getApk()
|
||||
@ -189,6 +199,7 @@ class RatingReplyAdapter(
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
is RatingDetailCommentItemViewHolder -> {
|
||||
val commentData = mEntityList[position].comment!!
|
||||
holder.setContent(commentData, viewModel, position, entrance, path)
|
||||
@ -232,6 +243,7 @@ class RatingReplyAdapter(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
is RatingReplyItemViewHolder -> {
|
||||
val replyEntity = mEntityList[position].reply!!
|
||||
holder.binding.run {
|
||||
@ -411,6 +423,7 @@ class RatingReplyAdapter(
|
||||
).copyTextAndToast()
|
||||
logGameDetailCommentDetailCommentClick("回复右上角-复制")
|
||||
}
|
||||
|
||||
"投诉" -> {
|
||||
mContext.ifLogin("游戏详情-评分-评论详情- 投诉评论") {
|
||||
DialogUtils.showReportReasonDialog(
|
||||
@ -427,6 +440,7 @@ class RatingReplyAdapter(
|
||||
}
|
||||
logGameDetailCommentDetailCommentClick("回复右上角-投诉")
|
||||
}
|
||||
|
||||
"删除" -> {
|
||||
DialogHelper.showDeleteGameCommentDialog(
|
||||
mContext,
|
||||
@ -493,6 +507,7 @@ class RatingReplyAdapter(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
is ListSectionItemViewHolder -> {
|
||||
holder.binding.run {
|
||||
root.setRootBackgroundColor(R.color.background_white)
|
||||
@ -521,6 +536,7 @@ class RatingReplyAdapter(
|
||||
viewModel.sortList(RatingReplyViewModel.SORT_POSITIVE)
|
||||
logGameDetailCommentDetailCommentClick("正序")
|
||||
}
|
||||
|
||||
1 -> {
|
||||
viewModel.sortList(RatingReplyViewModel.SORT_NEGATION)
|
||||
logGameDetailCommentDetailCommentClick("倒序")
|
||||
@ -529,6 +545,7 @@ class RatingReplyAdapter(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
is FooterViewHolder -> {
|
||||
holder.itemView.setBackgroundColor(R.color.background_white.toColor(mContext))
|
||||
when {
|
||||
@ -538,16 +555,19 @@ class RatingReplyAdapter(
|
||||
holder.itemView.isClickable = true
|
||||
holder.itemView.setOnClickListener { viewModel.load(LoadType.RETRY) }
|
||||
}
|
||||
|
||||
mIsLoading -> {
|
||||
holder.loading.visibility = View.VISIBLE
|
||||
holder.hint.setText(R.string.loading)
|
||||
holder.itemView.isClickable = false
|
||||
}
|
||||
|
||||
mIsOver && mEntityList.size > 2 && mEntityList[2].replyCount != null -> {
|
||||
holder.loading.visibility = View.GONE
|
||||
holder.hint.setText(R.string.load_over_hint)
|
||||
holder.itemView.isClickable = false
|
||||
}
|
||||
|
||||
mIsOver -> {
|
||||
holder.loading.visibility = View.GONE
|
||||
holder.hint.text = "这里还没有回复,说点什么吧~"
|
||||
@ -556,6 +576,7 @@ class RatingReplyAdapter(
|
||||
replyCallback.invoke(null)
|
||||
}
|
||||
}
|
||||
|
||||
else -> {
|
||||
holder.loading.visibility = View.GONE
|
||||
holder.hint.setText(R.string.loading_more_hint)
|
||||
|
||||
@ -20,6 +20,7 @@ import com.gh.gamecenter.common.constant.ItemViewType
|
||||
import com.gh.gamecenter.common.utils.dip2px
|
||||
import com.gh.gamecenter.common.utils.safelyGetInRelease
|
||||
import com.gh.gamecenter.common.utils.toBinding
|
||||
import com.gh.gamecenter.common.utils.toJson
|
||||
import com.gh.gamecenter.common.viewholder.FooterViewHolder
|
||||
import com.gh.gamecenter.core.runOnIoThread
|
||||
import com.gh.gamecenter.entity.AmwayCommentEntity
|
||||
@ -294,13 +295,15 @@ class HomeFragmentAdapter(
|
||||
val path = "(首页安利墙)"
|
||||
when (v.id) {
|
||||
R.id.rating_block -> {
|
||||
val exposureSource = arrayListOf(ExposureSource("新首页"), ExposureSource("安利墙")).toJson()
|
||||
val intent = RatingReplyActivity.getIntent(
|
||||
mContext,
|
||||
amway.game.id,
|
||||
amway.comment.id,
|
||||
false,
|
||||
path,
|
||||
""
|
||||
context = mContext,
|
||||
gameId = amway.game.id,
|
||||
commentId = amway.comment.id,
|
||||
showKeyboardIfReplyListIsEmpty = false,
|
||||
exposureSource = exposureSource,
|
||||
entrance = path,
|
||||
path = ""
|
||||
)
|
||||
mContext.startActivity(intent)
|
||||
NewLogUtils.logHomeShareWallCardClick(amway.game.name ?: "", amway.game.id, "评论内容")
|
||||
@ -353,7 +356,7 @@ class HomeFragmentAdapter(
|
||||
}
|
||||
}
|
||||
homeItemData.exposureEventList = exposureList
|
||||
holder.bindGameCollectionList(gameCollectionItemDataList, "首页内容列表")
|
||||
holder.bindGameCollectionList(gameCollectionItemDataList, "首页内容列表", mBasicExposureSource)
|
||||
}
|
||||
|
||||
private fun bindRecentVGame(holder: HomeRecentVGameViewHolder, position: Int) {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user