Compare commits
126 Commits
v5.24.3-83
...
v5.25.2-58
| Author | SHA1 | Date | |
|---|---|---|---|
| 33a5e2061f | |||
| b62b1f399c | |||
| c4449db90a | |||
| 6edd9f2204 | |||
| 8508b9ece2 | |||
| 20d5ef7a6e | |||
| ff70d7a48a | |||
| 4bc2374cb4 | |||
| 8efa858a01 | |||
| 53e2297976 | |||
| 9cd5e342ac | |||
| 26dfb79ece | |||
| 7bc36814b7 | |||
| b29651ecfb | |||
| 74aad0e7e0 | |||
| 52a5faacfe | |||
| 5cee489ba6 | |||
| f76c3e3638 | |||
| 386a7f82d9 | |||
| 94983c4b7f | |||
| 119cdf4f91 | |||
| bde7685dc6 | |||
| 6acaa95098 | |||
| 610f116b82 | |||
| fe616ed87b | |||
| 91ba665c4c | |||
| f05b20ed98 | |||
| 74d3e8b2d4 | |||
| 74364cd452 | |||
| dc2a023fbb | |||
| 47560daec6 | |||
| 657b900418 | |||
| d826c3dcce | |||
| 935d61f910 | |||
| 0a412feefb | |||
| 31111a1cc8 | |||
| cf901ef840 | |||
| 8d70716f15 | |||
| 7cf086874a | |||
| d1698f0c2d | |||
| f80bcbcfb9 | |||
| 2ea9d46e12 | |||
| 65445859d3 | |||
| 8c9927b9cb | |||
| 5477a4a4cc | |||
| 3ff4a9b6cf | |||
| 174f47edb1 | |||
| 96fbe30924 | |||
| 954c7e427a | |||
| e466eb6683 | |||
| 01437e9d8a | |||
| eac553ba46 | |||
| 81d5a8a12c | |||
| 192ae916de | |||
| 5047ae5f9c | |||
| f5a30a7dde | |||
| e9c22ef577 | |||
| 8292d8512d | |||
| a606633755 | |||
| 9788b632d6 | |||
| 0a8211d40b | |||
| c16407e360 | |||
| b7ca5c54a3 | |||
| d42a915ef5 | |||
| 91c1e8fcef | |||
| da40da432f | |||
| 6a03b63e65 | |||
| 224c17c582 | |||
| 64a35316cb | |||
| 78207eb0cb | |||
| c3b9b52f5d | |||
| 586af43050 | |||
| 50510b808f | |||
| d46ef9f068 | |||
| 293561d807 | |||
| 4c64137e9a | |||
| 57e57c19d0 | |||
| 475b03d591 | |||
| a97091bf49 | |||
| 7a12c4ab1d | |||
| 4f732c3921 | |||
| 531deacc3d | |||
| b219e60f13 | |||
| 387fc37b19 | |||
| 1b88c3e0a3 | |||
| af1c7ff2c9 | |||
| 976f315ba8 | |||
| 216c13054b | |||
| 3fd4d330d2 | |||
| f811759bf4 | |||
| 6efc5bb4fa | |||
| 754d7f58c0 | |||
| dc39f9f207 | |||
| 65c46c2eb4 | |||
| 40e30058f9 | |||
| 432f8dc090 | |||
| ea68931461 | |||
| e6a2f0528a | |||
| 71f2c937db | |||
| 2a8ae9a022 | |||
| 3f28fcc211 | |||
| dd850bdbbc | |||
| 6ae8b520ac | |||
| d956081d61 | |||
| fe75be35fb | |||
| 15d6fd98b5 | |||
| d1d22de559 | |||
| 2f69074418 | |||
| 684e7a63db | |||
| 208c21c4ea | |||
| 55c8fd9271 | |||
| 664f35090d | |||
| aaec370afa | |||
| af09f28fdd | |||
| 00b92d2aec | |||
| a90d694a48 | |||
| 03babbfdee | |||
| 32cf945b4d | |||
| 207813376b | |||
| 98a54ad85d | |||
| fc0a36e4b8 | |||
| a3a68d7550 | |||
| 572400a3c7 | |||
| 8b42390175 | |||
| ad71193089 | |||
| f631810acc |
180
.gitlab-ci.yml
180
.gitlab-ci.yml
@ -1,43 +1,155 @@
|
||||
stages:
|
||||
- analysis
|
||||
- sendmail
|
||||
# commit_sha 文件记录上一次成功流水线的commit sha,用于定时计划检测是否有新代码提交,有就执行流水线,没有就终止流水线
|
||||
cache:
|
||||
# 不同的分支采用不同的 cache,防止分支之间相互影响
|
||||
key: "${CI_COMMIT_REF_SLUG}_commit_sha"
|
||||
paths:
|
||||
- commit_sha
|
||||
policy: pull
|
||||
|
||||
## 代码检查
|
||||
# 将打包&发送apk包邮件job 和代码分析job 并行执行
|
||||
stages:
|
||||
- build&analyze
|
||||
- oss-upload&send-email
|
||||
- ci_sonar_mail
|
||||
|
||||
# 阻止了 合并请求 或 push(分支和标签)的流水线。 最后的 when: always 规则运行所有其他流水线类型,包括定时计划流水线。
|
||||
workflow:
|
||||
rules:
|
||||
- if: '$CI_PIPELINE_SOURCE == "push"'
|
||||
when: always
|
||||
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
|
||||
when: never
|
||||
- when: always
|
||||
|
||||
before_script:
|
||||
# 检查是否存在 commit_sha 文件
|
||||
- if [ -f commit_sha ]; then cat commit_sha; else echo "0000000" > commit_sha; fi
|
||||
- export BEFORE_COMMIT_SHA=$(cat commit_sha)
|
||||
# 比较commit sha ,若与上一次成功流水线的commit sha 相同,则退出流水线
|
||||
- if [ "$CI_COMMIT_SHA" == "$BEFORE_COMMIT_SHA" ] && [ "$CI_PIPELINE_SOURCE" != "web" ]; then exit 137; fi
|
||||
|
||||
# 使用 .post 阶段使作业在流水线的末尾运行。.post 始终是流水线的最后阶段。
|
||||
change_commit:
|
||||
tags:
|
||||
- offline-test
|
||||
stage: .post
|
||||
# 此job 跳过拉取git代码
|
||||
variables:
|
||||
GIT_STRATEGY: none
|
||||
script:
|
||||
# 更新 commit_sha
|
||||
- if [ "$CI_COMMIT_SHA" != "$BEFORE_COMMIT_SHA" ]; then echo $CI_COMMIT_SHA > commit_sha; fi
|
||||
cache:
|
||||
# 不同的分支采用不同的 cache,防止分支之间相互影响
|
||||
key: "${CI_COMMIT_REF_SLUG}_commit_sha"
|
||||
paths:
|
||||
- commit_sha
|
||||
policy: pull-push
|
||||
allow_failure:
|
||||
exit_codes: 137
|
||||
|
||||
android_build:
|
||||
tags:
|
||||
# - local-runner
|
||||
- offline-test
|
||||
stage: build&analyze
|
||||
image: hub.shanqu.cc/library/ci-android:jdk11-sdk31-33
|
||||
resource_group: android_build
|
||||
variables:
|
||||
GIT_SUBMODULE_STRATEGY: recursive
|
||||
KUBERNETES_CPU_LIMIT: "10"
|
||||
script:
|
||||
- export GRADLE_USER_HOME=/home/gitlab-runner/ci-build-cache/$CI_PROJECT_PATH/.gradle
|
||||
- chmod +x ./gradlew
|
||||
- ./scripts/jenkins_build.sh -c
|
||||
#设置打包后的产物,用于job之间共享
|
||||
artifacts:
|
||||
paths:
|
||||
- app/build/tmp/*.apk
|
||||
expire_in: 48 hrs # 指定附件上载后保存的时间24h,默认永久在Gitlab保存
|
||||
allow_failure:
|
||||
exit_codes: 137
|
||||
only:
|
||||
- dev
|
||||
- dev-5.25.0
|
||||
|
||||
# 代码检查
|
||||
sonarqube_analysis:
|
||||
tags:
|
||||
- offline-test
|
||||
stage: analysis
|
||||
image: sonarsource/sonar-scanner-cli:latest
|
||||
dependencies: [] #禁止传递来的artifact
|
||||
script:
|
||||
## 获取项目的一级组和二级组和项目名作为projectKey,例如projectKey=platform-backend-eci-monitor
|
||||
- group=`echo $CI_PROJECT_PATH | sed 's#/#-#g'`
|
||||
- sonar-scanner
|
||||
-Dsonar.host.url=http://sonarqube-server.sonarqube:9000/
|
||||
-Dsonar.login=be43de7264ce4c4766eb0c020373c3e74e6df257
|
||||
-Dsonar.jacoco.reportPaths=target/jacoco.exec
|
||||
-Dsonar.projectKey=$group
|
||||
-Dsonar.projectName=$CI_PROJECT_PATH
|
||||
-Dsonar.sourceEncoding=UTF-8
|
||||
-Dsonar.exclusions=**/vendor/**,**/errcode/**
|
||||
-Dsonar.gitlab.project_id=$CI_PROJECT_ID
|
||||
-Dsonar.gitlab.commit_sha=$CI_COMMIT_SHA
|
||||
-Dsonar.gitlab.ref_name=$CI_COMMIT_REF_NAME
|
||||
-Dsonar.gitlab.ci_merge_request_iid=$CI_MERGE_REQUEST_IID
|
||||
-Dsonar.gitlab.merge_request_discussion=true
|
||||
-Dsonar.java.binaries=. # 如果不使用Maven或Gradle进行分析,则必须手动提供测试二进制文件
|
||||
only:
|
||||
- dev
|
||||
tags:
|
||||
- offline-test
|
||||
stage: build&analyze
|
||||
image: sonarsource/sonar-scanner-cli:latest
|
||||
dependencies: [] #禁止传递来的artifact
|
||||
script:
|
||||
## 获取项目的一级组和二级组和项目名作为projectKey,例如projectKey=platform-backend-eci-monitor
|
||||
- group=`echo $CI_PROJECT_PATH | sed 's#/#-#g'`
|
||||
- sonar-scanner
|
||||
-Dsonar.host.url=http://sonarqube-server.sonarqube:9000/
|
||||
-Dsonar.login=be43de7264ce4c4766eb0c020373c3e74e6df257
|
||||
-Dsonar.jacoco.reportPaths=target/jacoco.exec
|
||||
-Dsonar.projectKey=$group
|
||||
-Dsonar.projectName=$CI_PROJECT_PATH
|
||||
-Dsonar.sourceEncoding=UTF-8
|
||||
-Dsonar.exclusions=**/vendor/**,**/errcode/**
|
||||
-Dsonar.gitlab.project_id=$CI_PROJECT_ID
|
||||
-Dsonar.gitlab.commit_sha=$CI_COMMIT_SHA
|
||||
-Dsonar.gitlab.ref_name=$CI_COMMIT_REF_NAME
|
||||
-Dsonar.gitlab.ci_merge_request_iid=$CI_MERGE_REQUEST_IID
|
||||
-Dsonar.gitlab.merge_request_discussion=true
|
||||
-Dsonar.java.binaries=.
|
||||
-Dsonar.branch.name=$CI_COMMIT_REF_NAME
|
||||
allow_failure:
|
||||
exit_codes: 137
|
||||
only:
|
||||
- dev
|
||||
- dev-5.25.0
|
||||
|
||||
## 发送简易检测结果报告
|
||||
send_sonar_report:
|
||||
tags:
|
||||
- offline-test
|
||||
stage: ci_sonar_mail
|
||||
image: hub.shanqu.cc/library/docker:latest
|
||||
# 此job 跳过拉取git代码
|
||||
variables:
|
||||
GIT_STRATEGY: none
|
||||
script:
|
||||
- group=`echo $CI_PROJECT_PATH | sed 's#/#-#g'`
|
||||
- docker run -e PROJECTKEY=$group -e EMAIL=$GITLAB_USER_EMAIL -e BRANCH=$CI_COMMIT_REF_NAME --name send-email --rm hub.shanqu.cc/platform/send-sonar-report:latest
|
||||
allow_failure:
|
||||
exit_codes: 137
|
||||
only:
|
||||
- dev
|
||||
- dev-5.25.0
|
||||
|
||||
oss-upload&send-email:
|
||||
tags:
|
||||
- offline-test
|
||||
stage: sendmail
|
||||
image: hub.shanqu.cc/library/docker:latest
|
||||
dependencies: [] #禁止传递来的artifact
|
||||
- rancher-k8s
|
||||
stage: oss-upload&send-email
|
||||
image: hub.shanqu.cc/devops/android-apk-oss-upload:latest
|
||||
variables:
|
||||
GIT_STRATEGY: none
|
||||
VAULT_ADDR: https://vault.shanqu.cc # 固定值
|
||||
VAULT_SECRET_PATH: prod/devops/android-apk-oss-upload # 固定值
|
||||
VAULT_ROLE: android-apk-oss-upload # 固定值
|
||||
ENDPOINT: "oss-cn-shenzhen-internal.aliyuncs.com" # 固定值
|
||||
BUCKET: "shanqu" # 固定值
|
||||
FILE_PATH: "app/build/tmp/" # APK 存放路径
|
||||
Email_To_List: $EMAIL_TO_LIST # 邮件接受人列表
|
||||
Email_Title: "光环助手 $CI_COMMIT_BRANCH" # 邮件标题
|
||||
PIPELINE_ID: $CI_PIPELINE_ID # 流水线id
|
||||
COMMIT_BRANCH: $CI_COMMIT_BRANCH # 提交分支
|
||||
MAIL_MESSAGE: "[$CI_COMMIT_AUTHOR] $CI_COMMIT_MESSAGE"
|
||||
needs:
|
||||
- job: android_build
|
||||
artifacts: true
|
||||
script:
|
||||
- group=`echo $CI_PROJECT_PATH | sed 's#/#-#g'`
|
||||
- docker run -e PROJECTKEY=$group -e EMAIL=$GITLAB_USER_EMAIL --name send-email --rm hub.shanqu.cc/platform/send-sonar-report:latest
|
||||
### 绑定上传参数 ###
|
||||
- export OSS_PATH="release/dev/${CI_PROJECT_NAME}/$(date "+%Y/%m/%d")"
|
||||
### 开启上传 ###
|
||||
- /usr/local/bin/python /upload.py
|
||||
### 发送邮件
|
||||
- /usr/local/bin/python /ci-android-mail.py
|
||||
only:
|
||||
- dev
|
||||
- dev-5.25.0
|
||||
|
||||
@ -11,6 +11,7 @@ android {
|
||||
|
||||
String CONFIG_ID = ""
|
||||
String FIRST_LAUNCH = ""
|
||||
int ACTIVATE_REPORTING_RATIO = 0
|
||||
|
||||
buildFeatures {
|
||||
viewBinding true
|
||||
@ -76,6 +77,8 @@ android {
|
||||
// 首次启动的跳转配置
|
||||
buildConfigField "String", "FIRST_LAUNCH", "\"${FIRST_LAUNCH}\""
|
||||
|
||||
buildConfigField "int", "ACTIVATE_REPORTING_RATIO", "${ACTIVATE_REPORTING_RATIO}"
|
||||
|
||||
// All third-party appid/appkey
|
||||
buildConfigField "String", "API_HOST", "\"${API_HOST}\""
|
||||
buildConfigField "String", "NEW_API_HOST", "\"${NEW_API_HOST}\""
|
||||
@ -294,7 +297,6 @@ dependencies {
|
||||
|
||||
implementation "com.lg:shortcut:${shortcut}"
|
||||
|
||||
compileOnly "com.github.axen1314.lancet:lancet-base:${lancet_version}"
|
||||
kapt "com.alibaba:arouter-compiler:$arouterVersion"
|
||||
|
||||
implementation project(':ndownload')
|
||||
@ -321,9 +323,10 @@ dependencies {
|
||||
implementation(project(':module_sensors_data')) {
|
||||
exclude group: 'androidx.swiperefreshlayout'
|
||||
}
|
||||
// implementation(project(':module_vpn'))
|
||||
implementation(project(':module_pkg'))
|
||||
// implementation(project(':feature:vpn'))
|
||||
implementation(project(':feature:pkg'))
|
||||
implementation(project(':feature:floating-window'))
|
||||
implementation(project(':feature:beizi_startup_ad'))
|
||||
}
|
||||
|
||||
File propFile = file('sign.properties')
|
||||
|
||||
@ -26,7 +26,7 @@ class FlavorProviderImp : IFlavorProvider {
|
||||
return channel
|
||||
}
|
||||
|
||||
override fun init(application: Application, activity: Activity) {
|
||||
override fun init(application: Application, activity: Activity, activateRatio: Int) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
|
||||
@ -12,7 +12,7 @@ import com.leon.channel.helper.ChannelReaderUtil
|
||||
|
||||
class FlavorProviderImp : IFlavorProvider {
|
||||
|
||||
override fun init(application: Application, activity: Activity) {
|
||||
override fun init(application: Application, activity: Activity, activateRatio: Int) {
|
||||
GdtHelper.init(application, getChannelStr(application))
|
||||
|
||||
if (HaloApp.getInstance().isBrandNewInstall) {
|
||||
|
||||
10
app/src/internal/res/xml/network_security_config.xml
Normal file
10
app/src/internal/res/xml/network_security_config.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<network-security-config>
|
||||
<base-config cleartextTrafficPermitted="true">
|
||||
<trust-anchors>
|
||||
<!-- Trust user added CAs while debuggable only -->
|
||||
<certificates src="user" />
|
||||
<certificates src="system" />
|
||||
</trust-anchors>
|
||||
</base-config>
|
||||
</network-security-config>
|
||||
@ -12,7 +12,7 @@ import com.leon.channel.helper.ChannelReaderUtil
|
||||
|
||||
class FlavorProviderImp : IFlavorProvider {
|
||||
|
||||
override fun init(application: Application, activity: Activity) {
|
||||
override fun init(application: Application, activity: Activity, activateRatio: Int) {
|
||||
KuaishouHelper.init(application, getChannelStr(application))
|
||||
|
||||
if (HaloApp.getInstance().isBrandNewInstall) {
|
||||
|
||||
@ -46,7 +46,8 @@
|
||||
<!-- 如果有视频相关的广告且使用textureView播放,请务必添加,否则黑屏 -->
|
||||
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
||||
|
||||
<uses-sdk tools:overrideLibrary="com.shuyu.gsyvideoplayer,
|
||||
<uses-sdk tools:overrideLibrary="
|
||||
com.shuyu.gsyvideoplayer,
|
||||
com.shuyu.gsyvideoplayer.lib,
|
||||
com.haroldadmin.whatthestack,
|
||||
com.shuyu.gsyvideoplayer.armv7a,
|
||||
@ -106,6 +107,7 @@
|
||||
android:label="@string/app_name"
|
||||
android:largeHeap="true"
|
||||
android:resizeableActivity="true"
|
||||
android:networkSecurityConfig="@xml/network_security_config"
|
||||
android:theme="@style/AppCompatTheme.APP"
|
||||
tools:replace="android:name,android:allowBackup"
|
||||
tools:targetApi="n">
|
||||
@ -119,7 +121,7 @@
|
||||
android:name="io.sentry.breadcrumbs.system-events"
|
||||
android:value="false" />
|
||||
|
||||
<service android:name = "com.gh.ndownload.NDownloadService" />
|
||||
<service android:name="com.gh.ndownload.NDownloadService" />
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.SplashScreenActivity"
|
||||
|
||||
@ -60,7 +60,12 @@ import java.io.File
|
||||
import java.io.FileOutputStream
|
||||
import java.util.*
|
||||
|
||||
class DefaultJsApi(var context: Context, val entrance: String = "", private var mFragment: Fragment? = null) {
|
||||
class DefaultJsApi(
|
||||
var context: Context,
|
||||
val entrance: String = "",
|
||||
private var mFragment: Fragment? = null,
|
||||
private var mBbsId: String? = "",
|
||||
) {
|
||||
|
||||
private var mLoginHandler: CompletionHandler<Any>? = null
|
||||
private var mDownloadWatcher: DataWatcher? = null // 下载观察者
|
||||
@ -258,6 +263,24 @@ class DefaultJsApi(var context: Context, val entrance: String = "", private var
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否为论坛详情的专区
|
||||
*/
|
||||
@JavascriptInterface
|
||||
fun isForumZone(msg: Any): Boolean {
|
||||
return !mBbsId.isNullOrEmpty()
|
||||
}
|
||||
|
||||
/**
|
||||
* 打开论坛搜索页
|
||||
*/
|
||||
@JavascriptInterface
|
||||
fun openForumSearch(msg: Any) {
|
||||
runOnUiThread {
|
||||
DirectUtils.directToForumOrUserSearch(context, mBbsId ?: "", entrance.ifBlank { "内部网页" })
|
||||
}
|
||||
}
|
||||
|
||||
@JavascriptInterface
|
||||
fun exitWebView(msg: Any) {
|
||||
runOnUiThread { (context as Activity).finish() }
|
||||
|
||||
@ -21,7 +21,7 @@ object FixedRateJobHelper {
|
||||
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 REGION_SETTING_PERIOD: Long = 30 * 1000L
|
||||
private const val REGION_SETTING_PERIOD: Long = 60 * 1000L
|
||||
private const val VIDEO_RECORD_PERIOD: Long = 60 * 1000L
|
||||
|
||||
private const val DOWNLOAD_HEARTBEAT_PERIOD: Long = 60 * 1000L
|
||||
|
||||
@ -455,7 +455,7 @@ public class BindingAdapters {
|
||||
}
|
||||
|
||||
if (gameEntity.isVGame()) {
|
||||
VHelper.installOrLaunch((AppCompatActivity) v.getContext(), gameEntity.getApk().get(0).getPackageName());
|
||||
VHelper.installOrLaunch((AppCompatActivity) v.getContext(), gameEntity);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -473,10 +473,9 @@ public class BindingAdapters {
|
||||
case INSTALL_NORMAL:
|
||||
if (gameEntity.getApk().size() == 1) {
|
||||
DownloadEntity downloadEntity = DownloadManager.getInstance().getDownloadEntitySnapshot(gameEntity);
|
||||
String packageName = gameEntity.getApk().get(0).getPackageName();
|
||||
|
||||
if (gameEntity.isVGame()) {
|
||||
VHelper.installOrLaunch(v.getContext(), packageName);
|
||||
VHelper.installOrLaunch(v.getContext(), gameEntity);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@ -8,6 +8,8 @@ import com.google.gson.annotations.SerializedName
|
||||
class RegionSetting(
|
||||
@SerializedName("game_mirror")
|
||||
var mirrorGameIdSet: HashSet<String>,
|
||||
@SerializedName("game_mirror2")
|
||||
var mirrorGameIdSet2: HashSet<String>?,
|
||||
@SerializedName("game_block")
|
||||
var filterGameIdSet: HashSet<String>,
|
||||
@SerializedName("channel_control")
|
||||
|
||||
@ -23,7 +23,8 @@ object RegionSettingHelper {
|
||||
|
||||
private var mChannelControl: RegionSetting.ChannelControl? = null
|
||||
private var mFilterGameIdSet: HashSet<String>? = hashSetOf()
|
||||
private var mDisplayMirrorIfoGameIdSet: HashSet<String>? = hashSetOf()
|
||||
private var mDisplayMirrorGameIdSet: HashSet<String>? = hashSetOf()
|
||||
private var mDisplayMirrorGameIdSet2: HashSet<String>? = hashSetOf()
|
||||
private var mGameH5DownloadList: List<RegionSetting.GameH5Download>? = listOf()
|
||||
private var mGameSpecialDownloadInfoList: List<RegionSetting.GameSpecialDownloadInfo>? = listOf()
|
||||
private var mIpInfo: IpInfo? = null
|
||||
@ -33,7 +34,21 @@ object RegionSettingHelper {
|
||||
|
||||
@JvmStatic
|
||||
fun shouldThisGameDisplayMirrorInfo(gameId: String): Boolean {
|
||||
return mDisplayMirrorIfoGameIdSet?.contains(gameId) ?: false
|
||||
return mDisplayMirrorGameIdSet?.contains(gameId) == true
|
||||
|| mDisplayMirrorGameIdSet2?.contains(gameId) == true
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取镜像数据的位置,是归属镜像 1 还是镜像 2
|
||||
*/
|
||||
fun getMirrorPosition(gameId: String): Int {
|
||||
return if (mDisplayMirrorGameIdSet?.contains(gameId) == true) {
|
||||
1
|
||||
} else if (mDisplayMirrorGameIdSet2?.contains(gameId) == true) {
|
||||
2
|
||||
} else {
|
||||
-1
|
||||
}
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
@ -131,7 +146,8 @@ object RegionSettingHelper {
|
||||
|
||||
private fun updateSettingsInMemory(data: RegionSetting) {
|
||||
mFilterGameIdSet = data.filterGameIdSet
|
||||
mDisplayMirrorIfoGameIdSet = data.mirrorGameIdSet
|
||||
mDisplayMirrorGameIdSet = data.mirrorGameIdSet
|
||||
mDisplayMirrorGameIdSet2 = data.mirrorGameIdSet2
|
||||
mChannelControl = data.channelControl
|
||||
mGameH5DownloadList = data.gameH5DownloadList
|
||||
mGameSpecialDownloadInfoList = data.gameSpecialDownloadInfoList
|
||||
|
||||
@ -22,7 +22,7 @@ class GameDetailProviderImpl : IGameDetailProvider {
|
||||
context: Context,
|
||||
gameEntity: GameEntity?,
|
||||
entrance: String,
|
||||
defaultTab: Int,
|
||||
defaultTab: String,
|
||||
isSkipGameComment: Boolean,
|
||||
scrollToLibao: Boolean,
|
||||
scrollToServer: Boolean,
|
||||
|
||||
@ -14,6 +14,10 @@ class RegionSettingHelperProviderImpl : IRegionSettingHelperProvider {
|
||||
return RegionSettingHelper.shouldThisGameDisplayMirrorInfo(gameId)
|
||||
}
|
||||
|
||||
override fun getMirrorPosition(gameId: String): Int {
|
||||
return RegionSettingHelper.getMirrorPosition(gameId)
|
||||
}
|
||||
|
||||
override fun shouldThisGameShowSpecialDownload(gameId: String): Boolean {
|
||||
return RegionSettingHelper.shouldThisGameShowSpecialDownload(gameId)
|
||||
}
|
||||
|
||||
@ -114,7 +114,7 @@ public class DetailDownloadUtils {
|
||||
if (downloadEntity == null && viewHolder.gameEntity.isVGame()) {
|
||||
String packageName = viewHolder.gameEntity.getUniquePackageName();
|
||||
if (!TextUtils.isEmpty(packageName)) {
|
||||
downloadEntity = VHelper.getDownloadEntitySnapshot(viewHolder.gameEntity.getId(), packageName);
|
||||
downloadEntity = VHelper.getVDownloadEntitySnapshot(viewHolder.gameEntity.getId(), packageName);
|
||||
}
|
||||
}
|
||||
|
||||
@ -214,7 +214,7 @@ public class DetailDownloadUtils {
|
||||
if (downloadEntity == null && viewHolder.gameEntity.isVGame()) {
|
||||
String packageName = viewHolder.gameEntity.getUniquePackageName();
|
||||
if (!TextUtils.isEmpty(packageName)) {
|
||||
downloadEntity = VHelper.getDownloadEntitySnapshot(viewHolder.gameEntity.getId(), packageName);
|
||||
downloadEntity = VHelper.getVDownloadEntitySnapshot(viewHolder.gameEntity.getId(), packageName);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -45,6 +45,7 @@ import com.gh.gamecenter.feature.exposure.ExposureEvent.Companion.createEvent
|
||||
import com.gh.gamecenter.feature.exposure.ExposureType
|
||||
import com.gh.gamecenter.forum.detail.ForumDetailActivity
|
||||
import com.gh.gamecenter.forum.home.CommunityHomeFragment
|
||||
import com.gh.gamecenter.forum.search.ForumOrUserSearchActivity
|
||||
import com.gh.gamecenter.fragment.MainWrapperFragment
|
||||
import com.gh.gamecenter.game.columncollection.detail.ColumnCollectionDetailActivity
|
||||
import com.gh.gamecenter.game.commoncollection.detail.CommonCollectionDetailActivity
|
||||
@ -310,13 +311,14 @@ object DirectUtils {
|
||||
name = linkEntity.name,
|
||||
display = linkEntity.display ?: Display()
|
||||
),
|
||||
entrance
|
||||
entrance,
|
||||
exposureEvent
|
||||
)
|
||||
}
|
||||
|
||||
"column_collection", "专题合集" -> directToColumnCollection(context, linkEntity.link!!, -1, entrance)
|
||||
|
||||
"server", "game_server", "开服表" -> directToGameServers(context, entrance, path)
|
||||
"server", "game_server", "开服表" -> directToGameServers(context, entrance, path, exposureEvent)
|
||||
|
||||
"top_game_comment" -> directToAmway(context, null, entrance, path)
|
||||
|
||||
@ -438,11 +440,28 @@ object DirectUtils {
|
||||
|
||||
"game_list" -> directToGameCollectionSquare(context, entrance, "", "", "")
|
||||
|
||||
"game_list_detail" -> directToGameCollectionDetail(context, linkEntity.link ?: "", entrance)
|
||||
"game_list_detail" -> directToGameCollectionDetail(
|
||||
context,
|
||||
linkEntity.link ?: "",
|
||||
entrance,
|
||||
exposureEvent = exposureEvent
|
||||
)
|
||||
|
||||
"explore_column", "game_explore" -> context.startActivity(DiscoveryActivity.getIntent(context, entrance))
|
||||
"explore_column", "game_explore" -> context.startActivity(
|
||||
DiscoveryActivity.getIntent(
|
||||
context,
|
||||
entrance,
|
||||
exposureEvent
|
||||
)
|
||||
)
|
||||
|
||||
"column_test_v2" -> context.startActivity(GameServerTestV2Activity.getIntent(context, entrance))
|
||||
"column_test_v2" -> context.startActivity(
|
||||
GameServerTestV2Activity.getIntent(
|
||||
context,
|
||||
entrance,
|
||||
exposureEvent
|
||||
)
|
||||
)
|
||||
|
||||
"" -> {
|
||||
// do nothing
|
||||
@ -660,10 +679,10 @@ object DirectUtils {
|
||||
bundle.putString(KEY_GAMEID, id)
|
||||
if (!TextUtils.isEmpty(tab)) {
|
||||
when (tab) {
|
||||
"comment" -> bundle.putInt(KEY_TARGET, GameDetailFragment.INDEX_RATING)
|
||||
"desc" -> bundle.putInt(KEY_TARGET, GameDetailFragment.INDEX_DESC)
|
||||
"forum" -> bundle.putInt(KEY_TARGET, GameDetailFragment.INDEX_BBS)
|
||||
"zone" -> bundle.putInt(KEY_TARGET, GameDetailFragment.INDEX_TRENDES)
|
||||
"comment" -> bundle.putString(KEY_TARGET, GameDetailFragment.TAB_RATING)
|
||||
"desc" -> bundle.putString(KEY_TARGET, GameDetailFragment.TAB_DESC)
|
||||
"forum" -> bundle.putString(KEY_TARGET, GameDetailFragment.TAB_BBS)
|
||||
"zone" -> bundle.putString(KEY_TARGET, GameDetailFragment.TAB_TRENDS)
|
||||
}
|
||||
}
|
||||
if (traceEvent != null) {
|
||||
@ -703,7 +722,7 @@ object DirectUtils {
|
||||
bundle.putString(KEY_ENTRANCE, entrance)
|
||||
bundle.putString(KEY_GAMEID, id)
|
||||
bundle.putBoolean(KEY_OPEN_VIDEO_STREAMING, true)
|
||||
bundle.putInt(KEY_TARGET, GameDetailFragment.INDEX_DESC)
|
||||
bundle.putString(KEY_TARGET, GameDetailFragment.TAB_DESC)
|
||||
jumpActivity(context, bundle)
|
||||
}
|
||||
|
||||
@ -711,14 +730,14 @@ object DirectUtils {
|
||||
fun directToGameDetail(
|
||||
context: Context,
|
||||
id: String,
|
||||
defaultTab: Int = GameDetailFragment.INDEX_DESC,
|
||||
defaultTab: String = GameDetailFragment.TAB_DESC,
|
||||
entrance: String? = null
|
||||
) {
|
||||
val bundle = Bundle()
|
||||
bundle.putString(KEY_TO, GameDetailActivity::class.java.name)
|
||||
bundle.putString(KEY_ENTRANCE, entrance)
|
||||
bundle.putString(KEY_GAMEID, id)
|
||||
bundle.putInt(KEY_TARGET, defaultTab)
|
||||
bundle.putString(KEY_TARGET, defaultTab)
|
||||
jumpActivity(context, bundle)
|
||||
}
|
||||
|
||||
@ -1352,11 +1371,17 @@ object DirectUtils {
|
||||
* 跳转到板块
|
||||
*/
|
||||
@JvmStatic
|
||||
fun directToBlock(context: Context, blockData: SubjectRecommendEntity, entrance: String) {
|
||||
fun directToBlock(
|
||||
context: Context,
|
||||
blockData: SubjectRecommendEntity,
|
||||
entrance: String,
|
||||
exposureEvent: ExposureEvent? = null
|
||||
) {
|
||||
val bundle = Bundle()
|
||||
bundle.putString(KEY_TO, BlockActivity::class.java.name)
|
||||
bundle.putParcelable(KEY_BLOCK_DATA, blockData)
|
||||
bundle.putString(KEY_ENTRANCE, entrance)
|
||||
exposureEvent?.let { bundle.putParcelableArrayList(KEY_EXPOSURE_SOURCE_LIST, ArrayList(exposureEvent.source)) }
|
||||
jumpActivity(context, bundle)
|
||||
}
|
||||
|
||||
@ -1364,10 +1389,11 @@ object DirectUtils {
|
||||
* 跳转到开服表
|
||||
*/
|
||||
@JvmStatic
|
||||
fun directToGameServers(context: Context, entrance: String, path: String) {
|
||||
fun directToGameServers(context: Context, entrance: String, path: String, exposureEvent: ExposureEvent? = null) {
|
||||
val bundle = Bundle()
|
||||
bundle.putString(KEY_TO, GameServersActivity::class.java.name)
|
||||
bundle.putString(KEY_ENTRANCE, ToolBarActivity.mergeEntranceAndPath(entrance, path))
|
||||
exposureEvent?.let { bundle.putParcelableArrayList(KEY_EXPOSURE_SOURCE_LIST, ArrayList(exposureEvent.source)) }
|
||||
jumpActivity(context, bundle)
|
||||
}
|
||||
|
||||
@ -1395,7 +1421,7 @@ object DirectUtils {
|
||||
response?.apply {
|
||||
if (zone.status == "on") {
|
||||
if (zone.style == "link") {
|
||||
directToGameDetail(context, gameId, GameDetailFragment.INDEX_TRENDES, entrance)
|
||||
directToGameDetail(context, gameId, GameDetailFragment.TAB_TRENDS, entrance)
|
||||
} else {
|
||||
directToWebView(context, url, entrance)
|
||||
}
|
||||
@ -1817,7 +1843,8 @@ object DirectUtils {
|
||||
collectionId: String,
|
||||
blockId: String = "",
|
||||
blockName: String = "",
|
||||
entrance: String = ""
|
||||
entrance: String = "",
|
||||
exposureEvent: ExposureEvent? = null
|
||||
) {
|
||||
if (collectionId.isEmpty()) return
|
||||
val bundle = Bundle()
|
||||
@ -1826,6 +1853,7 @@ object DirectUtils {
|
||||
bundle.putString(KEY_BLOCK_NAME, blockName)
|
||||
bundle.putString(KEY_ENTRANCE, entrance)
|
||||
bundle.putString(KEY_COLLECTION_ID, collectionId)
|
||||
exposureEvent?.let { bundle.putParcelableArrayList(KEY_EXPOSURE_SOURCE_LIST, ArrayList(exposureEvent.source)) }
|
||||
jumpActivity(context, bundle)
|
||||
}
|
||||
|
||||
@ -1861,13 +1889,20 @@ object DirectUtils {
|
||||
* 跳转至游戏单详情
|
||||
*/
|
||||
@JvmStatic
|
||||
fun directToGameCollectionDetail(context: Context, id: String, entrance: String? = null, path: String? = null) {
|
||||
fun directToGameCollectionDetail(
|
||||
context: Context,
|
||||
id: String,
|
||||
entrance: String? = null,
|
||||
path: String? = null,
|
||||
exposureEvent: ExposureEvent? = null
|
||||
) {
|
||||
if (id.isEmpty()) return
|
||||
val bundle = Bundle()
|
||||
bundle.putString(KEY_ENTRANCE, entrance ?: ENTRANCE_BROWSER)
|
||||
bundle.putString(KEY_PATH, path)
|
||||
bundle.putString(KEY_TO, GameCollectionDetailActivity::class.java.name)
|
||||
bundle.putString(KEY_GAME_COLLECTION_ID, id)
|
||||
exposureEvent?.let { bundle.putParcelableArrayList(KEY_EXPOSURE_SOURCE_LIST, ArrayList(exposureEvent.source)) }
|
||||
jumpActivity(context, bundle)
|
||||
}
|
||||
|
||||
@ -1909,6 +1944,15 @@ object DirectUtils {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 跳转到论坛搜索页
|
||||
* @param bbsId, 为空时搜索全范围的内容,不为空时搜索该 bbsId 对应的内容
|
||||
*/
|
||||
@JvmStatic
|
||||
fun directToForumOrUserSearch(context: Context, bbsId: String, entrance: String) {
|
||||
context.startActivity(ForumOrUserSearchActivity.getIntent(context, bbsId, entrance))
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun directToVGameDownload(context: Context, switchToDownloadingTab: Boolean = false) {
|
||||
val bundle = Bundle()
|
||||
|
||||
@ -29,7 +29,7 @@ object DownloadDialogHelper {
|
||||
|
||||
private fun retrieveAvailableDialog(gameEntity: GameEntity, apkEntity: ApkEntity): GameEntity.Dialog? {
|
||||
val downloadDialog = if (gameEntity.shouldUseMirrorInfo()) {
|
||||
gameEntity.mirrorData?.downloadDialog
|
||||
gameEntity.obtainMirrorData()?.downloadDialog
|
||||
} else {
|
||||
gameEntity.downloadDialog
|
||||
}
|
||||
|
||||
@ -266,7 +266,7 @@ object DownloadItemUtils {
|
||||
var downloadEntity = DownloadManager.getInstance().getDownloadEntitySnapshot(gameEntity)
|
||||
|
||||
if (downloadEntity == null && gameEntity.isVGame()) {
|
||||
downloadEntity = VHelper.getDownloadEntitySnapshot(gameEntity.id, gameEntity.getUniquePackageName())
|
||||
downloadEntity = VHelper.getVDownloadEntitySnapshot(gameEntity.id, gameEntity.getUniquePackageName())
|
||||
}
|
||||
|
||||
if (downloadEntity == null) {
|
||||
@ -884,7 +884,7 @@ object DownloadItemUtils {
|
||||
}
|
||||
|
||||
if (gameEntity.isVGame()) {
|
||||
VHelper.installOrLaunch((context as AppCompatActivity), gameEntity.getUniquePackageName() ?: "")
|
||||
VHelper.installOrLaunch((context as AppCompatActivity), gameEntity)
|
||||
} else {
|
||||
install(context, gameEntity, position, adapter, refreshCallback)
|
||||
}
|
||||
@ -909,7 +909,7 @@ object DownloadItemUtils {
|
||||
}
|
||||
|
||||
if (gameEntity.isVGame()) {
|
||||
VHelper.installOrLaunch((context as AppCompatActivity), gameEntity.getUniquePackageName() ?: "")
|
||||
VHelper.installOrLaunch((context as AppCompatActivity), gameEntity)
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@ -298,7 +298,7 @@ object GameActivityDownloadHelper {
|
||||
}
|
||||
|
||||
if (gameEntity.isVGame()) {
|
||||
VHelper.installOrLaunch((context as AppCompatActivity), gameEntity.getUniquePackageName() ?: "")
|
||||
VHelper.installOrLaunch((context as AppCompatActivity), gameEntity)
|
||||
} else {
|
||||
downloadEntity?.run {
|
||||
install(context, gameEntity, apk, this)
|
||||
@ -336,7 +336,7 @@ object GameActivityDownloadHelper {
|
||||
}
|
||||
|
||||
if (gameEntity.isVGame()) {
|
||||
VHelper.installOrLaunch((context as AppCompatActivity), gameEntity.getUniquePackageName() ?: "")
|
||||
VHelper.installOrLaunch((context as AppCompatActivity), gameEntity)
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@ -107,7 +107,7 @@ public class GameUtils {
|
||||
|
||||
// 在下载管理找不到下载实体,并且为畅玩游戏的时候到畅玩数据库里找
|
||||
if (downloadEntity == null && gameEntity.isVGame()) {
|
||||
downloadEntity = VHelper.getDownloadEntitySnapshot(gameEntity.getId(), apkEntity.getPackageName());
|
||||
downloadEntity = VHelper.getVDownloadEntitySnapshot(gameEntity.getId(), apkEntity.getPackageName());
|
||||
}
|
||||
|
||||
if (downloadEntity != null) {
|
||||
|
||||
@ -568,16 +568,19 @@ public class LogUtils {
|
||||
}
|
||||
|
||||
public static void uploadSearchGame(String event, String location, String key, String searchType) {
|
||||
uploadSearchClick(event, location, key, searchType, "", "", false, false);
|
||||
uploadSearchClick(event, location, key, searchType, "", "", 0, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mirrorDataPosition 镜像的归类,不是镜像是为 -1 ,使用镜像 1 时为 1,使用镜像 2 时为 2
|
||||
*/
|
||||
public static void uploadSearchClick(String event,
|
||||
String location,
|
||||
String key,
|
||||
String searchType,
|
||||
String gameId,
|
||||
String gameName,
|
||||
Boolean isMirrorData,
|
||||
int mirrorDataPosition,
|
||||
Boolean isAdData) {
|
||||
JSONObject object = new JSONObject();
|
||||
JSONObject payload = new JSONObject();
|
||||
@ -591,7 +594,13 @@ public class LogUtils {
|
||||
payload.put("search_type", searchType); //搜索类型, 有四种取值 默认搜索/历史搜索/自动搜索/主动搜索
|
||||
payload.put(KEY_GAME_ID, gameId); //event为search_click才取值
|
||||
payload.put(KEY_GAME_NAME, gameName); //event为search_click才取值
|
||||
payload.put("is_mirror_data", isMirrorData);
|
||||
|
||||
// 是否使用镜像
|
||||
if (mirrorDataPosition == 1) {
|
||||
payload.put("is_mirror_data", true);
|
||||
} else if (mirrorDataPosition == 2) {
|
||||
payload.put("is_mirror2_data", true);
|
||||
}
|
||||
payload.put("is_ad_data", isAdData);
|
||||
object.put(KEY_PAY_LOAD, payload);
|
||||
} catch (JSONException e) {
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
package com.gh.common.xapk
|
||||
|
||||
import android.app.Activity
|
||||
import android.app.Dialog
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.graphics.Color
|
||||
@ -20,13 +21,26 @@ import com.gh.gamecenter.core.utils.SPUtils
|
||||
import com.gh.gamecenter.help.HelpAndFeedbackBridge
|
||||
import com.lightgame.download.DownloadEntity
|
||||
import com.lightgame.utils.Utils
|
||||
import java.lang.ref.WeakReference
|
||||
|
||||
object XapkDialogHelper {
|
||||
|
||||
private var mUnzipFailureDialogRef: WeakReference<Dialog>? = null
|
||||
|
||||
fun showUnzipFailureDialog(context: Context, downloadEntity: DownloadEntity, isManualAction: Boolean) {
|
||||
val trigger = if (isManualAction) "手动触发" else "自动触发"
|
||||
NewFlatLogUtils.logXApkUnzipFailedDialogShowed(trigger, downloadEntity.gameId, downloadEntity.name)
|
||||
DialogHelper.showGuideDialog(
|
||||
|
||||
val previousShowedDialog = mUnzipFailureDialogRef?.get()
|
||||
|
||||
if (previousShowedDialog != null
|
||||
&& previousShowedDialog.isShowing
|
||||
&& context == previousShowedDialog.ownerActivity) {
|
||||
// 上一个解压失败弹窗还在显示,当前 activity 不用再显示新的弹窗了
|
||||
return
|
||||
}
|
||||
|
||||
val dialog = DialogHelper.showGuideDialog(
|
||||
context = context,
|
||||
title = "",
|
||||
content = "未授权允许未知来源安装、数据包格式、设备兼容性…等均可能导致解压失败。\n如果开启权限后仍未能解决,请提交反馈帮助我们改进。",
|
||||
@ -107,6 +121,11 @@ object XapkDialogHelper {
|
||||
},
|
||||
extraConfig = DialogHelper.Config(showCloseIcon = true)
|
||||
)
|
||||
|
||||
if (context is Activity) {
|
||||
dialog?.setOwnerActivity(context)
|
||||
}
|
||||
mUnzipFailureDialogRef = WeakReference(dialog)
|
||||
}
|
||||
|
||||
}
|
||||
@ -626,7 +626,7 @@ public class DownloadManager implements DownloadStatusListener {
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据 url 获取下载任务快照 (仅保证下载状态一致)
|
||||
* 根据包名获取下载任务快照 (仅保证下载状态一致)
|
||||
*
|
||||
* @param packageName 包名 (多包名一样时取第一个,若使用场景里有多包名,请使用 url 获取下载任务)
|
||||
* @return null 表示下载列表中不存在该任务,否则返回下载任务
|
||||
|
||||
@ -15,6 +15,7 @@ import okhttp3.Request
|
||||
import okhttp3.Response
|
||||
import tv.danmaku.ijk.media.exo2.ExoSourceManager
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
object ExoCacheManager {
|
||||
|
||||
@ -98,7 +99,9 @@ object ExoCacheManager {
|
||||
.build()
|
||||
var response: Response? = null
|
||||
try {
|
||||
response = OkHttpClient.Builder().build().newCall(request).execute()
|
||||
response =
|
||||
OkHttpClient.Builder().connectTimeout(5, TimeUnit.SECONDS).readTimeout(5, TimeUnit.SECONDS).build()
|
||||
.newCall(request).execute()
|
||||
if (response!!.isSuccessful && response.body() != null) {
|
||||
val length = response.body()!!.contentLength()
|
||||
contentLength = if (length == 0L) -1L else length
|
||||
|
||||
@ -27,7 +27,7 @@ class BlockActivity : DownloadToolbarActivity() {
|
||||
}
|
||||
|
||||
override fun provideNormalIntent(): Intent {
|
||||
return getTargetIntent(this, BlockActivity::class.java, GameFragment::class.java)
|
||||
return getTargetIntent(this, BlockActivity::class.java, GameFragment::class.java, intent?.extras)
|
||||
}
|
||||
|
||||
override fun showDownloadMenu(): Boolean {
|
||||
|
||||
@ -101,7 +101,7 @@ class GameDetailActivity : DownloadToolbarActivity() {
|
||||
entrance: String,
|
||||
traceEvent: ExposureEvent?
|
||||
) {
|
||||
startGameDetailActivity(context, gameEntity, entrance, -1, traceEvent = traceEvent)
|
||||
startGameDetailActivity(context, gameEntity, entrance, "", traceEvent = traceEvent)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -117,7 +117,7 @@ class GameDetailActivity : DownloadToolbarActivity() {
|
||||
context: Context,
|
||||
gameEntity: GameEntity?,
|
||||
entrance: String,
|
||||
defaultTab: Int = -1,
|
||||
defaultTab: String = "",
|
||||
isSkipGameComment: Boolean = false,
|
||||
scrollToLibao: Boolean = false,
|
||||
scrollToServer: Boolean = false,
|
||||
@ -140,18 +140,18 @@ class GameDetailActivity : DownloadToolbarActivity() {
|
||||
)
|
||||
traceEvent.payload = payload
|
||||
}
|
||||
if (defaultTab != -1) {
|
||||
bundle.putInt(EntranceConsts.KEY_TARGET, defaultTab)
|
||||
if (defaultTab.isNotEmpty()) {
|
||||
bundle.putString(EntranceConsts.KEY_TARGET, defaultTab)
|
||||
}
|
||||
if (isSkipGameComment) {
|
||||
bundle.putBoolean(EntranceConsts.KEY_SKIP_GAME_COMMENT, true)
|
||||
}
|
||||
if (scrollToLibao) {
|
||||
bundle.putInt(EntranceConsts.KEY_TARGET, GameDetailFragment.INDEX_DESC)
|
||||
bundle.putString(EntranceConsts.KEY_TARGET, GameDetailFragment.TAB_DESC)
|
||||
bundle.putBoolean(EntranceConsts.KEY_SCROLL_TO_LIBAO, true)
|
||||
}
|
||||
if (scrollToServer) {
|
||||
bundle.putInt(EntranceConsts.KEY_TARGET, GameDetailFragment.INDEX_DESC)
|
||||
bundle.putString(EntranceConsts.KEY_TARGET, GameDetailFragment.TAB_DESC)
|
||||
bundle.putBoolean(EntranceConsts.KEY_SCROLL_TO_SERVER, true)
|
||||
}
|
||||
bundle.putString(EntranceConsts.KEY_GAMEID, gameEntity?.id)
|
||||
@ -257,7 +257,7 @@ class GameDetailActivity : DownloadToolbarActivity() {
|
||||
}
|
||||
if (openVideoStreaming) {
|
||||
bundle.putBoolean(EntranceConsts.KEY_OPEN_VIDEO_STREAMING, true)
|
||||
bundle.putInt(EntranceConsts.KEY_TARGET, GameDetailFragment.INDEX_DESC)
|
||||
bundle.putString(EntranceConsts.KEY_TARGET, GameDetailFragment.TAB_DESC)
|
||||
}
|
||||
if (openPlatformWindow) {
|
||||
bundle.putBoolean(EntranceConsts.KEY_OPEN_PLATFORM_WINDOW, true)
|
||||
@ -269,7 +269,7 @@ class GameDetailActivity : DownloadToolbarActivity() {
|
||||
}
|
||||
}
|
||||
if (scrollToLibao) {
|
||||
bundle.putInt(EntranceConsts.KEY_TARGET, GameDetailFragment.INDEX_TRENDES)
|
||||
bundle.putString(EntranceConsts.KEY_TARGET, GameDetailFragment.TAB_DESC)
|
||||
bundle.putBoolean(EntranceConsts.KEY_SCROLL_TO_LIBAO, true)
|
||||
}
|
||||
bundle.putString(EntranceConsts.KEY_GAMEID, gameId)
|
||||
|
||||
@ -861,7 +861,7 @@ class ImageViewerActivity : BaseActivity(), OnPageChangeListener {
|
||||
imageView.setOnLongClickListener {
|
||||
// 下滑的时候不弹
|
||||
if (imageView.isDragging()) {
|
||||
return@setOnLongClickListener false
|
||||
return@setOnLongClickListener true
|
||||
}
|
||||
|
||||
val dialog = Dialog(this@ImageViewerActivity)
|
||||
@ -897,7 +897,7 @@ class ImageViewerActivity : BaseActivity(), OnPageChangeListener {
|
||||
}
|
||||
dialog.cancel()
|
||||
}
|
||||
false
|
||||
true
|
||||
}
|
||||
view.tag = position
|
||||
container.addView(view)
|
||||
|
||||
@ -26,7 +26,6 @@ import android.graphics.Color;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.os.Message;
|
||||
import android.os.SystemClock;
|
||||
import android.preference.PreferenceManager;
|
||||
@ -34,6 +33,7 @@ import android.text.Html;
|
||||
import android.text.TextUtils;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.View;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
@ -43,6 +43,7 @@ import androidx.constraintlayout.widget.ConstraintLayout;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.lifecycle.ViewModelProviders;
|
||||
|
||||
import com.alibaba.android.arouter.launcher.ARouter;
|
||||
import com.facebook.drawee.view.SimpleDraweeView;
|
||||
import com.gh.common.DefaultUrlHandler;
|
||||
import com.gh.common.constant.Config;
|
||||
@ -76,6 +77,7 @@ import com.gh.gamecenter.common.base.fragment.ToolbarFragment;
|
||||
import com.gh.gamecenter.common.constant.CommonConsts;
|
||||
import com.gh.gamecenter.common.constant.Constants;
|
||||
import com.gh.gamecenter.common.constant.EntranceConsts;
|
||||
import com.gh.gamecenter.common.constant.RouteConsts;
|
||||
import com.gh.gamecenter.common.entity.LinkEntity;
|
||||
import com.gh.gamecenter.common.entity.NotificationUgc;
|
||||
import com.gh.gamecenter.common.entity.SuggestType;
|
||||
@ -90,6 +92,7 @@ import com.gh.gamecenter.common.utils.ImageUtils;
|
||||
import com.gh.gamecenter.common.utils.NotificationHelper;
|
||||
import com.gh.gamecenter.common.utils.ShareUtils;
|
||||
import com.gh.gamecenter.core.AppExecutor;
|
||||
import com.gh.gamecenter.core.provider.IStartUpAdProvider;
|
||||
import com.gh.gamecenter.core.utils.ClassUtils;
|
||||
import com.gh.gamecenter.core.utils.DisplayUtils;
|
||||
import com.gh.gamecenter.core.utils.GsonUtils;
|
||||
@ -189,6 +192,8 @@ public class MainActivity extends BaseActivity {
|
||||
private final Handler handler = new Handler();
|
||||
public boolean showAd = false; // 是否显示广告
|
||||
|
||||
private IStartUpAdProvider mStartUpAdProvider;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
showAd = getIntent().getBooleanExtra(SHOW_AD, false) && savedInstanceState == null;
|
||||
@ -469,6 +474,8 @@ public class MainActivity extends BaseActivity {
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
|
||||
if (mStartUpAdProvider != null) mStartUpAdProvider.cancelStartUpAd(this);
|
||||
|
||||
handler.removeCallbacksAndMessages(null);
|
||||
releaseExoSourceCache();
|
||||
}
|
||||
@ -502,8 +509,17 @@ public class MainActivity extends BaseActivity {
|
||||
showStartUp(startUp);
|
||||
AppExecutor.getUiExecutor().executeWithDelay(() -> {
|
||||
hideStartUp();
|
||||
observeStartUpAd();
|
||||
initStartUpAd();
|
||||
}, 2000);
|
||||
} else {
|
||||
initStartUpAd();
|
||||
}
|
||||
}
|
||||
|
||||
private void initStartUpAd() {
|
||||
mStartUpAdProvider = (IStartUpAdProvider) ARouter.getInstance().build(RouteConsts.provider.adSdk).navigation();
|
||||
if (mStartUpAdProvider != null && mStartUpAdProvider.shouldEnableSDK(HaloApp.getInstance().getChannel())) {
|
||||
initSDKStartUpAd();
|
||||
} else {
|
||||
observeStartUpAd();
|
||||
}
|
||||
@ -597,6 +613,12 @@ public class MainActivity extends BaseActivity {
|
||||
startAdContainer.setVisibility(View.GONE);
|
||||
ExtensionsKt.removeFromParent(startAdContainer);
|
||||
}
|
||||
View startSdkAdContainer = findViewById(R.id.sdkStartAdContainer);
|
||||
if (startSdkAdContainer != null) {
|
||||
startSdkAdContainer.setVisibility(View.GONE);
|
||||
ExtensionsKt.removeFromParent(startSdkAdContainer);
|
||||
if (mStartUpAdProvider != null) mStartUpAdProvider.cancelStartUpAd(this);
|
||||
}
|
||||
checkDialog();
|
||||
}
|
||||
|
||||
@ -654,6 +676,18 @@ public class MainActivity extends BaseActivity {
|
||||
mBaseHandler.sendEmptyMessageDelayed(COUNTDOWN_AD, 1000);
|
||||
}
|
||||
|
||||
private void initSDKStartUpAd() {
|
||||
View startAdContainer = findViewById(R.id.sdkStartAdContainer);
|
||||
startAdContainer.setVisibility(View.VISIBLE);
|
||||
FrameLayout adsFl = findViewById(R.id.adsFl);
|
||||
if (mStartUpAdProvider != null) {
|
||||
mStartUpAdProvider.initStartUpAd(startAdContainer, adsFl, showAd, () -> {
|
||||
hideStartUpAd();
|
||||
return null;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void showStartUp(StartupAdEntity ad) {
|
||||
TextView adContentTv = findViewById(R.id.adContentTv);
|
||||
View containerView = findViewById(R.id.maskContainer);
|
||||
|
||||
@ -58,6 +58,7 @@ import com.gh.gamecenter.common.entity.CommunityEntity;
|
||||
import com.gh.gamecenter.common.entity.LinkEntity;
|
||||
import com.gh.gamecenter.common.entity.SimpleGameEntity;
|
||||
import com.gh.gamecenter.core.utils.GsonUtils;
|
||||
import com.gh.gamecenter.core.utils.ToastUtils;
|
||||
import com.gh.gamecenter.entity.SubjectRecommendEntity;
|
||||
import com.gh.gamecenter.entity.VideoLinkEntity;
|
||||
import com.gh.gamecenter.feature.utils.PlatformUtils;
|
||||
@ -327,11 +328,11 @@ public class SkipActivity extends BaseActivity {
|
||||
entity.setLink(path);
|
||||
entity.setName(name);
|
||||
entity.setText(name);
|
||||
DirectUtils.directToBlock(this, entity, mEntrance);
|
||||
DirectUtils.directToBlock(this, entity, mEntrance, null);
|
||||
break;
|
||||
|
||||
case EntranceConsts.HOST_SERVER_BLOCK:
|
||||
DirectUtils.directToGameServers(this, ENTRANCE_BROWSER, "浏览器");
|
||||
DirectUtils.directToGameServers(this, ENTRANCE_BROWSER, "浏览器", null);
|
||||
break;
|
||||
|
||||
case EntranceConsts.HOST_AMWAY_BLOCK:
|
||||
@ -399,7 +400,7 @@ public class SkipActivity extends BaseActivity {
|
||||
DirectUtils.directToHelpAndFeedback(this, TextUtils.isEmpty(position) ? 0 : Integer.parseInt(position));
|
||||
break;
|
||||
case HOST_GAME_COLLECTION_DETAIL:
|
||||
DirectUtils.directToGameCollectionDetail(this, path, ENTRANCE_BROWSER, "");
|
||||
DirectUtils.directToGameCollectionDetail(this, path, ENTRANCE_BROWSER, "", null);
|
||||
break;
|
||||
case HOST_GAME_COLLECTION_SQUARE:
|
||||
DirectUtils.directToGameCollectionSquare(this, ENTRANCE_BROWSER, "", "", "");
|
||||
@ -450,6 +451,12 @@ public class SkipActivity extends BaseActivity {
|
||||
finish();
|
||||
}
|
||||
});
|
||||
|
||||
if (SkipActivity.this.isFinishing()) {
|
||||
ToastUtils.toast("创建桌面图标失败,请重试");
|
||||
return;
|
||||
}
|
||||
|
||||
dialog.show();
|
||||
}
|
||||
|
||||
|
||||
@ -21,7 +21,6 @@ import com.alibaba.android.arouter.launcher.ARouter
|
||||
import com.g00fy2.versioncompare.Version
|
||||
import com.gh.common.dialog.NewPrivacyPolicyDialogFragment
|
||||
import com.gh.common.util.*
|
||||
import com.gh.common.util.DialogUtils
|
||||
import com.gh.common.util.GameSubstituteRepositoryHelper.updateGameSubstituteRepository
|
||||
import com.gh.common.util.UsageStatsHelper.checkAndPostUsageStats
|
||||
import com.gh.download.DownloadManager
|
||||
@ -29,10 +28,12 @@ import com.gh.gamecenter.common.base.activity.BaseActivity
|
||||
import com.gh.gamecenter.common.callback.SimpleCallback
|
||||
import com.gh.gamecenter.common.constant.Constants
|
||||
import com.gh.gamecenter.common.constant.RouteConsts
|
||||
import com.gh.gamecenter.common.exposure.meta.MetaUtil
|
||||
import com.gh.gamecenter.common.tracker.TrackerLogger
|
||||
import com.gh.gamecenter.common.utils.*
|
||||
import com.gh.gamecenter.core.provider.IAppProvider
|
||||
import com.gh.gamecenter.core.provider.IPackageUtilsProvider
|
||||
import com.gh.gamecenter.core.provider.IStartUpAdProvider
|
||||
import com.gh.gamecenter.core.runOnIoThread
|
||||
import com.gh.gamecenter.core.utils.*
|
||||
import com.gh.gamecenter.entity.PrivacyPolicyEntity
|
||||
@ -62,6 +63,9 @@ class SplashScreenActivity : BaseActivity() {
|
||||
private var mStartMainActivityDirectly = false // 是否不需要用户点击立即体验就直接跳转首页
|
||||
private var mViewModel: SplashScreenViewModel? = null
|
||||
private var mShouldPrefetchData = true
|
||||
private val mStartUpAdProvider by lazy {
|
||||
ARouter.getInstance().build(RouteConsts.provider.adSdk).navigation() as? IStartUpAdProvider
|
||||
}
|
||||
|
||||
private val mPermissions = arrayOf(
|
||||
Manifest.permission.WRITE_EXTERNAL_STORAGE,
|
||||
@ -294,19 +298,45 @@ class SplashScreenActivity : BaseActivity() {
|
||||
overridePendingTransition(0, 0)
|
||||
startActivity(intent)
|
||||
doFlavorInit()
|
||||
initStartUpAdSDK()
|
||||
logAppLaunch()
|
||||
finish()
|
||||
}
|
||||
|
||||
private fun doFlavorInit() {
|
||||
HaloApp.getInstance().flavorProvider.init(HaloApp.getInstance(), this)
|
||||
HaloApp.getInstance().flavorProvider.init(HaloApp.getInstance(), this, PkgHelper.getActivateRatio())
|
||||
|
||||
// 仅官网渠道和测试包启用神策
|
||||
if ("GH_206" == HaloApp.getInstance().channel || PackageFlavorHelper.IS_TEST_FLAVOR) {
|
||||
val whiteListChannel = arrayListOf<String>(
|
||||
"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) {
|
||||
SensorsBridge.init(HaloApp.getInstance(), HaloApp.getInstance().channel)
|
||||
}
|
||||
}
|
||||
|
||||
private fun initStartUpAdSDK() {
|
||||
mStartUpAdProvider?.run {
|
||||
if (shouldEnableSDK(HaloApp.getInstance().channel)) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
initOAID(applicationContext) {
|
||||
HaloApp.getInstance().oaid = it
|
||||
MetaUtil.refreshMeta()
|
||||
}
|
||||
}
|
||||
initSDK(applicationContext)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun getGitLogString(): String {
|
||||
if (com.gh.gamecenter.common.BuildConfig.BUILD_TIME != 0L) {
|
||||
val stringBuilder = StringBuilder()
|
||||
|
||||
@ -324,7 +324,11 @@ public class LibaoDetailAdapter extends BaseRecyclerAdapter<ViewHolder> {
|
||||
if (mLibaoDetailEntity.getTime() != null) {
|
||||
SimpleDateFormat format = new SimpleDateFormat("yyyy年MM月dd日 HH:mm", Locale.CHINA);
|
||||
String start = format.format((mLibaoDetailEntity.getTime().getStart() * 1000));
|
||||
String end = format.format((mLibaoDetailEntity.getTime().getEnd() * 1000));
|
||||
|
||||
long libaoLingEndTime = mLibaoDetailEntity.getTime().getEnd();
|
||||
String end = libaoLingEndTime == 0
|
||||
? mContext.getString(R.string.libao_ling_time_infinitely) // 礼包领取结束时间为空则表示礼包长期有效
|
||||
: format.format((mLibaoDetailEntity.getTime().getEnd() * 1000));
|
||||
|
||||
holder.binding.libaodetailTimeStart.setText(StringUtils.buildString("开始时间:", start));
|
||||
holder.binding.libaodetailTimeEnd.setText(StringUtils.buildString("截止时间:", end));
|
||||
|
||||
@ -346,7 +346,7 @@ public class DetailViewHolder {
|
||||
}
|
||||
|
||||
if (mGameEntity.isVGame()) {
|
||||
VHelper.installOrLaunch(mViewHolder.context, mGameEntity.getApk().get(0).getPackageName());
|
||||
VHelper.installOrLaunch(mViewHolder.context, mGameEntity);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -388,7 +388,7 @@ public class DetailViewHolder {
|
||||
}
|
||||
|
||||
if (mGameEntity.isVGame()) {
|
||||
VHelper.installOrLaunch(v.getContext(), mGameEntity.getApk().get(0).getPackageName());
|
||||
VHelper.installOrLaunch(v.getContext(), mGameEntity);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@ -210,7 +210,7 @@ class AuthorizationActivity : ToolBarActivity() {
|
||||
private fun backToLaunchApp(showLoading: Boolean = true) {
|
||||
val gamePkg = mGamePkg
|
||||
if (gamePkg != null) { // 跳转回游戏
|
||||
VHelper.launch(this, gamePkg, showLoading = showLoading)
|
||||
VHelper.launch(this, gamePkg, ignoreGApps = true, showLoading = showLoading)
|
||||
return
|
||||
}
|
||||
val remotePkgName = this.mRemotePkgName
|
||||
|
||||
@ -43,14 +43,14 @@ class SpecialCatalogSubjectCollectionAdapter(
|
||||
}
|
||||
val entity = mList[position]
|
||||
ImageUtils.display(subjectCollectionImage, entity.image)
|
||||
subjectCollectionImage.loadingCallback = object : WrapContentDraweeView.LoadingCallback {
|
||||
subjectCollectionImage.registerLoadingCallback(object : WrapContentDraweeView.LoadingCallback {
|
||||
override fun loaded() {
|
||||
subjectCollectionImage.layoutParams = subjectCollectionImage.layoutParams.apply {
|
||||
height = 96F.dip2px()
|
||||
width = (subjectCollectionImage.aspectRatio * 96F.dip2px()).toInt()
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
root.setOnClickListener {
|
||||
DirectUtils.directToLinkPage(
|
||||
mContext,
|
||||
|
||||
@ -338,7 +338,7 @@ class CloudArchiveManagerActivity : BaseActivity_TabLayout() {
|
||||
btnText = getString(R.string.launch)
|
||||
setOnClickListener {
|
||||
CurrentActivityHolder.getCurrentActivity()?.let {
|
||||
VHelper.installOrLaunch(it, downloadEntity.packageName)
|
||||
VHelper.installOrLaunch(it, downloadEntity)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -7,6 +7,9 @@ import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.base.activity.ToolBarActivity
|
||||
import com.gh.gamecenter.common.constant.EntranceConsts
|
||||
import com.gh.gamecenter.common.utils.updateStatusBarColor
|
||||
import com.gh.gamecenter.feature.exposure.ExposureEvent
|
||||
import com.gh.gamecenter.feature.exposure.ExposureSource
|
||||
import java.util.ArrayList
|
||||
|
||||
/**
|
||||
* 猜你喜欢-发现页
|
||||
@ -27,9 +30,15 @@ class DiscoveryActivity : ToolBarActivity() {
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun getIntent(context: Context, entrance: String): Intent {
|
||||
fun getIntent(context: Context, entrance: String, exposureEvent: ExposureEvent? = null): Intent {
|
||||
val bundle = Bundle()
|
||||
bundle.putString(EntranceConsts.KEY_ENTRANCE, entrance)
|
||||
exposureEvent?.let {
|
||||
bundle.putParcelableArrayList(
|
||||
EntranceConsts.KEY_EXPOSURE_SOURCE_LIST,
|
||||
ArrayList(exposureEvent.source)
|
||||
)
|
||||
}
|
||||
return getTargetIntent(context, DiscoveryActivity::class.java, DiscoveryFragment::class.java, bundle)
|
||||
}
|
||||
}
|
||||
|
||||
@ -151,6 +151,8 @@ class DiscoveryFragment : LazyListFragment<DiscoveryItemData, DiscoveryViewModel
|
||||
override fun provideListAdapter(): ListAdapter<*> {
|
||||
val basicExposureSource = arrayListOf<ExposureSource>().apply {
|
||||
arguments?.getParcelable<ExposureSource>(EntranceConsts.KEY_EXPOSURE_SOURCE)?.let { add(it) }
|
||||
arguments?.getParcelableArrayList<ExposureSource>(EntranceConsts.KEY_EXPOSURE_SOURCE_LIST)
|
||||
?.let { addAll(it) }
|
||||
}
|
||||
val outerSequence = requireArguments().getInt(EntranceConsts.KEY_POSITION, -1)
|
||||
|
||||
|
||||
@ -52,7 +52,10 @@ class ForumDetailEntity(
|
||||
@SerializedName("_id")
|
||||
var id: String = "",
|
||||
var name: String = "",
|
||||
var permissions: String = ""
|
||||
var permissions: String = "",
|
||||
var icon: String = "",
|
||||
@SerializedName("icon_type")
|
||||
var iconType: String = ""
|
||||
) : Parcelable
|
||||
|
||||
fun convertForumDetailEntityToForumEntity(): ForumEntity {
|
||||
|
||||
@ -41,6 +41,10 @@ data class SubjectRecommendEntity(
|
||||
|
||||
var display: Display = Display(),
|
||||
|
||||
var img: String? = "",
|
||||
@SerializedName("tab_show_img")
|
||||
var showImgOnSelected: Boolean? = false, // 选中时是否显示图片
|
||||
|
||||
// local variable
|
||||
var useLightStyle: Boolean = false,
|
||||
var primaryColor: Int = Color.WHITE,
|
||||
|
||||
@ -5,6 +5,7 @@ import android.app.Activity
|
||||
import android.content.Intent
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.Color
|
||||
import android.graphics.Typeface
|
||||
import android.graphics.drawable.ColorDrawable
|
||||
import android.graphics.drawable.GradientDrawable
|
||||
import android.os.Build
|
||||
@ -14,10 +15,7 @@ import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.animation.AnimationUtils
|
||||
import android.widget.ImageView
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.PopupWindow
|
||||
import android.widget.TextView
|
||||
import android.widget.*
|
||||
import androidx.annotation.RequiresApi
|
||||
import androidx.appcompat.content.res.AppCompatResources
|
||||
import androidx.core.content.ContextCompat
|
||||
@ -57,6 +55,7 @@ import com.gh.gamecenter.core.iinterface.IScrollable
|
||||
import com.gh.gamecenter.core.runOnUiThread
|
||||
import com.gh.gamecenter.core.utils.*
|
||||
import com.gh.gamecenter.databinding.FragmentForumDetailBinding
|
||||
import com.gh.gamecenter.databinding.ItemForumSectionBinding
|
||||
import com.gh.gamecenter.databinding.PopupForumDetailSectionsBinding
|
||||
import com.gh.gamecenter.entity.*
|
||||
import com.gh.gamecenter.eventbus.EBForumFollowChange
|
||||
@ -75,6 +74,7 @@ import com.gh.gamecenter.qa.article.edit.ArticleEditActivity
|
||||
import com.gh.gamecenter.qa.questions.edit.QuestionEditActivity
|
||||
import com.gh.gamecenter.qa.video.publish.VideoPublishActivity
|
||||
import com.google.android.material.appbar.AppBarLayout
|
||||
import com.google.android.material.tabs.TabLayout
|
||||
import com.halo.assistant.fragment.WebFragment
|
||||
import org.greenrobot.eventbus.EventBus
|
||||
import org.greenrobot.eventbus.Subscribe
|
||||
@ -171,6 +171,8 @@ class ForumDetailFragment : BaseLazyTabFragment(), IScrollable {
|
||||
return FragmentStateAdapter(childFragmentManager, mFragmentsList, mTabTitleList)
|
||||
}
|
||||
|
||||
override fun provideIndicatorWidth(): Int = 16
|
||||
|
||||
override fun getInflatedLayout(): View {
|
||||
mBinding = FragmentForumDetailBinding.bind(layoutInflater.inflate(R.layout.fragment_forum_detail, null, false))
|
||||
return mBinding.root
|
||||
@ -373,6 +375,73 @@ class ForumDetailFragment : BaseLazyTabFragment(), IScrollable {
|
||||
LogUtils.uploadAccessToBbs(mBbsId, "论坛详情")
|
||||
}
|
||||
|
||||
override fun onFragmentFirstVisible() {
|
||||
mTabTitleList.clear()
|
||||
mFragmentsList.clear()
|
||||
|
||||
initTabTitleList(mTabTitleList)
|
||||
mFragmentsList.addAll(restoreFragments())
|
||||
if (mFragmentsList.isEmpty() || mFragmentsList.size != mTabTitleList.size) {
|
||||
mFragmentsList.clear()
|
||||
initFragmentList(mFragmentsList)
|
||||
}
|
||||
|
||||
mViewPager.offscreenPageLimit = mFragmentsList.size
|
||||
mViewPager.addOnPageChangeListener(this)
|
||||
mViewPager.adapter = providePagerAdapter()
|
||||
mViewPager.currentItem = mCheckedIndex
|
||||
mTabLayout.setupWithViewPager(mViewPager)
|
||||
mTabIndicatorView.setupWithTabLayout(mTabLayout)
|
||||
mTabIndicatorView.setupWithViewPager(mViewPager)
|
||||
mTabIndicatorView.setIndicatorWidth(provideIndicatorWidth())
|
||||
initTabLayout()
|
||||
mTabLayout.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener {
|
||||
override fun onTabSelected(tab: TabLayout.Tab) {
|
||||
updateTabStyle(tab, true)
|
||||
}
|
||||
|
||||
override fun onTabUnselected(tab: TabLayout.Tab) {
|
||||
updateTabStyle(tab, false)
|
||||
}
|
||||
|
||||
override fun onTabReselected(tab: TabLayout.Tab) {
|
||||
updateTabStyle(tab, true)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private fun initTabLayout() {
|
||||
for (i in 0 until mTabLayout.tabCount) {
|
||||
val tab = mTabLayout.getTabAt(i)
|
||||
if (tab != null) {
|
||||
tab.customView =
|
||||
BaseFragment_TabLayout.createDefaultTabCustomView(requireContext(), tab.text.toString())
|
||||
updateTabStyle(tab, i == mViewPager.currentItem)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateTabStyle(tab: TabLayout.Tab, isChecked: Boolean) {
|
||||
tab.customView?.findViewById<TextView>(R.id.tab_title)?.run {
|
||||
if (mShowZone && text == mTabTitleList[INDEX_TRENDS]) {
|
||||
compoundDrawablePadding = 2F.dip2px()
|
||||
setDrawableStart(
|
||||
AppCompatResources.getDrawable(
|
||||
requireContext(),
|
||||
if (isChecked) R.drawable.icon_raiders_selected else R.drawable.icon_raiders_default
|
||||
)
|
||||
)
|
||||
}
|
||||
textSize = 16F
|
||||
setTextColor(
|
||||
if (isChecked) R.color.text_title.toColor(requireContext()) else R.color.text_subtitle.toColor(
|
||||
requireContext()
|
||||
)
|
||||
)
|
||||
typeface = if (isChecked) Typeface.DEFAULT_BOLD else Typeface.DEFAULT
|
||||
}
|
||||
}
|
||||
|
||||
private fun initSection() {
|
||||
val sectionLayoutManager = LinearLayoutManager(requireContext(), RecyclerView.HORIZONTAL, false)
|
||||
mForumSectionAdapter = ForumSectionAdapter(requireContext(), mViewModel!!) {
|
||||
@ -394,7 +463,7 @@ class ForumDetailFragment : BaseLazyTabFragment(), IScrollable {
|
||||
mViewModel?.sectionListLiveData?.observe(this) {
|
||||
if (!it.isNullOrEmpty() && it.size >= 2) {
|
||||
mShowSections = true
|
||||
mBinding.sectionContainer.visibility = View.VISIBLE
|
||||
mBinding.sectionContainer.goneIf(mViewPager.currentItem != INDEX_ALL)
|
||||
if (mSectionId.isNotEmpty()) {
|
||||
it.forEachIndexed { index, section ->
|
||||
if (section.id == mSectionId) {
|
||||
@ -569,6 +638,7 @@ class ForumDetailFragment : BaseLazyTabFragment(), IScrollable {
|
||||
webBundle.putString(EntranceConsts.KEY_ENTRANCE, "游戏专区")
|
||||
webBundle.putString(EntranceConsts.KEY_URL, it.link)
|
||||
webBundle.putBoolean(WebFragment.KEY_OPEN_NATIVE_PAGE, true)
|
||||
webBundle.putString(EntranceConsts.KEY_BBS_ID, mBbsId)
|
||||
webBundle.putString(EntranceConsts.KEY_PATH, TAB_TRENDS)
|
||||
webFragment.arguments = webBundle
|
||||
mTrendsFragment = webFragment
|
||||
@ -586,6 +656,7 @@ class ForumDetailFragment : BaseLazyTabFragment(), IScrollable {
|
||||
mViewPager.adapter?.notifyDataSetChanged()
|
||||
mAskIndex = INDEX_ASK + 1
|
||||
mVideoIndex = INDEX_VIDEO + 1
|
||||
initTabLayout()
|
||||
|
||||
if (arguments?.getBoolean(EntranceConsts.KEY_SCROLL_TO_TRENDS, false) == true) {
|
||||
mViewPager.currentItem = INDEX_TRENDS
|
||||
@ -1016,12 +1087,12 @@ class ForumDetailFragment : BaseLazyTabFragment(), IScrollable {
|
||||
).apply { mPopupWindow = this }
|
||||
|
||||
mViewModel?.sectionListLiveData?.value?.forEachIndexed { index, section ->
|
||||
val item = getItemTextView(section.name)
|
||||
val item = getSectionItemView(section)
|
||||
binding.flexbox.addView(item)
|
||||
item.tag = section.name
|
||||
toggleHighlightedTextView(item, mViewModel?.selectedSection?.id == section.id)
|
||||
toggleHighlightedView(item, mViewModel?.selectedSection?.id == section.id)
|
||||
item.setOnClickListener {
|
||||
toggleHighlightedTextView(item, true)
|
||||
toggleHighlightedView(item, true)
|
||||
mViewModel?.selectedSection = section
|
||||
setSection(index)
|
||||
mForumSectionAdapter?.run {
|
||||
@ -1046,25 +1117,30 @@ class ForumDetailFragment : BaseLazyTabFragment(), IScrollable {
|
||||
popupWindow.showAsDropDown(mBinding.tabContainer, 0, 0)
|
||||
}
|
||||
|
||||
private fun toggleHighlightedTextView(targetTextView: TextView, highlightIt: Boolean) {
|
||||
private fun toggleHighlightedView(targetView: View, highlightIt: Boolean) {
|
||||
val sectionTv = targetView.findViewById<TextView>(R.id.sectionTv)
|
||||
if (highlightIt) {
|
||||
targetTextView.background = R.drawable.button_round_primary_light.toDrawable(requireContext())
|
||||
targetTextView.setTextColor(R.color.theme_font.toColor(requireContext()))
|
||||
targetView.background = R.drawable.button_round_primary_light.toDrawable(requireContext())
|
||||
sectionTv?.setTextColor(R.color.theme_font.toColor(requireContext()))
|
||||
} else {
|
||||
targetTextView.background = R.drawable.button_round_gray_light.toDrawable(requireContext())
|
||||
targetTextView.setTextColor(R.color.text_subtitle.toColor(requireContext()))
|
||||
targetView.background = R.drawable.button_round_gray_light.toDrawable(requireContext())
|
||||
sectionTv?.setTextColor(R.color.text_subtitle.toColor(requireContext()))
|
||||
}
|
||||
}
|
||||
|
||||
private fun getItemTextView(name: String): TextView {
|
||||
return TextView(requireContext()).apply {
|
||||
text = name
|
||||
includeFontPadding = false
|
||||
textSize = 12F
|
||||
gravity = Gravity.CENTER
|
||||
setPadding(12F.dip2px(), 0, 12F.dip2px(), 0)
|
||||
val params = LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, 24F.dip2px())
|
||||
layoutParams = params
|
||||
private fun getSectionItemView(entity: ForumDetailEntity.Section): View {
|
||||
return ItemForumSectionBinding.bind(
|
||||
LayoutInflater.from(requireContext()).inflate(R.layout.item_forum_section, null)
|
||||
).apply {
|
||||
iconIv.goneIf(entity.iconType.isEmpty() || entity.iconType == "none")
|
||||
when {
|
||||
entity.iconType == "url" && entity.icon.isNotEmpty() -> ImageUtils.display(iconIv, entity.icon)
|
||||
entity.iconType == "new" -> ImageUtils.display(iconIv, R.drawable.icon_section_newest)
|
||||
entity.iconType == "hot" -> ImageUtils.display(iconIv, R.drawable.icon_section_heat)
|
||||
}
|
||||
sectionTv.text = entity.name
|
||||
}.root.apply {
|
||||
layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, 24F.dip2px())
|
||||
}
|
||||
}
|
||||
|
||||
@ -1143,7 +1219,7 @@ class ForumDetailFragment : BaseLazyTabFragment(), IScrollable {
|
||||
for (i in 0 until mBinding.fragmentTabLayout.tabCount) {
|
||||
val tab = mBinding.fragmentTabLayout.getTabAt(i)
|
||||
if (tab != null) {
|
||||
BaseFragment_TabLayout.updateTabStyle(tab, tab.isSelected)
|
||||
updateTabStyle(tab, tab.isSelected)
|
||||
}
|
||||
}
|
||||
mForumSectionAdapter?.let { it.notifyItemRangeChanged(0, it.itemCount) }
|
||||
|
||||
@ -5,10 +5,7 @@ import android.view.ViewGroup
|
||||
import android.view.ViewGroup.MarginLayoutParams
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.utils.dip2px
|
||||
import com.gh.gamecenter.common.utils.toBinding
|
||||
import com.gh.gamecenter.common.utils.toColor
|
||||
import com.gh.gamecenter.common.utils.toDrawable
|
||||
import com.gh.gamecenter.common.utils.*
|
||||
import com.gh.gamecenter.databinding.ItemForumSectionBinding
|
||||
import com.gh.gamecenter.entity.ForumDetailEntity
|
||||
import com.lightgame.adapter.BaseRecyclerAdapter
|
||||
@ -30,26 +27,38 @@ class ForumSectionAdapter(context: Context, val viewModel: ForumDetailViewModel,
|
||||
|
||||
override fun onBindViewHolder(holder: ForumSectionItemViewHolder, position: Int) {
|
||||
val entity = mSectionList[position]
|
||||
holder.binding.root.run {
|
||||
layoutParams = (layoutParams as MarginLayoutParams).apply {
|
||||
leftMargin = if (position == 0) 16F.dip2px() else 6F.dip2px()
|
||||
}
|
||||
holder.binding.iconIv.goneIf(entity.iconType.isEmpty() || entity.iconType == "none")
|
||||
when {
|
||||
entity.iconType == "url" && entity.icon.isNotEmpty() -> ImageUtils.display(
|
||||
holder.binding.iconIv,
|
||||
entity.icon
|
||||
)
|
||||
|
||||
entity.iconType == "new" -> ImageUtils.display(holder.binding.iconIv, R.drawable.icon_section_newest)
|
||||
entity.iconType == "hot" -> ImageUtils.display(holder.binding.iconIv, R.drawable.icon_section_heat)
|
||||
}
|
||||
holder.binding.sectionTv.run {
|
||||
text = entity.name
|
||||
setTextColor(
|
||||
if (entity.id == viewModel.selectedSection.id) R.color.theme_font.toColor(mContext) else R.color.text_subtitle.toColor(
|
||||
mContext
|
||||
)
|
||||
)
|
||||
background =
|
||||
if (entity.id == viewModel.selectedSection.id) R.drawable.button_round_primary_light.toDrawable(mContext) else R.drawable.button_round_gray_light.toDrawable(
|
||||
mContext
|
||||
)
|
||||
setOnClickListener {
|
||||
viewModel.selectedSection = entity
|
||||
notifyItemRangeChanged(0, itemCount)
|
||||
onClick.invoke(position)
|
||||
}
|
||||
}
|
||||
holder.binding.root.run {
|
||||
layoutParams = (layoutParams as MarginLayoutParams).apply {
|
||||
leftMargin = if (position == 0) 16F.dip2px() else 6F.dip2px()
|
||||
}
|
||||
background =
|
||||
if (entity.id == viewModel.selectedSection.id) R.drawable.button_round_primary_light.toDrawable(mContext) else R.drawable.button_round_gray_light.toDrawable(
|
||||
mContext
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
class ForumSectionItemViewHolder(val binding: ItemForumSectionBinding) : RecyclerView.ViewHolder(binding.root)
|
||||
|
||||
@ -386,4 +386,9 @@ class ArticleItemVideoView @JvmOverloads constructor(context: Context, attrs: At
|
||||
fun getCurrentPosition(): Long {
|
||||
return mCurrentPosition
|
||||
}
|
||||
|
||||
override fun onDetachedFromWindow() {
|
||||
super.onDetachedFromWindow()
|
||||
mMuteDisposable?.dispose()
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@ -8,6 +8,7 @@ import com.gh.common.filter.RegionSettingHelper
|
||||
import com.gh.gamecenter.BuildConfig
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.retrofit.BiResponse
|
||||
import com.gh.gamecenter.common.utils.debugOnly
|
||||
import com.gh.gamecenter.common.utils.singleToMain
|
||||
import com.gh.gamecenter.common.utils.toColor
|
||||
import com.gh.gamecenter.entity.HomeDataEntity
|
||||
@ -26,12 +27,19 @@ class HomeSearchToolWrapperViewModel(application: Application) : AndroidViewMode
|
||||
val homeDataLiveData = MutableLiveData<HomeDataEntity>()
|
||||
val error = MutableLiveData<Exception>()
|
||||
|
||||
private var mHomeTabPosition: Int = -1
|
||||
private var mHomeTab: SubjectRecommendEntity? = null
|
||||
|
||||
var appBarOffset = 0
|
||||
|
||||
init {
|
||||
getHomeContentUnion()
|
||||
}
|
||||
|
||||
fun getHomeTabEntity() = mHomeTab
|
||||
|
||||
fun getHomeTabPosition() = mHomeTabPosition
|
||||
|
||||
@SuppressLint("CheckResult")
|
||||
fun getHomeContentUnion(isRefresh: Boolean = false) {
|
||||
RetrofitManager.getInstance().api
|
||||
@ -55,6 +63,8 @@ class HomeSearchToolWrapperViewModel(application: Application) : AndroidViewMode
|
||||
tab.isSlideEmpty = true
|
||||
tab.isTopViewShow = false
|
||||
}
|
||||
mHomeTab = tab
|
||||
mHomeTabPosition = index
|
||||
}
|
||||
|
||||
if (tab.type == "bbs") {
|
||||
|
||||
@ -111,7 +111,7 @@ class WelcomeDialogFragment : BaseDialogFragment() {
|
||||
dismissAllowingStateLoss()
|
||||
}
|
||||
|
||||
binding.ivOpeningCover.loadingCallback = object : WrapContentDraweeView.LoadingCallback {
|
||||
binding.ivOpeningCover.registerLoadingCallback(object : WrapContentDraweeView.LoadingCallback {
|
||||
override fun loaded() {
|
||||
binding.root.post {
|
||||
if (binding.ivOpeningCover.measuredHeight > binding.root.resources.displayMetrics.heightPixels * .8) {
|
||||
@ -121,7 +121,7 @@ class WelcomeDialogFragment : BaseDialogFragment() {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
binding.ivCloseBackup.setOnClickListener {
|
||||
dismissAllowingStateLoss()
|
||||
|
||||
@ -136,6 +136,9 @@ class GameFragment : LazyFragment() {
|
||||
arguments?.getParcelable<ExposureSource>(EntranceConsts.KEY_EXPOSURE_SOURCE)?.let {
|
||||
add(it)
|
||||
}
|
||||
arguments?.getParcelableArrayList<ExposureSource>(EntranceConsts.KEY_EXPOSURE_SOURCE_LIST)?.let {
|
||||
addAll(it)
|
||||
}
|
||||
add(
|
||||
ExposureSource(
|
||||
"板块",
|
||||
|
||||
@ -45,7 +45,7 @@ class GameColumnCollectionAdapter(
|
||||
|
||||
val data = mSubjectEntity.data!![position]
|
||||
ImageUtils.display(holder.binding.columnCollectionImage, data.image)
|
||||
holder.binding.columnCollectionImage.loadingCallback = object : WrapContentDraweeView.LoadingCallback {
|
||||
holder.binding.columnCollectionImage.registerLoadingCallback(object : WrapContentDraweeView.LoadingCallback {
|
||||
override fun loaded() {
|
||||
holder.binding.columnCollectionImage.layoutParams =
|
||||
holder.binding.columnCollectionImage.layoutParams.apply {
|
||||
@ -53,7 +53,7 @@ class GameColumnCollectionAdapter(
|
||||
width = (holder.binding.columnCollectionImage.aspectRatio * columnCollectionHeight).toInt()
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
holder.binding.columnCollectionImage.setOnClickListener {
|
||||
mClickClosure(position, data)
|
||||
|
||||
@ -14,7 +14,8 @@ class CommonCollectionDetailActivity : ToolBarActivity() {
|
||||
return getTargetIntent(
|
||||
this,
|
||||
CommonCollectionDetailActivity::class.java,
|
||||
CommonCollectionDetailFragment::class.java
|
||||
CommonCollectionDetailFragment::class.java,
|
||||
intent?.extras
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@ -28,7 +28,8 @@ class CommonCollectionDetailAdapter(
|
||||
val mViewModel: CommonCollectionDetailViewModel,
|
||||
val mBlockId: String,
|
||||
val mBlockName: String,
|
||||
val mEntrance: String
|
||||
val mEntrance: String,
|
||||
private val mBasicExposureSource: List<ExposureSource>?
|
||||
) : ListAdapter<CommonCollectionContentEntity>(context), IExposable {
|
||||
|
||||
private val mExposureEventSparseArray = SparseArray<ExposureEvent>()
|
||||
@ -98,13 +99,14 @@ class CommonCollectionDetailAdapter(
|
||||
if (linkEntity.type == "game") {
|
||||
mExposureEventSparseArray.put(
|
||||
position,
|
||||
ExposureEvent.createEvent(
|
||||
ExposureEvent.createEventWithSourceConcat(
|
||||
GameEntity(
|
||||
id = linkEntity.link,
|
||||
name = linkEntity.name
|
||||
).also {
|
||||
it.sequence = position
|
||||
},
|
||||
basicSource = mBasicExposureSource ?: listOf(),
|
||||
listOf(
|
||||
ExposureSource(
|
||||
"内容合集",
|
||||
|
||||
@ -21,6 +21,7 @@ import com.gh.gamecenter.common.view.GridSpacingItemDecoration
|
||||
import com.gh.gamecenter.common.view.VerticalItemDecoration
|
||||
import com.gh.gamecenter.databinding.FragmentListBaseSkeletonBinding
|
||||
import com.gh.gamecenter.common.entity.LinkEntity
|
||||
import com.gh.gamecenter.feature.exposure.ExposureSource
|
||||
|
||||
class CommonCollectionDetailFragment : LazyListFragment<LinkEntity, CommonCollectionDetailViewModel>() {
|
||||
|
||||
@ -47,13 +48,16 @@ class CommonCollectionDetailFragment : LazyListFragment<LinkEntity, CommonCollec
|
||||
|
||||
override fun provideListAdapter(): ListAdapter<*> {
|
||||
if (mAdapter == null) {
|
||||
val exposureEvent =
|
||||
requireArguments().getParcelableArrayList<ExposureSource>(EntranceConsts.KEY_EXPOSURE_SOURCE_LIST)
|
||||
mAdapter = CommonCollectionDetailAdapter(
|
||||
requireContext(),
|
||||
mCollectionStyle,
|
||||
mViewModel,
|
||||
mBlockId,
|
||||
mBlockName,
|
||||
mEntrance
|
||||
mEntrance,
|
||||
exposureEvent
|
||||
)
|
||||
}
|
||||
return mAdapter!!
|
||||
|
||||
@ -102,9 +102,9 @@ import org.greenrobot.eventbus.ThreadMode
|
||||
import retrofit2.HttpException
|
||||
import java.lang.ref.WeakReference
|
||||
import java.util.*
|
||||
import kotlin.collections.ArrayList
|
||||
import kotlin.math.abs
|
||||
|
||||
// TODO 更改现有的使用 INDEX_DESC, INDEX_BBS 等固定数值来确定 tab 位置的做法,避免后续更改 tab 位置出现奇怪的异常
|
||||
class GameDetailFragment : ToolbarFragment(), IScrollable {
|
||||
|
||||
private var mDownloadMenuIcon: ImageView? = null
|
||||
@ -118,7 +118,6 @@ class GameDetailFragment : ToolbarFragment(), IScrollable {
|
||||
private var mSearchMenuItem: MenuItem? = null
|
||||
private var mDownloadMenuItem: MenuItem? = null
|
||||
private var mTraceEvent: ExposureEvent? = null
|
||||
private var mFirstTimeSelected = true
|
||||
private var mIsTouchScreen = false
|
||||
private var mIsShowKaifuHint: Boolean = false
|
||||
private var mIsScrollToKaiFu: Boolean = false
|
||||
@ -150,6 +149,7 @@ class GameDetailFragment : ToolbarFragment(), IScrollable {
|
||||
|
||||
private val mFragmentsList = ArrayList<Fragment>()
|
||||
private val mTabTitleList = ArrayList<String>()
|
||||
private val mTabTypeList = ArrayList<String>() // tab 类型的列表,用于确定某个类型的 tab 在第几个位置
|
||||
private val mLooperHandle = LooperHandle(this)
|
||||
private val mServerLooperKey = 123
|
||||
|
||||
@ -217,6 +217,7 @@ class GameDetailFragment : ToolbarFragment(), IScrollable {
|
||||
detailViewHolder.mDownloadTips.setDownloadTipsAnimation(true)
|
||||
}
|
||||
}
|
||||
|
||||
DownloadStatus.done,
|
||||
DownloadStatus.pause,
|
||||
DownloadStatus.waiting,
|
||||
@ -227,6 +228,7 @@ class GameDetailFragment : ToolbarFragment(), IScrollable {
|
||||
detailViewHolder.mDownloadTips.visibility = View.VISIBLE
|
||||
detailViewHolder.mDownloadTips.setDownloadTipsAnimation(false)
|
||||
}
|
||||
|
||||
else -> detailViewHolder.mDownloadTips.visibility = View.GONE
|
||||
}
|
||||
}
|
||||
@ -275,6 +277,7 @@ class GameDetailFragment : ToolbarFragment(), IScrollable {
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
"func_libao" -> {
|
||||
mBodyBinding.gamedetailVp.currentItem = 0
|
||||
mBodyBinding.gamedetailAppbar.setExpanded(false, true)
|
||||
@ -283,6 +286,7 @@ class GameDetailFragment : ToolbarFragment(), IScrollable {
|
||||
fragment.scrollToLibao()
|
||||
}
|
||||
}
|
||||
|
||||
"func_related_version" -> {
|
||||
mBodyBinding.gamedetailVp.currentItem = 0
|
||||
mBodyBinding.gamedetailAppbar.setExpanded(false, true)
|
||||
@ -291,6 +295,7 @@ class GameDetailFragment : ToolbarFragment(), IScrollable {
|
||||
fragment.scrollToRelatedVersion()
|
||||
}
|
||||
}
|
||||
|
||||
"func_zone" -> {
|
||||
val gameDetailEntity = mViewModel.gameDetailLiveData.value?.data
|
||||
if (contentCardEntity.zoneTab && gameDetailEntity?.zone != null && gameDetailEntity.zone!!.style == "link") {
|
||||
@ -303,12 +308,14 @@ class GameDetailFragment : ToolbarFragment(), IScrollable {
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
"func_bbs" -> {
|
||||
val funcBbs = contentCardEntity.funcBbs
|
||||
funcBbs?.let {
|
||||
DirectUtils.directForumDetail(requireContext(), it.link, path)
|
||||
}
|
||||
}
|
||||
|
||||
"func_tool_kit" -> {
|
||||
if (contentCardEntity.toolkit.isNotEmpty()) {
|
||||
contentCardEntity.toolkit.safelyGetInRelease(0)?.let {
|
||||
@ -329,6 +336,7 @@ class GameDetailFragment : ToolbarFragment(), IScrollable {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
else -> DirectUtils.directToLinkPage(
|
||||
requireContext(),
|
||||
contentCardEntity.toLinkEntity(),
|
||||
@ -336,7 +344,10 @@ class GameDetailFragment : ToolbarFragment(), IScrollable {
|
||||
path,
|
||||
ExposureEvent.createEvent(
|
||||
null,
|
||||
listOf(ExposureSource("游戏详情", mGameEntity?.id ?: ""), ExposureSource("内容卡片", contentCardEntity.id))
|
||||
listOf(
|
||||
ExposureSource("游戏详情", mGameEntity?.id ?: ""),
|
||||
ExposureSource("内容卡片", contentCardEntity.id)
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
@ -420,7 +431,6 @@ class GameDetailFragment : ToolbarFragment(), IScrollable {
|
||||
mAutoDownload = args.getBoolean(EntranceConsts.KEY_AUTO_DOWNLOAD)
|
||||
mTraceEvent = args.getParcelable(EntranceConsts.KEY_TRACE_EVENT)
|
||||
mSkipGameComment = args.getBoolean(EntranceConsts.KEY_SKIP_GAME_COMMENT)
|
||||
mDestinationTab = if (mDestinationTab >= 0) mDestinationTab else args.getInt(EntranceConsts.KEY_TARGET, -1)
|
||||
mIsOpenPlatformWindow = args.getBoolean(EntranceConsts.KEY_OPEN_PLATFORM_WINDOW)
|
||||
|
||||
mSkeleton = Skeleton.bind(mBinding.listSkeleton)
|
||||
@ -445,13 +455,10 @@ class GameDetailFragment : ToolbarFragment(), IScrollable {
|
||||
mBodyBinding.gamedetailVp.doOnPageSelected { position ->
|
||||
if (!isAdded) return@doOnPageSelected
|
||||
|
||||
mBinding.gamedetailKaifuHint.visibleIf(mIsShowKaifuHint && position == INDEX_TRENDES)
|
||||
mBinding.gamedetailKaifuHint.visibleIf(mIsShowKaifuHint && position == getTabPositionFromTabType(TAB_TRENDS))
|
||||
|
||||
val bbsPosition = getTabPositionFromTabName(getString(R.string.game_detail_bbs))
|
||||
val trendsPosition = getTabPositionFromTabName(
|
||||
if (mNewGameDetailEntity?.zone?.customName.isNullOrEmpty()) getString(R.string.game_detail_dongtai) else mNewGameDetailEntity?.zone?.customName
|
||||
?: ""
|
||||
)
|
||||
val bbsPosition = getTabPositionFromTabType(TAB_BBS)
|
||||
val trendsPosition = getTabPositionFromTabType(TAB_TRENDS)
|
||||
|
||||
if (mNewGameDetailEntity?.bbsTab != null && position == bbsPosition) {
|
||||
DirectUtils.directToLinkPage(
|
||||
@ -468,7 +475,7 @@ class GameDetailFragment : ToolbarFragment(), IScrollable {
|
||||
}, 200)
|
||||
} else if (mNewGameDetailEntity?.zone != null && mNewGameDetailEntity?.zone?.style != "default" && position == trendsPosition && mNewGameDetailEntity?.bbsTab != null) {
|
||||
// 跳转论坛-专区
|
||||
val entrance = if (mDestinationTab == INDEX_TRENDES) {
|
||||
val entrance = if (mDestinationTab == getTabPositionFromTabType(TAB_TRENDS)) {
|
||||
if (mEntrance.contains("搜索")) "搜索页面" else "其他"
|
||||
} else "游戏详情页"
|
||||
mNewGameDetailEntity?.bbsTab?.link?.let {
|
||||
@ -755,6 +762,9 @@ class GameDetailFragment : ToolbarFragment(), IScrollable {
|
||||
val viewHolder = detailViewHolder
|
||||
DetailDownloadUtils.detailInitDownload(viewHolder, true)
|
||||
|
||||
mDestinationTab =
|
||||
getTabPositionFromTabType(arguments?.getString(EntranceConsts.KEY_TARGET, TAB_DESC) ?: TAB_DESC)
|
||||
|
||||
// destinationTab 的优先级最高,关注和关联关注在它的后面
|
||||
if (mDestinationTab != -1) {
|
||||
tabPerformClick(mDestinationTab)
|
||||
@ -855,6 +865,8 @@ class GameDetailFragment : ToolbarFragment(), IScrollable {
|
||||
|
||||
@SuppressLint("ClickableViewAccessibility")
|
||||
private fun initViewPage(data: NewGameDetailEntity) {
|
||||
// 各个 tab 显示的顺序为:详情>云存档>评价>专区>论坛
|
||||
|
||||
val scrollToLibao = arguments?.getBoolean(EntranceConsts.KEY_SCROLL_TO_LIBAO) ?: false
|
||||
var scrollToServer = arguments?.getBoolean(EntranceConsts.KEY_SCROLL_TO_SERVER) ?: false
|
||||
|
||||
@ -889,18 +901,37 @@ class GameDetailFragment : ToolbarFragment(), IScrollable {
|
||||
mTabTitleList.clear()
|
||||
|
||||
val tag = "android:switcher:${mBodyBinding.gamedetailVp.id}:"
|
||||
val descFragment = childFragmentManager.findFragmentByTag("${tag}$INDEX_DESC") ?: DescFragment()
|
||||
val descFragment = childFragmentManager.findFragmentByTag("${tag}$TAB_DESC") ?: DescFragment()
|
||||
descFragment.arguments = bundle
|
||||
mFragmentsList.add(descFragment)
|
||||
mTabTitleList.add(getString(R.string.game_detail_desc))
|
||||
mTabTypeList.add(TAB_DESC)
|
||||
|
||||
if (data.showArchive) {
|
||||
val cloudArchiveFragment =
|
||||
childFragmentManager.findFragmentByTag("${tag}${TAB_ARCHIVE}") ?: CloudArchiveFragment()
|
||||
bundle.putParcelable(EntranceConsts.KEY_GAME, mGameEntity ?: GameEntity())
|
||||
bundle.putString(EntranceConsts.KEY_ARCHIVE_CONFIG_URL, data.archiveTab.configUrl)
|
||||
cloudArchiveFragment.arguments = bundle
|
||||
mFragmentsList.add(cloudArchiveFragment)
|
||||
mTabTitleList.add(getString(R.string.game_detail_cloud_archive))
|
||||
mTabTypeList.add(TAB_ARCHIVE)
|
||||
|
||||
NewFlatLogUtils.logCloudArchiveGameDetailTabRelated(
|
||||
"cloud_save_tab_show",
|
||||
mGameEntity?.id ?: "",
|
||||
mGameEntity?.name ?: ""
|
||||
)
|
||||
}
|
||||
|
||||
if (data.showComment) {
|
||||
val ratingFragment = childFragmentManager.findFragmentByTag("${tag}${INDEX_RATING}") ?: RatingFragment()
|
||||
val ratingFragment = childFragmentManager.findFragmentByTag("${tag}${TAB_RATING}") ?: RatingFragment()
|
||||
bundle.putBoolean(EntranceConsts.KEY_SKIP_GAME_COMMENT, mSkipGameComment)
|
||||
bundle.putBoolean(EntranceConsts.KEY_DIRECT_COMMENT, data.directComment)
|
||||
ratingFragment.arguments = bundle
|
||||
mFragmentsList.add(ratingFragment)
|
||||
mTabTitleList.add(getString(R.string.game_detail_comment))
|
||||
mTabTypeList.add(TAB_RATING)
|
||||
}
|
||||
|
||||
data.zone?.let {
|
||||
@ -911,7 +942,7 @@ class GameDetailFragment : ToolbarFragment(), IScrollable {
|
||||
mFragmentsList.add(Fragment())
|
||||
} else if (it.style == "link") {
|
||||
//显示web页面
|
||||
val webFragment = childFragmentManager.findFragmentByTag("${tag}${INDEX_TRENDES}") ?: WebFragment()
|
||||
val webFragment = childFragmentManager.findFragmentByTag("${tag}${TAB_TRENDS}") ?: WebFragment()
|
||||
val webBundle = Bundle()
|
||||
webBundle.putString(EntranceConsts.KEY_ENTRANCE, "游戏专区")
|
||||
webBundle.putString(EntranceConsts.KEY_URL, it.link)
|
||||
@ -919,7 +950,7 @@ class GameDetailFragment : ToolbarFragment(), IScrollable {
|
||||
webFragment.arguments = webBundle
|
||||
mFragmentsList.add(webFragment)
|
||||
} else {
|
||||
val fuliFragment = childFragmentManager.findFragmentByTag("${tag}${INDEX_TRENDES}") ?: FuLiFragment()
|
||||
val fuliFragment = childFragmentManager.findFragmentByTag("${tag}${TAB_TRENDS}") ?: FuLiFragment()
|
||||
fuliFragment.arguments = bundle
|
||||
mFragmentsList.add(fuliFragment)
|
||||
}
|
||||
@ -928,22 +959,7 @@ class GameDetailFragment : ToolbarFragment(), IScrollable {
|
||||
} else {
|
||||
mTabTitleList.add(getString(R.string.game_detail_dongtai))
|
||||
}
|
||||
}
|
||||
|
||||
if (data.showArchive) {
|
||||
val cloudArchiveFragment =
|
||||
childFragmentManager.findFragmentByTag("${tag}${INDEX_ARCHIVE}") ?: CloudArchiveFragment()
|
||||
bundle.putParcelable(EntranceConsts.KEY_GAME, mGameEntity ?: GameEntity())
|
||||
bundle.putString(EntranceConsts.KEY_ARCHIVE_CONFIG_URL, data.archiveTab.configUrl)
|
||||
cloudArchiveFragment.arguments = bundle
|
||||
mFragmentsList.add(cloudArchiveFragment)
|
||||
mTabTitleList.add(getString(R.string.game_detail_cloud_archive))
|
||||
|
||||
NewFlatLogUtils.logCloudArchiveGameDetailTabRelated(
|
||||
"cloud_save_tab_show",
|
||||
mGameEntity?.id ?: "",
|
||||
mGameEntity?.name ?: ""
|
||||
)
|
||||
mTabTypeList.add(TAB_TRENDS)
|
||||
}
|
||||
|
||||
var isShowBbs = true
|
||||
@ -957,6 +973,7 @@ class GameDetailFragment : ToolbarFragment(), IScrollable {
|
||||
if (isShowBbs && mGameEntity?.shouldUseMirrorInfo() == false) {
|
||||
mFragmentsList.add(Fragment())
|
||||
mTabTitleList.add(getString(R.string.game_detail_bbs))
|
||||
mTabTypeList.add(TAB_BBS)
|
||||
}
|
||||
}
|
||||
|
||||
@ -969,7 +986,7 @@ class GameDetailFragment : ToolbarFragment(), IScrollable {
|
||||
gamedetailVp.doOnPageSelected {
|
||||
logTabClick(it)
|
||||
}
|
||||
gamedetailVp.currentItem = INDEX_DESC
|
||||
gamedetailVp.currentItem = getTabPositionFromTabType(TAB_DESC)
|
||||
|
||||
mBodyBinding.tabLayout.setupWithViewPager(gamedetailVp)
|
||||
mBodyBinding.tabIndicator.setupWithTabLayout(mBodyBinding.tabLayout)
|
||||
@ -978,7 +995,7 @@ class GameDetailFragment : ToolbarFragment(), IScrollable {
|
||||
for (i in 0 until mBodyBinding.tabLayout.tabCount) {
|
||||
val tab = mBodyBinding.tabLayout.getTabAt(i) ?: continue
|
||||
val tabTitle = if (tab.text != null) tab.text.toString() else ""
|
||||
if (data.showArchive && i == getTabPositionFromTabName(getString(R.string.game_detail_cloud_archive))) {
|
||||
if (data.showArchive && i == getTabPositionFromTabType(TAB_ARCHIVE)) {
|
||||
tab.customView = getArchiveTabView(tabTitle)
|
||||
tab.view.run {
|
||||
clipChildren = false
|
||||
@ -1081,7 +1098,7 @@ class GameDetailFragment : ToolbarFragment(), IScrollable {
|
||||
|
||||
if (mNewGameDetailEntity!!.showComment) {
|
||||
if (mSkipGameComment) {
|
||||
tabPerformClick(INDEX_RATING)
|
||||
tabPerformClick(getTabPositionFromTabType(TAB_RATING))
|
||||
mBodyBinding.gamedetailAppbar.setExpanded(false)
|
||||
mSkipGameComment = false
|
||||
}
|
||||
@ -1288,8 +1305,10 @@ class GameDetailFragment : ToolbarFragment(), IScrollable {
|
||||
when {
|
||||
isHighlightBg && !isLastView -> root.background =
|
||||
R.drawable.bg_content_card_large_primary.toDrawable(requireContext())
|
||||
|
||||
!isHighlightBg && !isLastView -> root.background =
|
||||
R.drawable.bg_content_card_large.toDrawable(requireContext())
|
||||
|
||||
!isHighlightBg && isLastView -> root.background =
|
||||
R.drawable.bg_content_card_large_right.toDrawable(requireContext())
|
||||
}
|
||||
@ -1348,7 +1367,10 @@ class GameDetailFragment : ToolbarFragment(), IScrollable {
|
||||
ExposureManager.log(
|
||||
ExposureEvent.createEvent(
|
||||
GameEntity(sequence = position),
|
||||
listOf(ExposureSource("游戏详情", mGameEntity?.id ?: ""), ExposureSource("内容卡片", contentCardEntity.id))
|
||||
listOf(
|
||||
ExposureSource("游戏详情", mGameEntity?.id ?: ""),
|
||||
ExposureSource("内容卡片", contentCardEntity.id)
|
||||
)
|
||||
)
|
||||
)
|
||||
}.root
|
||||
@ -1383,7 +1405,10 @@ class GameDetailFragment : ToolbarFragment(), IScrollable {
|
||||
ExposureManager.log(
|
||||
ExposureEvent.createEvent(
|
||||
GameEntity(sequence = position),
|
||||
listOf(ExposureSource("游戏详情", mGameEntity?.id ?: ""), ExposureSource("内容卡片", contentCardEntity.id))
|
||||
listOf(
|
||||
ExposureSource("游戏详情", mGameEntity?.id ?: ""),
|
||||
ExposureSource("内容卡片", contentCardEntity.id)
|
||||
)
|
||||
)
|
||||
)
|
||||
}.root
|
||||
@ -1536,19 +1561,19 @@ class GameDetailFragment : ToolbarFragment(), IScrollable {
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
fun onEventMainThread(reuse: EBReuse) {
|
||||
if (SKIP_DESC == reuse.type) {
|
||||
tabPerformClick(INDEX_DESC)
|
||||
tabPerformClick(getTabPositionFromTabType(TAB_DESC))
|
||||
} else if (OPEN_APPBAR == reuse.type && !mIsTouchScreen) {
|
||||
mBodyBinding.gamedetailAppbar.setExpanded(true, true)
|
||||
} else if (SKIP_FULI == reuse.type) {
|
||||
tabPerformClick(INDEX_TRENDES)
|
||||
tabPerformClick(getTabPositionFromTabType(TAB_TRENDS))
|
||||
} else if (SKIP_RATING == reuse.type) {
|
||||
tabPerformClick(INDEX_RATING)
|
||||
tabPerformClick(getTabPositionFromTabType(TAB_RATING))
|
||||
} else if ("hideKaifuHint" == reuse.type) {
|
||||
mIsShowKaifuHint = false
|
||||
mBinding.gamedetailKaifuHint.visibility = View.GONE
|
||||
} else if ("showKaifuHint" == reuse.type) {
|
||||
mIsShowKaifuHint = true
|
||||
if (mCurVpPosition == INDEX_TRENDES) {
|
||||
if (mCurVpPosition == getTabPositionFromTabType(TAB_TRENDS)) {
|
||||
mBinding.gamedetailKaifuHint.post { mBinding.gamedetailKaifuHint.visibility = View.VISIBLE }
|
||||
}
|
||||
} else if (CLOSE_APPBAR == reuse.type && !mIsTouchScreen) {
|
||||
@ -1807,28 +1832,29 @@ class GameDetailFragment : ToolbarFragment(), IScrollable {
|
||||
}
|
||||
|
||||
private fun tabPerformClick(position: Int) {
|
||||
val trendsTabPosition = getTabPositionFromTabType(TAB_TRENDS)
|
||||
val bbsTabPosition = getTabPositionFromTabType(TAB_BBS)
|
||||
|
||||
when (position) {
|
||||
INDEX_TRENDES -> {
|
||||
trendsTabPosition -> {
|
||||
val zoneEntity = mNewGameDetailEntity?.zone
|
||||
if (!mTabTitleList.contains(getString(R.string.game_detail_dongtai))
|
||||
&& !mTabTitleList.contains(zoneEntity?.customName)
|
||||
) {
|
||||
performJumpContentCard("func_zone")
|
||||
} else {
|
||||
mBodyBinding.gamedetailVp.currentItem = getTabPositionFromTabName(
|
||||
if (mNewGameDetailEntity?.zone?.customName.isNullOrEmpty()) getString(R.string.game_detail_dongtai) else mNewGameDetailEntity?.zone?.customName
|
||||
?: ""
|
||||
)
|
||||
mBodyBinding.gamedetailVp.currentItem = getTabPositionFromTabType(TAB_TRENDS)
|
||||
}
|
||||
}
|
||||
INDEX_BBS -> {
|
||||
|
||||
bbsTabPosition -> {
|
||||
if (!mTabTitleList.contains(getString(R.string.game_detail_bbs))) {
|
||||
performJumpContentCard("func_bbs")
|
||||
} else {
|
||||
mBodyBinding.gamedetailVp.currentItem =
|
||||
getTabPositionFromTabName(getString(R.string.game_detail_bbs))
|
||||
mBodyBinding.gamedetailVp.currentItem = getTabPositionFromTabType(TAB_BBS)
|
||||
}
|
||||
}
|
||||
|
||||
else -> {
|
||||
mBodyBinding.gamedetailVp.currentItem = position
|
||||
}
|
||||
@ -1850,10 +1876,11 @@ class GameDetailFragment : ToolbarFragment(), IScrollable {
|
||||
|
||||
val entrance = if (mEntrance.contains("论坛详情")) "论坛" else "游戏"
|
||||
mGameEntity?.run {
|
||||
when (getTabContentForReal(position)) {
|
||||
when (mTabTypeList[position]) {
|
||||
TAB_DESC -> {
|
||||
NewLogUtils.logGameDetailTabClick(name ?: "", id, "详情")
|
||||
}
|
||||
|
||||
TAB_TRENDS -> {
|
||||
NewLogUtils.logGameDetailTabClick(
|
||||
"view_game_detail_special_area_tab",
|
||||
@ -1864,6 +1891,7 @@ class GameDetailFragment : ToolbarFragment(), IScrollable {
|
||||
)
|
||||
NewLogUtils.logGameDetailTabClick(name ?: "", id, "专区")
|
||||
}
|
||||
|
||||
TAB_ARCHIVE -> {
|
||||
NewFlatLogUtils.logCloudArchiveGameDetailTabRelated(
|
||||
"cloud_save_tab_click",
|
||||
@ -1882,10 +1910,12 @@ class GameDetailFragment : ToolbarFragment(), IScrollable {
|
||||
"last_page_business_id", getLastPageEntity().pageBusinessId
|
||||
)
|
||||
}
|
||||
|
||||
TAB_RATING -> {
|
||||
NewLogUtils.logGameDetailTabClick("view_game_detail_comment_tab", entrance, id, gameType, bbsId)
|
||||
NewLogUtils.logGameDetailTabClick(name ?: "", id, "评论")
|
||||
}
|
||||
|
||||
TAB_BBS -> {
|
||||
NewLogUtils.logGameDetailTabClick(name ?: "", id, "论坛")
|
||||
}
|
||||
@ -1893,35 +1923,13 @@ class GameDetailFragment : ToolbarFragment(), IScrollable {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取真实的 tab 内容类型
|
||||
* @param position tab 的位置
|
||||
* @return 真实的 tab 类型
|
||||
*/
|
||||
private fun getTabContentForReal(position: Int): String {
|
||||
return when (mTabTitleList[position]) {
|
||||
getString(R.string.game_detail_dongtai),
|
||||
mNewGameDetailEntity?.zone?.customName -> TAB_TRENDS
|
||||
|
||||
getString(R.string.game_detail_cloud_archive) -> TAB_ARCHIVE
|
||||
|
||||
getString(R.string.game_detail_comment) -> TAB_RATING
|
||||
|
||||
getString(R.string.game_detail_bbs) -> TAB_BBS
|
||||
|
||||
getString(R.string.game_detail_desc) -> TAB_DESC
|
||||
|
||||
else -> TAB_DESC
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 tab 的位置
|
||||
* @param tabName tab 名字
|
||||
* @param tabType tab 类型
|
||||
* @return tab 的真实位置
|
||||
*/
|
||||
private fun getTabPositionFromTabName(tabName: String): Int {
|
||||
return mTabTitleList.indexOf(tabName)
|
||||
private fun getTabPositionFromTabType(tabType: String): Int {
|
||||
return mTabTypeList.indexOf(tabType)
|
||||
}
|
||||
|
||||
private fun handleTabTouchEvent(title: String) {
|
||||
@ -1938,8 +1946,9 @@ class GameDetailFragment : ToolbarFragment(), IScrollable {
|
||||
getString(R.string.game_detail_comment),
|
||||
getString(R.string.game_detail_cloud_archive) -> {
|
||||
mBodyBinding.gamedetailAppbar.setExpanded(false, true)
|
||||
tabPerformClick(getTabPositionFromTabName(title))
|
||||
tabPerformClick(getTabPositionFromTabType(title))
|
||||
}
|
||||
|
||||
else -> {
|
||||
// do nothing
|
||||
}
|
||||
@ -1971,7 +1980,8 @@ class GameDetailFragment : ToolbarFragment(), IScrollable {
|
||||
} else {
|
||||
hintText =
|
||||
if (SPUtils.getBoolean(Constants.SP_USE_BROWSER_TO_INSTALL)) "当前安装方式为[浏览器安装],点击切换安装方式" else "手机如何解决无法安装问题"
|
||||
closeHintText = "关闭后“切换安装方式”入口将显示在左下角,您也可以前往“我的光环-设置-切换安装方式”进行设置"
|
||||
closeHintText =
|
||||
"关闭后“切换安装方式”入口将显示在左下角,您也可以前往“我的光环-设置-切换安装方式”进行设置"
|
||||
}
|
||||
|
||||
mDownloadBinding.browserInstallHintTv.text = hintText
|
||||
@ -2056,7 +2066,7 @@ class GameDetailFragment : ToolbarFragment(), IScrollable {
|
||||
mRecommendBinding.recommendText.text = popupDetail.text
|
||||
if (popupDetail.images.isNotEmpty()) {
|
||||
ImageUtils.display(mRecommendBinding.recommendImage, popupDetail.images[0])
|
||||
mRecommendBinding.recommendImage.loadingCallback = object : WrapContentDraweeView.LoadingCallback {
|
||||
mRecommendBinding.recommendImage.registerLoadingCallback(object : WrapContentDraweeView.LoadingCallback {
|
||||
override fun loaded() {
|
||||
mRecommendBinding.recommendImage.post {
|
||||
mRecommendBinding.recommendImage.layoutParams.apply {
|
||||
@ -2066,7 +2076,7 @@ class GameDetailFragment : ToolbarFragment(), IScrollable {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
} else {
|
||||
mRecommendBinding.recommendImage.visibility = View.GONE
|
||||
(mRecommendBinding.recommendText.layoutParams as ConstraintLayout.LayoutParams).apply {
|
||||
@ -2151,7 +2161,7 @@ class GameDetailFragment : ToolbarFragment(), IScrollable {
|
||||
|
||||
private fun updateArchiveTabUI() {
|
||||
mBodyBinding.tabLayout.run {
|
||||
val archivePosition = getTabPositionFromTabName(getString(R.string.game_detail_cloud_archive))
|
||||
val archivePosition = getTabPositionFromTabType(TAB_ARCHIVE)
|
||||
getTabAt(archivePosition)?.customView?.findViewById<ImageView>(R.id.newIv)?.visibility = View.VISIBLE
|
||||
}
|
||||
}
|
||||
@ -2168,11 +2178,13 @@ class GameDetailFragment : ToolbarFragment(), IScrollable {
|
||||
override fun onBackPressed(): Boolean {
|
||||
mOrientationUtils?.backToProtVideo()
|
||||
|
||||
if (mBodyBinding.gamedetailVp.currentItem == INDEX_TRENDES
|
||||
&& mFragmentsList[INDEX_TRENDES] is WebFragment
|
||||
&& mFragmentsList[INDEX_TRENDES].isAdded
|
||||
val trendsTabPosition = getTabPositionFromTabType(TAB_TRENDS)
|
||||
|
||||
if (mBodyBinding.gamedetailVp.currentItem == trendsTabPosition
|
||||
&& mFragmentsList[trendsTabPosition] is WebFragment
|
||||
&& mFragmentsList[trendsTabPosition].isAdded
|
||||
) {
|
||||
return (mFragmentsList[INDEX_TRENDES] as WebFragment).onBackPressed()
|
||||
return (mFragmentsList[trendsTabPosition] as WebFragment).onBackPressed()
|
||||
}
|
||||
|
||||
if (CustomManager.backFromWindowFull(requireActivity(), mVideoBinding.player.getKey())) {
|
||||
@ -2349,12 +2361,6 @@ class GameDetailFragment : ToolbarFragment(), IScrollable {
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val INDEX_DESC = 0
|
||||
const val INDEX_RATING = 1
|
||||
const val INDEX_ARCHIVE = 2
|
||||
const val INDEX_TRENDES = 3
|
||||
const val INDEX_BBS = 4
|
||||
|
||||
const val TAB_DESC = "详情"
|
||||
const val TAB_TRENDS = "专区"
|
||||
const val TAB_ARCHIVE = "云存档"
|
||||
@ -2368,7 +2374,6 @@ class GameDetailFragment : ToolbarFragment(), IScrollable {
|
||||
const val CLOSE_APPBAR = "closeappbar"
|
||||
const val SCROLL_TO_KAIFU = "scrollToKaiFu"
|
||||
const val EB_SCROLLING = "EB_SCROLLING"
|
||||
const val EB_STAR = "eb_star"
|
||||
const val INITIAL_DELAY = 500L
|
||||
const val CONTENT_CARD_LOOP_TIME = 3000L
|
||||
|
||||
|
||||
@ -208,127 +208,143 @@ class GameDetailViewModel(
|
||||
}
|
||||
|
||||
private fun replaceWithMirrorInfoIfNeeded(data: NewGameDetailEntity) {
|
||||
if (data.mirrorStatus == "on"
|
||||
&& (game?.useMirrorInfo == true
|
||||
|| RegionSettingHelper.shouldThisGameDisplayMirrorInfo(game?.id ?: ""))
|
||||
) {
|
||||
val finalItemList: ArrayList<DetailEntity> = arrayListOf()
|
||||
val mirrorCustomColumnList = data.mirrorData?.customColumnList ?: arrayListOf()
|
||||
mirrorCustomColumnList.sortByDescending { it.order }
|
||||
for (item in data.detailEntity) {
|
||||
// 去掉所有自定义栏目并把镜像相应权重的自定义栏目放到相应的位置
|
||||
if (item.type == DetailEntity.Type.CUSTOM_COLUMN.value) {
|
||||
val usedMirrorCustomColumnList = arrayListOf<CustomColumn>()
|
||||
for (mirrorCustomColumn in mirrorCustomColumnList) {
|
||||
if ((mirrorCustomColumn.order!! > 0 && item.customColumn?.order!! > 0)
|
||||
|| (mirrorCustomColumn.order == item.customColumn?.order)
|
||||
) {
|
||||
finalItemList.add(
|
||||
DetailEntity(
|
||||
type = DetailEntity.Type.CUSTOM_COLUMN.value,
|
||||
customColumn = mirrorCustomColumn
|
||||
)
|
||||
// 获取镜像相关数据,不存在时不替换
|
||||
val mirrorData = getMirrorData(data) ?: return
|
||||
|
||||
val finalItemList: ArrayList<DetailEntity> = arrayListOf()
|
||||
val mirrorCustomColumnList = mirrorData.customColumnList ?: arrayListOf()
|
||||
mirrorCustomColumnList.sortByDescending { it.order }
|
||||
for (item in data.detailEntity) {
|
||||
// 去掉所有自定义栏目并把镜像相应权重的自定义栏目放到相应的位置
|
||||
if (item.type == DetailEntity.Type.CUSTOM_COLUMN.value) {
|
||||
val usedMirrorCustomColumnList = arrayListOf<CustomColumn>()
|
||||
for (mirrorCustomColumn in mirrorCustomColumnList) {
|
||||
if ((mirrorCustomColumn.order!! > 0 && item.customColumn?.order!! > 0)
|
||||
|| (mirrorCustomColumn.order == item.customColumn?.order)
|
||||
) {
|
||||
finalItemList.add(
|
||||
DetailEntity(
|
||||
type = DetailEntity.Type.CUSTOM_COLUMN.value,
|
||||
customColumn = mirrorCustomColumn
|
||||
)
|
||||
usedMirrorCustomColumnList.add(mirrorCustomColumn)
|
||||
}
|
||||
}
|
||||
mirrorCustomColumnList.removeAll(usedMirrorCustomColumnList)
|
||||
continue
|
||||
}
|
||||
|
||||
// 历史版本入口
|
||||
if (item.type == DetailEntity.Type.UPDATE_CONTENT.value) {
|
||||
item.update?.historyApkStatus = "off"
|
||||
}
|
||||
|
||||
// 不显示 "玩家评论`", "相关游戏`"
|
||||
if (item.type == DetailEntity.Type.COMMENTS.value ||
|
||||
item.type == DetailEntity.Type.RELATED_VERSION.value
|
||||
) {
|
||||
continue
|
||||
}
|
||||
|
||||
// 处理游戏信息区域
|
||||
if (item.type == DetailEntity.Type.GAME_INFO.value) {
|
||||
item.info?.manufacturer = data.mirrorData?.manufacturer ?: ""
|
||||
item.info?.privacyPolicyUrl = data.mirrorData?.privacyPolicyUrl ?: ""
|
||||
item.info?.manufacturerType = data.mirrorData?.manufacturerType ?: ""
|
||||
item.info?.publisher = data.mirrorData?.publisher ?: ""
|
||||
item.info?.developer = data.mirrorData?.developer ?: ""
|
||||
item.info?.supplier = data.mirrorData?.supplier ?: ""
|
||||
item.info?.creditCode = data.mirrorData?.creditCode ?: ""
|
||||
item.info?.updateTime = data.mirrorData?.updateTime ?: 0L
|
||||
finalItemList.add(item)
|
||||
continue
|
||||
}
|
||||
|
||||
// 去掉游戏信息里的 "mod 版"
|
||||
if (item.type == DetailEntity.Type.GAME_INFO.value) {
|
||||
item.info?.topTags?.removeAll { it.name.toLowerCase(Locale.getDefault()) == "mod版" }
|
||||
}
|
||||
|
||||
// 替换镜像开服信息
|
||||
if (item.type == DetailEntity.Type.LATEST_SERVER.value && data.mirrorData?.server != null) {
|
||||
if (data.mirrorData?.server?.status == "hide") {
|
||||
continue
|
||||
} else {
|
||||
item.server = data.mirrorData?.server
|
||||
}
|
||||
}
|
||||
|
||||
// 镜像游戏去掉推荐游戏 (用于构建大家都在玩)
|
||||
if (item.type == DetailEntity.Type.RECOMMENDED_GAMES.value) {
|
||||
continue
|
||||
}
|
||||
|
||||
finalItemList.add(item)
|
||||
}
|
||||
|
||||
val funcServer = data.contentCard.find { it.type == "func_server" }
|
||||
if (funcServer?.mirrorServer != null) {
|
||||
funcServer.server = funcServer.mirrorServer
|
||||
}
|
||||
|
||||
// 有多余的镜像自定义栏目没找到位置放,统一按权重为0放到详细信息后,连权重为0也没有就放到列表最后!
|
||||
if (!mirrorCustomColumnList.isNullOrEmpty()) {
|
||||
var gameInfoPosition = finalItemList.size - 1
|
||||
for ((index, item) in finalItemList.withIndex()) {
|
||||
if (item.type == DetailEntity.Type.GAME_INFO.value) {
|
||||
gameInfoPosition = index + 1
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
for ((index, remainingMirrorCustomColumn) in mirrorCustomColumnList.withIndex()) {
|
||||
finalItemList.add(
|
||||
gameInfoPosition + index,
|
||||
DetailEntity(
|
||||
type = DetailEntity.Type.CUSTOM_COLUMN.value,
|
||||
customColumn = remainingMirrorCustomColumn
|
||||
)
|
||||
)
|
||||
usedMirrorCustomColumnList.add(mirrorCustomColumn)
|
||||
}
|
||||
}
|
||||
mirrorCustomColumnList.removeAll(usedMirrorCustomColumnList)
|
||||
continue
|
||||
}
|
||||
|
||||
// 历史版本入口
|
||||
if (item.type == DetailEntity.Type.UPDATE_CONTENT.value) {
|
||||
item.update?.historyApkStatus = "off"
|
||||
}
|
||||
|
||||
// 不显示 "玩家评论`", "相关游戏`"
|
||||
if (item.type == DetailEntity.Type.COMMENTS.value ||
|
||||
item.type == DetailEntity.Type.RELATED_VERSION.value
|
||||
) {
|
||||
continue
|
||||
}
|
||||
|
||||
// 处理游戏信息区域
|
||||
if (item.type == DetailEntity.Type.GAME_INFO.value) {
|
||||
item.info?.manufacturer = mirrorData.manufacturer ?: ""
|
||||
item.info?.privacyPolicyUrl = mirrorData.privacyPolicyUrl ?: ""
|
||||
item.info?.manufacturerType = mirrorData.manufacturerType
|
||||
item.info?.publisher = mirrorData.publisher
|
||||
item.info?.developer = mirrorData.developer
|
||||
item.info?.supplier = mirrorData.supplier
|
||||
item.info?.creditCode = mirrorData.creditCode
|
||||
item.info?.updateTime = mirrorData.updateTime
|
||||
finalItemList.add(item)
|
||||
continue
|
||||
}
|
||||
|
||||
// 去掉游戏信息里的 "mod 版"
|
||||
if (item.type == DetailEntity.Type.GAME_INFO.value) {
|
||||
item.info?.topTags?.removeAll { it.name.toLowerCase(Locale.getDefault()) == "mod版" }
|
||||
}
|
||||
|
||||
// 替换镜像开服信息
|
||||
if (item.type == DetailEntity.Type.LATEST_SERVER.value && mirrorData.server != null) {
|
||||
if (mirrorData.server?.status == "hide") {
|
||||
continue
|
||||
} else {
|
||||
item.server = mirrorData.server
|
||||
}
|
||||
}
|
||||
|
||||
// 不显示评论 tab
|
||||
data.showComment = false
|
||||
|
||||
for (item in finalItemList) {
|
||||
item.des = data.mirrorData?.des
|
||||
item.gallery = data.mirrorData?.gallery
|
||||
|
||||
item.update?.updateDes = data.mirrorData?.updateDes ?: ""
|
||||
|
||||
item.info?.size = data.mirrorData?.apk?.firstOrNull()?.size ?: ""
|
||||
item.info?.version = data.mirrorData?.apk?.firstOrNull()?.version ?: ""
|
||||
// 镜像游戏去掉推荐游戏 (用于构建大家都在玩)
|
||||
if (item.type == DetailEntity.Type.RECOMMENDED_GAMES.value) {
|
||||
continue
|
||||
}
|
||||
|
||||
data.tagStyle =
|
||||
data.mirrorData?.tagStyle?.apply { removeAll { it.name.toLowerCase(Locale.getDefault()) == "mod版" } }
|
||||
?: arrayListOf()
|
||||
data.detailDialogs = data.mirrorData?.detailDialogs ?: arrayListOf()
|
||||
data.detailEntity = finalItemList
|
||||
finalItemList.add(item)
|
||||
}
|
||||
|
||||
val funcServer = data.contentCard.find { it.type == "func_server" }
|
||||
if (funcServer?.mirrorServer != null) {
|
||||
funcServer.server = funcServer.mirrorServer
|
||||
}
|
||||
|
||||
// 有多余的镜像自定义栏目没找到位置放,统一按权重为0放到详细信息后,连权重为0也没有就放到列表最后!
|
||||
if (!mirrorCustomColumnList.isNullOrEmpty()) {
|
||||
var gameInfoPosition = finalItemList.size - 1
|
||||
for ((index, item) in finalItemList.withIndex()) {
|
||||
if (item.type == DetailEntity.Type.GAME_INFO.value) {
|
||||
gameInfoPosition = index + 1
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
for ((index, remainingMirrorCustomColumn) in mirrorCustomColumnList.withIndex()) {
|
||||
finalItemList.add(
|
||||
gameInfoPosition + index,
|
||||
DetailEntity(
|
||||
type = DetailEntity.Type.CUSTOM_COLUMN.value,
|
||||
customColumn = remainingMirrorCustomColumn
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// 不显示评论 tab
|
||||
data.showComment = false
|
||||
|
||||
for (item in finalItemList) {
|
||||
item.des = mirrorData.des
|
||||
item.gallery = mirrorData.gallery
|
||||
|
||||
item.update?.updateDes = mirrorData.updateDes
|
||||
|
||||
item.info?.size = mirrorData.apk?.firstOrNull()?.size ?: ""
|
||||
item.info?.version = mirrorData.apk?.firstOrNull()?.version ?: ""
|
||||
}
|
||||
|
||||
data.tagStyle =
|
||||
mirrorData.tagStyle.apply { removeAll { it.name.toLowerCase(Locale.getDefault()) == "mod版" } }
|
||||
data.detailDialogs = mirrorData.detailDialogs
|
||||
data.detailEntity = finalItemList
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取镜像数据,为空时代表不启用镜像
|
||||
*/
|
||||
private fun getMirrorData(data: NewGameDetailEntity): DetailEntity? {
|
||||
// 游戏 id
|
||||
val id = game?.id ?: ""
|
||||
|
||||
if (RegionSettingHelper.shouldThisGameDisplayMirrorInfo(id) || game?.useMirrorInfo == true) {
|
||||
if (data.mirrorStatus == "on" || data.mirrorStatus2 == "on") {
|
||||
when (RegionSettingHelper.getMirrorPosition(id)) {
|
||||
1 -> return data.mirrorData
|
||||
2 -> return data.mirrorData2
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -50,7 +50,7 @@ class GameGalleryAdapter(
|
||||
is GameGalleryViewHolder -> {
|
||||
holder.binding.screenshotItemIv.setTag(ImageUtils.TAG_TARGET_WIDTH, 260F.dip2px())
|
||||
ImageUtils.display(holder.binding.screenshotItemIv, mGallery?.get(position))
|
||||
holder.binding.screenshotItemIv.loadingCallback = object : WrapContentDraweeView.LoadingCallback {
|
||||
holder.binding.screenshotItemIv.registerLoadingCallback(object : WrapContentDraweeView.LoadingCallback {
|
||||
override fun loaded() {
|
||||
holder.binding.screenshotItemIv.post {
|
||||
holder.binding.screenshotItemIv.layoutParams.apply {
|
||||
@ -63,7 +63,7 @@ class GameGalleryAdapter(
|
||||
holder.itemView.requestLayout()
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
holder.itemView.setDebouncedClickListener {
|
||||
DataCollectionUtils.uploadClick(context, "游戏介绍", "游戏详情")
|
||||
MtaHelper.onEvent("游戏详情_新", "点击游戏截图", mGame.name)
|
||||
|
||||
@ -40,6 +40,10 @@ class NewGameDetailEntity(
|
||||
var mirrorStatus: String? = "",
|
||||
@SerializedName("mirror_data")
|
||||
var mirrorData: DetailEntity? = null,
|
||||
@SerializedName("mirror_status2")
|
||||
var mirrorStatus2: String? = "",
|
||||
@SerializedName("mirror_data2")
|
||||
var mirrorData2: DetailEntity? = null,
|
||||
@SerializedName("bbs_tab")
|
||||
var bbsTab: LinkEntity? = null,
|
||||
@SerializedName("certification_tag")
|
||||
|
||||
@ -52,6 +52,7 @@ class TopVideoView @JvmOverloads constructor(context: Context, attrs: AttributeS
|
||||
private var mMuteDisposable: Disposable? = null
|
||||
private var mContentLength = 0.0
|
||||
private var mIsAutoPlay = false
|
||||
private var mLastGetContentLengthTime = 0L
|
||||
|
||||
val combinedTitleAndId: String
|
||||
get() = StringUtils.combineTwoString(video?.title, video?.videoId)
|
||||
@ -527,7 +528,11 @@ class TopVideoView @JvmOverloads constructor(context: Context, attrs: AttributeS
|
||||
val videoTotalTime = duration / 1000
|
||||
val progress = if (videoTotalTime != 0) videoPlayTs.toFloat() / videoTotalTime.toFloat() * 100 else 0f
|
||||
if (mContentLength == 0.0) {
|
||||
mContentLength = ExoCacheManager.getContentLength(video!!.url) / 1024.0 / 1024.0
|
||||
val newGetContentLengthTime = System.currentTimeMillis()
|
||||
if (newGetContentLengthTime - mLastGetContentLengthTime > 5000) {
|
||||
mLastGetContentLengthTime = newGetContentLengthTime
|
||||
mContentLength = ExoCacheManager.getContentLength(video!!.url) / 1024.0 / 1024.0
|
||||
}
|
||||
}
|
||||
|
||||
//https://exoplayer.dev/hello-world.html#a-note-on-threading
|
||||
|
||||
@ -1,9 +1,12 @@
|
||||
package com.gh.gamecenter.geetest;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.ProgressDialog;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.os.Build;
|
||||
|
||||
import com.gh.gamecenter.core.AppExecutor;
|
||||
import com.gh.gamecenter.core.utils.AppDebugConfig;
|
||||
import com.gh.gamecenter.common.retrofit.JSONObjectResponse;
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager;
|
||||
@ -113,6 +116,10 @@ public class GeetestUtils {
|
||||
mRetryCount = 0;
|
||||
final GtDialog dialog = new GtDialog(context, params);
|
||||
|
||||
if (context instanceof Activity) {
|
||||
dialog.setOwnerActivity((Activity) context);
|
||||
}
|
||||
|
||||
// 启用debug可以在webview上看到验证过程的一些数据
|
||||
dialog.setDebug(AppDebugConfig.IS_DEBUG);
|
||||
|
||||
@ -128,85 +135,88 @@ public class GeetestUtils {
|
||||
|
||||
@Override
|
||||
public void gtCallReady(Boolean status) {
|
||||
if (AppDebugConfig.IS_DEBUG) {
|
||||
AppDebugConfig.logMethodWithParams(this, status, mProgressDialog.isShowing());
|
||||
}
|
||||
AppExecutor.getUiExecutor().execute(() -> {
|
||||
if (AppDebugConfig.IS_DEBUG) {
|
||||
AppDebugConfig.logMethodWithParams(this, status, mProgressDialog.isShowing());
|
||||
}
|
||||
|
||||
mRetryCount = 0;
|
||||
if (!mProgressDialog.isShowing()) {
|
||||
//被手动取消了,也就是其实用户想取消loading了,那么即使回调也不弹出
|
||||
return;
|
||||
}
|
||||
mRetryCount = 0;
|
||||
if (!mProgressDialog.isShowing()) {
|
||||
//被手动取消了,也就是其实用户想取消loading了,那么即使回调也不弹出
|
||||
return;
|
||||
}
|
||||
|
||||
mProgressDialog.dismiss();
|
||||
mProgressDialog.dismiss();
|
||||
|
||||
if (status) {
|
||||
// 验证加载完成
|
||||
RuntimeUtils.getInstance().runOnUiThread(new Runnable() {
|
||||
if (status) {
|
||||
// 验证加载完成
|
||||
Activity ownerActivity = dialog.getOwnerActivity();
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
if (dialog != null) {
|
||||
dialog.show();
|
||||
}
|
||||
if (ownerActivity != null
|
||||
&& (ownerActivity.isFinishing()
|
||||
|| (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) && ownerActivity.isDestroyed())) {
|
||||
// activity 不可见
|
||||
toastMsg(context, "验证加载超时,请重新尝试");
|
||||
} else {
|
||||
dialog.show();
|
||||
}
|
||||
});
|
||||
|
||||
} else {
|
||||
// 验证加载超时,未准备完成
|
||||
toastMsg(context, "验证加载超时,请重新尝试");
|
||||
}
|
||||
} else {
|
||||
// 验证加载超时,未准备完成
|
||||
toastMsg(context, "验证加载超时,请重新尝试");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void gtCallClose() {
|
||||
if (AppDebugConfig.IS_DEBUG) {
|
||||
AppDebugConfig.logMethodWithParams(this);
|
||||
}
|
||||
if (dialog != null && dialog.isShowing()) {
|
||||
dialog.dismiss();
|
||||
}
|
||||
// toastMsg("close geetest windows");
|
||||
AppExecutor.getUiExecutor().execute(() -> {
|
||||
if (AppDebugConfig.IS_DEBUG) {
|
||||
AppDebugConfig.logMethodWithParams(this);
|
||||
}
|
||||
if (dialog != null && dialog.isShowing()) {
|
||||
dialog.dismiss();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void gtError() {
|
||||
if (AppDebugConfig.IS_DEBUG) {
|
||||
AppDebugConfig.logMethodWithParams(this);
|
||||
}
|
||||
|
||||
if (mRetryCount < RETRY_MAX_COUNT) {
|
||||
mRetryCount++;
|
||||
checkServer(context);
|
||||
} else {
|
||||
if (mProgressDialog.isShowing()) {
|
||||
mProgressDialog.dismiss();
|
||||
AppExecutor.getUiExecutor().execute(() -> {
|
||||
if (AppDebugConfig.IS_DEBUG) {
|
||||
AppDebugConfig.logMethodWithParams(this);
|
||||
}
|
||||
}
|
||||
|
||||
if (mRetryCount < RETRY_MAX_COUNT) {
|
||||
mRetryCount++;
|
||||
checkServer(context);
|
||||
} else {
|
||||
if (mProgressDialog.isShowing()) {
|
||||
mProgressDialog.dismiss();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void gtResult(boolean success, String result) {
|
||||
if (AppDebugConfig.IS_DEBUG) {
|
||||
AppDebugConfig.logMethodWithParams(this, success, result);
|
||||
}
|
||||
|
||||
if (success) {
|
||||
if (dialog != null && dialog.isShowing()) {
|
||||
dialog.dismiss();
|
||||
AppExecutor.getUiExecutor().execute(() -> {
|
||||
if (AppDebugConfig.IS_DEBUG) {
|
||||
AppDebugConfig.logMethodWithParams(this, success, result);
|
||||
}
|
||||
if (mGeetestListener != null) {
|
||||
mGeetestListener.onVerified(result);
|
||||
}
|
||||
// toastMsg("client captcha succeed:" + result);
|
||||
Utils.log("client captcha succeed:" + result);
|
||||
} else {
|
||||
// 验证失败
|
||||
// toastMsg("client captcha failed:" + result);
|
||||
Utils.log("client captcha failed:" + result);
|
||||
}
|
||||
|
||||
if (success) {
|
||||
if (dialog != null && dialog.isShowing()) {
|
||||
dialog.dismiss();
|
||||
}
|
||||
if (mGeetestListener != null) {
|
||||
mGeetestListener.onVerified(result);
|
||||
}
|
||||
Utils.log("client captcha succeed:" + result);
|
||||
} else {
|
||||
// 验证失败
|
||||
Utils.log("client captcha failed:" + result);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
});
|
||||
@ -218,7 +228,6 @@ public class GeetestUtils {
|
||||
if (AppDebugConfig.IS_DEBUG) {
|
||||
AppDebugConfig.logMethodWithParams(this);
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@ -27,6 +27,7 @@ import com.gh.gamecenter.common.utils.viewModelProviderFromParent
|
||||
import com.gh.gamecenter.common.view.OffsetLinearLayoutManager
|
||||
import com.gh.gamecenter.core.AppExecutor
|
||||
import com.gh.gamecenter.core.provider.IFloatingWindowProvider
|
||||
import com.gh.gamecenter.core.provider.IStartUpAdProvider
|
||||
import com.gh.gamecenter.core.utils.MD5Utils
|
||||
import com.gh.gamecenter.core.utils.MtaHelper
|
||||
import com.gh.gamecenter.core.utils.SPUtils
|
||||
@ -103,7 +104,10 @@ class HomeFragment : LazyFragment() {
|
||||
reuseLoading.root.goneIf(loadStatus != LoadStatus.INIT_LOADING)
|
||||
}
|
||||
mListAdapter.setLoadStatus(it)
|
||||
val startAdContainerView = requireActivity().findViewById<View>(R.id.startAdContainer)
|
||||
val startUpAdProvider =
|
||||
ARouter.getInstance().build(RouteConsts.provider.adSdk).navigation() as? IStartUpAdProvider
|
||||
val startAdContainerView =
|
||||
requireActivity().findViewById<View>(if (startUpAdProvider != null) R.id.sdkStartAdContainer else R.id.startAdContainer)
|
||||
if (it == LoadStatus.INIT_LOADED && startAdContainerView == null) {
|
||||
AppExecutor.uiExecutor.executeWithDelay({
|
||||
scroll()
|
||||
@ -171,7 +175,7 @@ class HomeFragment : LazyFragment() {
|
||||
super.onScrolled(recyclerView, dx, dy)
|
||||
if (parentFragment is HomeSearchToolWrapperFragment) {
|
||||
val bannerViewHeight = mAutomaticLayoutManager.heightMap[0] ?: 0
|
||||
val type = (parentFragment as HomeSearchToolWrapperFragment).getCurrentTab()?.type
|
||||
val type = (parentFragment as HomeSearchToolWrapperFragment).getCurrentTabEntity()?.type
|
||||
if (type == "home") {
|
||||
(parentFragment as HomeSearchToolWrapperFragment).onScrollChanged(
|
||||
bannerViewHeight,
|
||||
@ -195,7 +199,9 @@ class HomeFragment : LazyFragment() {
|
||||
}
|
||||
|
||||
fun setScrollEnabled(isScrollEnabled: Boolean) {
|
||||
mAutomaticLayoutManager.isScrollEnabled = isScrollEnabled
|
||||
if (::mAutomaticLayoutManager.isInitialized) {
|
||||
mAutomaticLayoutManager.isScrollEnabled = isScrollEnabled
|
||||
}
|
||||
}
|
||||
|
||||
fun onRefresh() {
|
||||
@ -217,7 +223,10 @@ class HomeFragment : LazyFragment() {
|
||||
* 2. 过早显示悬浮窗,出现首页还未显示悬浮窗就在广告页显示的情况
|
||||
*/
|
||||
private fun listenStartAdViewRemoved() {
|
||||
val startAdContainerView = requireActivity().findViewById<View>(R.id.startAdContainer)
|
||||
val startUpAdProvider =
|
||||
ARouter.getInstance().build(RouteConsts.provider.adSdk).navigation() as? IStartUpAdProvider
|
||||
val startAdContainerView =
|
||||
requireActivity().findViewById<View>(if (startUpAdProvider != null) R.id.sdkStartAdContainer else R.id.startAdContainer)
|
||||
val parentView = startAdContainerView?.parent as? ViewGroup
|
||||
|
||||
if (parentView == null) {
|
||||
|
||||
@ -32,9 +32,10 @@ class HomeGameCollectionAdapter(
|
||||
|
||||
override fun onBindViewHolder(holder: HomeGameCollectionCardViewHolder, position: Int) {
|
||||
if (gameCollectionItemDataList.isNotEmpty()) {
|
||||
val gameCollectionItemData = gameCollectionItemDataList.safelyGetInRelease(position)
|
||||
(holder.itemView as HomeGameCollectionItemCell).bindWhenInflated {
|
||||
(holder.itemView as HomeGameCollectionItemCell).binding?.run {
|
||||
holder.bindGameCollectionCard(this, gameCollectionItemDataList[position], entrance)
|
||||
gameCollectionItemData?.let { holder.bindGameCollectionCard(this, it, entrance) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -4,7 +4,6 @@ import android.graphics.Typeface
|
||||
import android.graphics.drawable.GradientDrawable
|
||||
import android.view.MotionEvent
|
||||
import android.view.View
|
||||
import androidx.constraintlayout.widget.ConstraintLayout
|
||||
import androidx.constraintlayout.widget.ConstraintSet
|
||||
import androidx.core.graphics.ColorUtils
|
||||
import androidx.core.view.isVisible
|
||||
@ -34,7 +33,6 @@ import com.gh.gamecenter.feature.exposure.ExposureSource
|
||||
import com.gh.gamecenter.feature.exposure.ExposureType
|
||||
import com.gh.gamecenter.home.HomeItemData
|
||||
import com.gh.gamecenter.home.HomeViewModel
|
||||
import splitties.views.dsl.core.endMargin
|
||||
import kotlin.math.abs
|
||||
|
||||
class HomeSlideWithCardsViewHolder(
|
||||
@ -261,7 +259,6 @@ class HomeSlideWithCardsViewHolder(
|
||||
)
|
||||
)
|
||||
)
|
||||
itemData.exposureEventList?.add(exposureEvent)
|
||||
|
||||
when (homeSubSlide.cardType) {
|
||||
"column",
|
||||
@ -285,6 +282,14 @@ class HomeSlideWithCardsViewHolder(
|
||||
gameIconStackIv1.visibility = View.GONE
|
||||
}
|
||||
homeSubSlide.cardData.games.take(3).forEachIndexed { index, gameEntity ->
|
||||
itemData.exposureEventList?.add(
|
||||
getGameExposureEvent(
|
||||
homeSubSlide,
|
||||
gameEntity,
|
||||
position,
|
||||
basicExposureSource
|
||||
)
|
||||
)
|
||||
when (index) {
|
||||
0 -> gameIconStackIv3.displayGameIcon(gameEntity, true)
|
||||
1 -> gameIconStackIv2.displayGameIcon(gameEntity, true)
|
||||
@ -314,6 +319,17 @@ class HomeSlideWithCardsViewHolder(
|
||||
gameIconIv3.visibility = View.GONE
|
||||
}
|
||||
homeSubSlide.cardData.games.take(3).forEachIndexed { index, gameEntity ->
|
||||
val gameExposureEvent =
|
||||
getGameExposureEvent(homeSubSlide, gameEntity, position, basicExposureSource)
|
||||
itemData.exposureEventList?.add(
|
||||
getGameExposureEvent(
|
||||
homeSubSlide,
|
||||
gameEntity,
|
||||
position,
|
||||
basicExposureSource
|
||||
)
|
||||
)
|
||||
|
||||
when (index) {
|
||||
0 -> {
|
||||
gameIconIv1.displayGameIcon(gameEntity, true)
|
||||
@ -327,10 +343,11 @@ class HomeSlideWithCardsViewHolder(
|
||||
binding.root.context,
|
||||
gameEntity.id,
|
||||
BaseActivity.mergeEntranceAndPath("新首页", "右侧卡片"),
|
||||
exposureEvent
|
||||
gameExposureEvent
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
1 -> {
|
||||
gameIconIv2.displayGameIcon(gameEntity, true)
|
||||
gameIconIv2.setOnClickListener {
|
||||
@ -343,10 +360,11 @@ class HomeSlideWithCardsViewHolder(
|
||||
binding.root.context,
|
||||
gameEntity.id,
|
||||
BaseActivity.mergeEntranceAndPath("新首页", "右侧卡片"),
|
||||
exposureEvent
|
||||
gameExposureEvent
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
2 -> {
|
||||
gameIconIv3.displayGameIcon(gameEntity, true)
|
||||
gameIconIv3.setOnClickListener {
|
||||
@ -359,7 +377,7 @@ class HomeSlideWithCardsViewHolder(
|
||||
binding.root.context,
|
||||
gameEntity.id,
|
||||
BaseActivity.mergeEntranceAndPath("新首页", "右侧卡片"),
|
||||
exposureEvent
|
||||
gameExposureEvent
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -417,6 +435,8 @@ class HomeSlideWithCardsViewHolder(
|
||||
connect(textContainer.id, ConstraintSet.TOP, ConstraintSet.PARENT_ID, ConstraintSet.TOP)
|
||||
connect(textContainer.id, ConstraintSet.BOTTOM, ConstraintSet.PARENT_ID, ConstraintSet.BOTTOM)
|
||||
}.applyTo(cardContainer)
|
||||
|
||||
itemData.exposureEventList?.add(exposureEvent)
|
||||
}
|
||||
}
|
||||
|
||||
@ -431,17 +451,42 @@ class HomeSlideWithCardsViewHolder(
|
||||
source = listOf(
|
||||
ExposureSource(
|
||||
"右侧卡片",
|
||||
"${homeSubSlide.cardId} - ${getCardTypeChinese(homeSubSlide.cardType)}"
|
||||
"${homeSubSlide.cardId.ifEmpty { homeSubSlide.linkId }} - ${getCardTypeChinese(homeSubSlide.cardType)}"
|
||||
)
|
||||
),
|
||||
event = ExposureType.CLICK
|
||||
)
|
||||
)
|
||||
com.gh.common.util.NewFlatLogUtils.logRightSideCardClick(homeSubSlide, viewModel.refreshCount, "卡片")
|
||||
DirectUtils.directToLinkPage(cardCv.context, homeSubSlide.toLinkEntity(), "新首页", "右侧卡片", exposureEvent)
|
||||
DirectUtils.directToLinkPage(
|
||||
cardCv.context,
|
||||
homeSubSlide.toLinkEntity(),
|
||||
"新首页",
|
||||
"右侧卡片",
|
||||
exposureEvent
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun getGameExposureEvent(
|
||||
homeSubSlide: HomeSubSlide,
|
||||
gameEntity: GameEntity,
|
||||
position: Int,
|
||||
basicExposureSource: List<ExposureSource>
|
||||
) = ExposureEvent.createEventWithSourceConcat(
|
||||
gameEntity = gameEntity.apply {
|
||||
sequence = position
|
||||
outerSequence = viewModel.refreshCount
|
||||
},
|
||||
basicSource = basicExposureSource,
|
||||
source = listOf(
|
||||
ExposureSource(
|
||||
"右侧卡片",
|
||||
"${homeSubSlide.cardId.ifEmpty { homeSubSlide.linkId }} - ${getCardTypeChinese(homeSubSlide.cardType)}"
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
private fun updateImmersiveColor(color: Int) {
|
||||
callback.invoke(color)
|
||||
val gradientDrawable = DrawableView.getGradientDrawable(
|
||||
|
||||
@ -5,6 +5,7 @@ import android.view.View
|
||||
import androidx.core.view.updateLayoutParams
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.gh.gamecenter.common.utils.dip2px
|
||||
import com.gh.gamecenter.core.utils.DisplayUtils
|
||||
|
||||
/**
|
||||
* @author : liujiarui
|
||||
@ -13,6 +14,9 @@ import com.gh.gamecenter.common.utils.dip2px
|
||||
* 仅用于新游开测,让条目右侧漏出部分,或者最后一列左侧条目漏出部分
|
||||
*/
|
||||
class HomeGameTestV2Decoration : RecyclerView.ItemDecoration() {
|
||||
|
||||
private val mParentWidth = DisplayUtils.getScreenWidth() - 32F.dip2px()
|
||||
|
||||
companion object {
|
||||
private const val SPAN_COUNT = 3
|
||||
}
|
||||
@ -24,7 +28,7 @@ class HomeGameTestV2Decoration : RecyclerView.ItemDecoration() {
|
||||
if (lastModPosition == 0) lastModPosition = SPAN_COUNT
|
||||
val isLastRow = (itemCount - position) <= lastModPosition
|
||||
view.updateLayoutParams {
|
||||
width = parent.width - if (isLastRow) {
|
||||
width = mParentWidth - if (isLastRow) {
|
||||
8F.dip2px()
|
||||
} else {
|
||||
24F.dip2px()
|
||||
|
||||
@ -77,10 +77,9 @@ class HomeGameTestV2GameListViewHolder(
|
||||
*/
|
||||
private fun fixViewHolderTheme(gameEntity: GameEntity) {
|
||||
val context = mBinding.root.context
|
||||
mBinding.root.setBackgroundColor(R.color.background_white.toColor(context))
|
||||
gameName.setTextColor(R.color.text_title.toColor(context))
|
||||
gameDownloadBtn.background = R.drawable.download_button_normal_style.toDrawable(context)
|
||||
gameDes.setTextColor(R.color.text_subtitle.toColor(context))
|
||||
gameDes.setTextColor(R.color.text_title.toColor(context))
|
||||
var gameRatingTextColor = R.color.theme.toColor(context)
|
||||
if (gameEntity.commentCount > 3) {
|
||||
gameRatingTextColor = R.color.theme_font.toColor(context)
|
||||
|
||||
@ -185,7 +185,8 @@ class HomeGameTestV2ViewModel(application: Application) : AndroidViewModel(appli
|
||||
timeType = response.timeType,
|
||||
pageId = response.pageId,
|
||||
action = Action.getActionByCommand(response.action),
|
||||
isRefresh = false
|
||||
isRefresh = false,
|
||||
isSameTimeType = timeType == loadTimeType
|
||||
)
|
||||
}
|
||||
|
||||
@ -289,7 +290,8 @@ class HomeGameTestV2ViewModel(application: Application) : AndroidViewModel(appli
|
||||
pageId: String,
|
||||
action: Action,
|
||||
firstIndex: Int = 0, //首页推荐列表左侧剩余游戏数
|
||||
isRefresh: Boolean = false
|
||||
isRefresh: Boolean = false,
|
||||
isSameTimeType: Boolean = false //当前时间轴类型与预加载时间轴类型是否相同
|
||||
) {
|
||||
val currentData = getCurrentData().toMutableList()
|
||||
val gameList = getFilterGameAndTrimList(currentData, list)
|
||||
@ -324,7 +326,7 @@ class HomeGameTestV2ViewModel(application: Application) : AndroidViewModel(appli
|
||||
gameList.reverse()
|
||||
}
|
||||
gameList.forEach {
|
||||
addGameItemWithAction(currentData, it, action)
|
||||
addGameItemWithAction(currentData, it, action, isSameTimeType)
|
||||
}
|
||||
}
|
||||
mDataLiveData.value = currentData.toMutableList()
|
||||
@ -341,11 +343,20 @@ class HomeGameTestV2ViewModel(application: Application) : AndroidViewModel(appli
|
||||
dataList: MutableList<GameDataWrapper>,
|
||||
gameDataWrapper: GameDataWrapper,
|
||||
action: Action,
|
||||
isSameTimeType: Boolean
|
||||
) {
|
||||
val gameTimeType = gameDataWrapper.timeType
|
||||
val firstLoadedRecommendPosition =
|
||||
dataList.indexOfFirst { it.timeType == "recommend" && !it.isPlaceHolder && !it.isSpace } // 推荐类型第一个非占位的位置
|
||||
val lastLoadedRecommendPosition =
|
||||
dataList.indexOfLast { it.timeType == "recommend" && !it.isPlaceHolder && !it.isSpace } // 推荐类型最后一个非占位的位置
|
||||
val shouldInsertLoadedRecommendFront =
|
||||
gameTimeType == "recommend" && isSameTimeType && firstLoadedRecommendPosition > 0 // 推荐定位不是第一个时需要插入到已加载位置的前面
|
||||
val shouldInsertLoadedRecommendBehind =
|
||||
gameTimeType == "recommend" && isSameTimeType && lastLoadedRecommendPosition > 0 // 推荐定位不是第一个时需要插入到已加载位置的后面
|
||||
val insertPosition = when (action) {
|
||||
Action.LEFT -> dataList.indexOfFirst { it.timeType == gameTimeType && it.isPlaceHolder }
|
||||
Action.RIGHT -> dataList.indexOfLast { it.timeType == gameTimeType && it.isPlaceHolder }
|
||||
Action.LEFT -> if (shouldInsertLoadedRecommendBehind) lastLoadedRecommendPosition + 1 else dataList.indexOfFirst { it.timeType == gameTimeType && it.isPlaceHolder }
|
||||
Action.RIGHT -> if (shouldInsertLoadedRecommendFront) firstLoadedRecommendPosition - 1 else dataList.indexOfLast { it.timeType == gameTimeType && it.isPlaceHolder }
|
||||
}
|
||||
val exist = dataList.find { it.timeType == gameTimeType && it.gameData?.id == gameDataWrapper.gameData?.id }
|
||||
if (exist != null) {
|
||||
|
||||
@ -212,7 +212,8 @@ class HomeItemGameTestV2ViewHolder(
|
||||
pageId = data.pageId,
|
||||
action = HomeGameTestV2ViewModel.Action.getActionByCommand(data.action),
|
||||
firstIndex = recommendLeftSurplusNum,
|
||||
isRefresh = true
|
||||
isRefresh = true,
|
||||
isSameTimeType = true
|
||||
)
|
||||
//数据填充完毕后滑动到推荐列表指定位置
|
||||
if (recommendLeftSurplusNum > 0) {
|
||||
|
||||
@ -51,6 +51,7 @@ class AutomaticVideoView @JvmOverloads constructor(context: Context, attrs: Attr
|
||||
private var mRandomPlaceholderColor = 0
|
||||
private var mVideoViewRadius = 6F
|
||||
private var mIsBottomRightAngle = true
|
||||
private var mLastGetContentLengthTime = 0L
|
||||
|
||||
init {
|
||||
val array = context.obtainStyledAttributes(attrs, R.styleable.AutomaticVideoView)
|
||||
@ -310,7 +311,11 @@ class AutomaticVideoView @JvmOverloads constructor(context: Context, attrs: Attr
|
||||
val videoTotalTime = duration / 1000
|
||||
val progress = if (videoTotalTime != 0) videoPlayTs.toFloat() / videoTotalTime.toFloat() * 100 else 0f
|
||||
if (mContentLength == 0.0) {
|
||||
mContentLength = ExoCacheManager.getContentLength(topVideo.url) / 1024.0 / 1024.0
|
||||
val newGetContentLengthTime = System.currentTimeMillis()
|
||||
if (newGetContentLengthTime - mLastGetContentLengthTime > 5000) {
|
||||
mLastGetContentLengthTime = newGetContentLengthTime
|
||||
mContentLength = ExoCacheManager.getContentLength(topVideo.url) / 1024.0 / 1024.0
|
||||
}
|
||||
}
|
||||
|
||||
//https://exoplayer.dev/hello-world.html#a-note-on-threading
|
||||
|
||||
@ -277,7 +277,7 @@ class MyFollowedGameViewHolder(var binding: ItemFollowedGameBinding) : RecyclerV
|
||||
binding.root.context,
|
||||
gameEntity,
|
||||
entrance,
|
||||
defaultTab = GameDetailFragment.INDEX_TRENDES
|
||||
defaultTab = GameDetailFragment.TAB_TRENDS
|
||||
)
|
||||
}
|
||||
} else {
|
||||
@ -303,7 +303,7 @@ class MyFollowedGameViewHolder(var binding: ItemFollowedGameBinding) : RecyclerV
|
||||
binding.root.context,
|
||||
gameEntity,
|
||||
entrance,
|
||||
defaultTab = GameDetailFragment.INDEX_BBS
|
||||
defaultTab = GameDetailFragment.TAB_BBS
|
||||
)
|
||||
}
|
||||
} else {
|
||||
|
||||
@ -378,13 +378,13 @@ class HaloPersonalFragment : BaseLazyFragment() {
|
||||
}
|
||||
|
||||
mUserHomeViewModel.availableBadge.observe(this) { badge: BadgeEntity? ->
|
||||
val badgeSevenDayMap = SPUtils.getMap(SP_BADGE_RECORD_SEVEN_DAY_MAP)
|
||||
// 徽章领取弹窗每隔7天弹出一次,所以要判断现在是否是上一次弹出的第7天或者之后
|
||||
if (badge != null && System.currentTimeMillis() >= SPUtils.getLong(SP_BADGE_RECORD_SEVEN_DAY)) {
|
||||
if (badge != null && System.currentTimeMillis() >= (badgeSevenDayMap[badge.id]?.toLong() ?: 0)) {
|
||||
// 徽章领取弹窗每隔7天弹出一次,所以本次弹出后就记录7天后的时间戳
|
||||
SPUtils.setLong(
|
||||
SP_BADGE_RECORD_SEVEN_DAY,
|
||||
TimeUtils.getStartTimeOfDay(System.currentTimeMillis() + 86400000 * 6)
|
||||
)
|
||||
badgeSevenDayMap[badge.id] =
|
||||
TimeUtils.getStartTimeOfDay(System.currentTimeMillis() + 86400000 * 6).toString()
|
||||
SPUtils.setMap(SP_BADGE_RECORD_SEVEN_DAY_MAP, badgeSevenDayMap)
|
||||
DialogUtils.showReceiveBadgeDialog(requireContext(), badge) {
|
||||
if ("auto" == badge.receive?.type) {
|
||||
DirectUtils.directToBadgeDetail(
|
||||
@ -941,7 +941,7 @@ class HaloPersonalFragment : BaseLazyFragment() {
|
||||
|
||||
companion object {
|
||||
private const val MESSAGE_READ_OVER = "MESSAGE_READ_OVER"
|
||||
private const val SP_BADGE_RECORD_SEVEN_DAY = "badgeRecordSevenDay"
|
||||
private const val SP_BADGE_RECORD_SEVEN_DAY_MAP = "badgeRecordSevenDayMap"
|
||||
private const val REQUEST_MESSAGE = 199
|
||||
private const val MAX_RECOMMEND_COUNT = 4
|
||||
private const val MAX_MORE_FEATURES_COUNT = 12
|
||||
|
||||
@ -43,7 +43,7 @@ class HaloPersonalFunctionAdapter(context: Context) : BaseRecyclerAdapter<Recycl
|
||||
}
|
||||
mEntityList.clear()
|
||||
mEntityList.addAll(functionList)
|
||||
notifyItemRangeChanged(0, itemCount)
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder =
|
||||
|
||||
@ -44,7 +44,7 @@ class HaloPersonalRecommendAdapter(val context: Context) : BaseRecyclerAdapter<R
|
||||
}
|
||||
mEntityList.clear()
|
||||
mEntityList.addAll(recommendList)
|
||||
notifyItemRangeChanged(0, itemCount)
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder =
|
||||
|
||||
@ -15,10 +15,23 @@ object PkgHelper {
|
||||
private var mPkgConfigLink: PkgConfigEntity.PkgLinkEntity? = null
|
||||
private const val SP_PKG_CONFIG_IS_USED = "pkg_config_is_used"
|
||||
|
||||
private var mActivateRatioFromInternet = 0
|
||||
|
||||
private val mPkgProvider by lazy {
|
||||
ARouter.getInstance().build(RouteConsts.provider.pkg).navigation() as? IPkgProvider<PkgConfigEntity>
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取激活比例
|
||||
*/
|
||||
fun getActivateRatio() : Int {
|
||||
return if (mActivateRatioFromInternet > 0) {
|
||||
mActivateRatioFromInternet
|
||||
} else {
|
||||
BuildConfig.ACTIVATE_REPORTING_RATIO
|
||||
}
|
||||
}
|
||||
|
||||
fun getPkgConfig(isFromHomeTopTab: Boolean): PkgConfigEntity.PkgLinkEntity? {
|
||||
if (mPkgConfigLink == null
|
||||
&& !SPUtils.getBoolean(SP_PKG_CONFIG_IS_USED, false)
|
||||
@ -56,7 +69,9 @@ object PkgHelper {
|
||||
|
||||
mPkgProvider?.requestPkgConfig(configId) {
|
||||
mPkgConfigLink = it.data?.link
|
||||
mActivateRatioFromInternet = it.data?.activateRatio ?: 0
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@ -2,16 +2,22 @@ package com.gh.gamecenter.qa.article.detail
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.Activity
|
||||
import android.graphics.Bitmap
|
||||
import android.text.SpannableStringBuilder
|
||||
import android.text.Spanned
|
||||
import android.view.Gravity
|
||||
import android.view.View
|
||||
import android.webkit.JavascriptInterface
|
||||
import android.webkit.WebView
|
||||
import android.widget.ImageView
|
||||
import android.widget.LinearLayout
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.appcompat.content.res.AppCompatResources
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.gh.common.DefaultUrlHandler
|
||||
import com.gh.gamecenter.core.runOnUiThread
|
||||
import com.gh.common.util.*
|
||||
import com.gh.common.util.DialogUtils
|
||||
import com.gh.common.util.LogUtils
|
||||
import com.gh.common.util.NewLogUtils
|
||||
import com.gh.common.view.RichEditor
|
||||
@ -19,11 +25,15 @@ import com.gh.gamecenter.ImageViewerActivity
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.callback.ConfirmListener
|
||||
import com.gh.gamecenter.common.utils.*
|
||||
import com.gh.gamecenter.core.runOnUiThread
|
||||
import com.gh.gamecenter.core.utils.*
|
||||
import com.gh.gamecenter.databinding.ItemArticleDetailContentBinding
|
||||
import com.gh.gamecenter.login.user.UserManager
|
||||
import com.gh.gamecenter.qa.editor.OnLinkClickListener
|
||||
import com.gh.gamecenter.qa.entity.ArticleDetailEntity
|
||||
import splitties.views.dsl.core.add
|
||||
import splitties.views.dsl.core.lParams
|
||||
import splitties.views.dsl.core.wrapContent
|
||||
import java.util.*
|
||||
|
||||
class ArticleDetailContentViewHolder(
|
||||
@ -42,12 +52,10 @@ class ArticleDetailContentViewHolder(
|
||||
forumContainer.background = R.drawable.bg_shape_f5_radius_6.toDrawable(binding.root.context)
|
||||
userNameTv.setTextColor(R.color.text_title.toColor(binding.root.context))
|
||||
badgeTv.setTextColor(R.color.text_subtitleDesc.toColor(binding.root.context))
|
||||
releaseTimeTv.setTextColor(R.color.text_subtitleDesc.toColor(binding.root.context))
|
||||
lastEditTimeTv.setTextColor(R.color.text_subtitleDesc.toColor(binding.root.context))
|
||||
followBtn.setTextColor(R.color.theme_font.toColor(binding.root.context))
|
||||
approvalStatusTv.setTextColor(R.color.theme_green.toColor(binding.root.context))
|
||||
titleTv.setTextColor(R.color.text_title.toColor(binding.root.context))
|
||||
originalTv.setTextColor(R.color.theme_font.toColor(binding.root.context))
|
||||
lastEditTimeTv.setTextColor(R.color.text_subtitleDesc.toColor(binding.root.context))
|
||||
gameName.setTextColor(R.color.text_subtitleDesc.toColor(binding.root.context))
|
||||
|
||||
richEditor.enableForceDark(DarkModeUtils.isDarkModeOn(binding.root.context))
|
||||
@ -81,7 +89,6 @@ class ArticleDetailContentViewHolder(
|
||||
return DefaultUrlHandler.interceptUrl(binding.root.context, url ?: "", "帖子详情")
|
||||
}
|
||||
})
|
||||
originalTv.goneIf(article.original != "yes")
|
||||
approvalStatusTv.goneIf(article.status == "pass")
|
||||
statusContainer.visibleIf(article.status != "pass")
|
||||
when (article.status) {
|
||||
@ -156,11 +163,20 @@ class ArticleDetailContentViewHolder(
|
||||
"帖子详情"
|
||||
)
|
||||
}
|
||||
labelIv.goneIf(article.getSimplifyChoicenessStatus() != "pass")
|
||||
if (article.getSimplifyChoicenessStatus() == "pass") {
|
||||
labelIv.setImageDrawable(R.drawable.ic_essence_label.toDrawable())
|
||||
titleTv.text = if (article.getSimplifyChoicenessStatus() == "pass" || article.original == "yes") {
|
||||
SpannableStringBuilder(" ${article.title}").apply {
|
||||
getLabelBitmap(article)?.let {
|
||||
setSpan(
|
||||
CenterImageSpan(
|
||||
binding.root.context,
|
||||
it
|
||||
), 0, 1, Spanned.SPAN_EXCLUSIVE_INCLUSIVE
|
||||
)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
article.title
|
||||
}
|
||||
titleTv.text = article.title
|
||||
userNameTv.text = article.user.name
|
||||
userIconIv.display(article.user.border, article.user.icon, article.user.auth?.icon)
|
||||
richEditor.setContentOwner(article.me.isContentOwner)
|
||||
@ -169,13 +185,25 @@ class ArticleDetailContentViewHolder(
|
||||
richEditor.setHtml(article.content, true)
|
||||
}
|
||||
|
||||
if (article.source != null && article.source.region.isNotEmpty()) {
|
||||
releaseTimeTv.text = "${NewsUtils.getFormattedTime(article.time.create)} · ${article.source.region}"
|
||||
} else {
|
||||
releaseTimeTv.text = "${NewsUtils.getFormattedTime(article.time.create)}"
|
||||
regionTv.goneIf(article.source?.region.isNullOrEmpty())
|
||||
regionTv.text = article.source?.region
|
||||
lastEditTimeTv.text = NewsUtils.getFormattedTime(article.time.edit)
|
||||
lastEditTimeTv.setDrawableEnd(
|
||||
if (article.time.create != article.time.edit) AppCompatResources.getDrawable(
|
||||
lastEditTimeTv.context,
|
||||
R.drawable.icon_revise
|
||||
) else null
|
||||
)
|
||||
lastEditTimeTv.setOnClickListener {
|
||||
if (lastEditTimeTv.context is AppCompatActivity && article.time.editHistory.isNotEmpty()) {
|
||||
val timeList = ArrayList(article.time.editHistory)
|
||||
// 需加上首次发布时间
|
||||
if (article.time.create != 0L) {
|
||||
timeList.add(article.time.create)
|
||||
}
|
||||
EditHistoryDialog.show(lastEditTimeTv.context as AppCompatActivity, timeList)
|
||||
}
|
||||
}
|
||||
lastEditTimeTv.goneIf(article.time.create == article.time.edit)
|
||||
lastEditTimeTv.text = "最后编辑于${NewsUtils.getFormattedTime(article.time.edit)}"
|
||||
|
||||
richEditor.visibility = View.VISIBLE
|
||||
article.community.let { entity ->
|
||||
@ -203,9 +231,30 @@ class ArticleDetailContentViewHolder(
|
||||
followBtn.isEnabled = true
|
||||
updateFollowBtn(article.me.isFollower)
|
||||
}
|
||||
if (article.tagActivityId.isNotEmpty() && article.tagActivityName.isNotEmpty()) {
|
||||
activityNameTv.text = article.tagActivityName
|
||||
|
||||
tagContainer.isVisible = article.sections.isNotEmpty() || article.activityTag != null
|
||||
if (article.sections.isNotEmpty() && article.sections[0].id.isNotEmpty() && article.sections[0].name.isNotEmpty()) {
|
||||
sectionNameTv.text = article.sections[0].name
|
||||
sectionNameTv.visibility = View.VISIBLE
|
||||
sectionNameTv.setOnClickListener {
|
||||
DirectUtils.directForumDetailSection(
|
||||
binding.root.context,
|
||||
article.community.id,
|
||||
article.sections[0].id,
|
||||
mEntrance
|
||||
)
|
||||
}
|
||||
} else {
|
||||
sectionNameTv.visibility = View.GONE
|
||||
}
|
||||
if (article.activityTag != null) {
|
||||
activityNameTv.text = article.activityTag.name
|
||||
activityNameTv.visibility = View.VISIBLE
|
||||
activityNameTv.setOnClickListener {
|
||||
article.activityTag.link?.let {
|
||||
DirectUtils.directToLinkPage(binding.root.context, it, mEntrance, "话题标签")
|
||||
}
|
||||
}
|
||||
} else {
|
||||
activityNameTv.visibility = View.GONE
|
||||
}
|
||||
@ -237,6 +286,27 @@ class ArticleDetailContentViewHolder(
|
||||
}
|
||||
}
|
||||
|
||||
private fun getLabelBitmap(article: ArticleDetailEntity): Bitmap? {
|
||||
val context = binding.root.context
|
||||
return LinearLayout(binding.root.context).apply {
|
||||
setVerticalGravity(Gravity.CENTER)
|
||||
if (article.getSimplifyChoicenessStatus() == "pass") {
|
||||
add(ImageView(context).apply {
|
||||
setImageResource(R.drawable.ic_essence)
|
||||
}, lParams(wrapContent, wrapContent) {
|
||||
setMargins(0, 0, 4F.dip2px(), 0)
|
||||
})
|
||||
}
|
||||
if (article.original == "yes") {
|
||||
add(ImageView(context).apply {
|
||||
setImageResource(R.drawable.label_original)
|
||||
}, lParams(wrapContent, wrapContent) {
|
||||
setMargins(0, 0, 8F.dip2px(), 0)
|
||||
})
|
||||
}
|
||||
}.convertViewToBitmap()
|
||||
}
|
||||
|
||||
/**
|
||||
* 回调列表视频播放结束时的时间
|
||||
*/
|
||||
|
||||
@ -769,21 +769,43 @@ class ArticleDetailFragment : BaseCommentFragment<CommentItemData, ArticleDetail
|
||||
)
|
||||
|
||||
ImageUtils.display(mBinding.userAvatar, articleDetail.user.icon)
|
||||
mBinding.forumTitleTv.text = articleDetail.community.name
|
||||
|
||||
if (!mEntrance.contains("论坛详情")) {
|
||||
mBinding.forumContainer.visibility = View.VISIBLE
|
||||
mBinding.userContainer.visibility = View.GONE
|
||||
}
|
||||
|
||||
val icon =
|
||||
if (!articleDetail.community.icon.isNullOrEmpty()) articleDetail.community.icon else articleDetail.community.game?.getIcon()
|
||||
val iconSubscript =
|
||||
if (!articleDetail.community.iconSubscript.isNullOrEmpty()) articleDetail.community.iconSubscript else articleDetail.community.game?.iconSubscript
|
||||
mBinding.forumIv.displayGameIcon(icon, iconSubscript, articleDetail.community.game?.iconFloat)
|
||||
mBinding.forumNameTv.text = articleDetail.community.name
|
||||
mBinding.forumContainer.setOnClickListener {
|
||||
DirectUtils.directForumDetail(requireContext(), articleDetail.community.id, "帖子详情")
|
||||
}
|
||||
|
||||
mListRv.addOnScrollListener(object : RecyclerView.OnScrollListener() {
|
||||
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
|
||||
if (!mIsToolbarUserShow && mListRv.computeVerticalScrollOffset() > 56F.dip2px()) {
|
||||
mBinding.userAvatar.visibility = View.VISIBLE
|
||||
mAttentionMenu?.isVisible = articleDetail.user.id != UserManager.getInstance().userId
|
||||
mBinding.forumTitleTv.visibility = View.VISIBLE
|
||||
mBinding.forumTitleTv.text = articleDetail.user.name
|
||||
mBinding.userNameTv.visibility = View.VISIBLE
|
||||
mBinding.userNameTv.text = articleDetail.user.name
|
||||
mIsToolbarUserShow = true
|
||||
if (!mEntrance.contains("论坛详情")) {
|
||||
mBinding.forumContainer.visibility = View.GONE
|
||||
mBinding.userContainer.visibility = View.VISIBLE
|
||||
}
|
||||
} else if (mIsToolbarUserShow && mListRv.computeVerticalScrollOffset() <= 56F.dip2px()) {
|
||||
mBinding.userAvatar.visibility = View.GONE
|
||||
mAttentionMenu?.isVisible = false
|
||||
mBinding.forumTitleTv.visibility = View.GONE
|
||||
mBinding.userNameTv.visibility = View.GONE
|
||||
mIsToolbarUserShow = false
|
||||
if (!mEntrance.contains("论坛详情")) {
|
||||
mBinding.forumContainer.visibility = View.VISIBLE
|
||||
mBinding.userContainer.visibility = View.GONE
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -0,0 +1,88 @@
|
||||
package com.gh.gamecenter.qa.article.detail
|
||||
|
||||
import android.app.Dialog
|
||||
import android.graphics.Color
|
||||
import android.graphics.drawable.ColorDrawable
|
||||
import android.os.Bundle
|
||||
import android.view.Gravity
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.TextView
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.os.bundleOf
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.base.fragment.BaseDialogFragment
|
||||
import com.gh.gamecenter.common.constant.EntranceConsts
|
||||
import com.gh.gamecenter.common.utils.dip2px
|
||||
import com.gh.gamecenter.common.utils.goneIf
|
||||
import com.gh.gamecenter.common.utils.toColor
|
||||
import com.gh.gamecenter.core.utils.TimeUtils
|
||||
import com.gh.gamecenter.databinding.DialogEditHistoryBinding
|
||||
import com.halo.assistant.HaloApp
|
||||
import com.halo.assistant.fragment.user.avatar.ChooseDefaultAvatarDialog
|
||||
import splitties.views.dsl.core.add
|
||||
import splitties.views.dsl.core.lParams
|
||||
import splitties.views.dsl.core.wrapContent
|
||||
|
||||
|
||||
class EditHistoryDialog : BaseDialogFragment() {
|
||||
private var mBinding: DialogEditHistoryBinding? = null
|
||||
private var mEditHistoryArray: LongArray? = null
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
|
||||
return DialogEditHistoryBinding.inflate(layoutInflater, null, false).apply {
|
||||
mBinding = this
|
||||
}.root
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
mEditHistoryArray = requireArguments().getLongArray(EntranceConsts.KEY_EDIT_HISTORY)
|
||||
mBinding?.run {
|
||||
cancelTv.setOnClickListener {
|
||||
dismissAllowingStateLoss()
|
||||
}
|
||||
maskView.goneIf((mEditHistoryArray?.size ?: 0) <= 10)
|
||||
if ((mEditHistoryArray?.size ?: 0) > 10) {
|
||||
contentContainer.setPadding(0, 0, 8F.dip2px(), 22F.dip2px())
|
||||
}
|
||||
mEditHistoryArray?.forEach {
|
||||
contentContainer.add(
|
||||
getTimeTextView(it),
|
||||
contentContainer.lParams(contentContainer.wrapContent, 22F.dip2px())
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
val width = HaloApp.getInstance().application.resources.displayMetrics.widthPixels
|
||||
val height = dialog?.window?.attributes?.height ?: ViewGroup.LayoutParams.WRAP_CONTENT
|
||||
dialog?.window?.setLayout(width, height)
|
||||
}
|
||||
|
||||
private fun getTimeTextView(time: Long): TextView = TextView(requireContext()).apply {
|
||||
text = TimeUtils.getFormatTime(time, "-yyyy-MM-dd HH:mm:ss")
|
||||
gravity = Gravity.CENTER
|
||||
setTextColor(R.color.text_subtitle.toColor(requireContext()))
|
||||
}
|
||||
|
||||
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
||||
val createDialog = super.onCreateDialog(savedInstanceState)
|
||||
createDialog.setCanceledOnTouchOutside(true)
|
||||
val window = createDialog.window
|
||||
window?.setGravity(Gravity.CENTER)
|
||||
window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
|
||||
return createDialog
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun show(activity: AppCompatActivity, editHistory: List<Long>) {
|
||||
EditHistoryDialog().apply {
|
||||
arguments = bundleOf(EntranceConsts.KEY_EDIT_HISTORY to editHistory.toLongArray())
|
||||
}.show(activity.supportFragmentManager, ChooseDefaultAvatarDialog::class.java.name)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -129,6 +129,7 @@ class NewCommentDetailActivity : ToolBarActivity() {
|
||||
) = Bundle().apply {
|
||||
putString(EntranceConsts.KEY_ENTRANCE, mergeEntranceAndPath(entrance, path))
|
||||
putInt(EntranceConsts.KEY_POSITION, 1)
|
||||
putBoolean(EntranceConsts.KEY_USE_ALTERNATIVE_LAYOUT, true)
|
||||
putString(EntranceConsts.KEY_COMMENT_ID, commentId)
|
||||
putString(EntranceConsts.KEY_TOP_COMMENT_ID, topCommentId)
|
||||
putString(EntranceConsts.KEY_PATH, path)
|
||||
|
||||
@ -8,6 +8,8 @@ import android.view.LayoutInflater
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.FrameLayout
|
||||
import androidx.core.view.updateLayoutParams
|
||||
import com.ethanhua.skeleton.Skeleton
|
||||
import com.gh.gamecenter.common.base.activity.ToolBarActivity
|
||||
import com.gh.gamecenter.core.AppExecutor
|
||||
@ -35,6 +37,8 @@ class CommentConversationFragment :
|
||||
private lateinit var mBinding: FragmentArticleDetailCommentBinding
|
||||
private var mAdapterCommunity: CommentConversationAdapter? = null
|
||||
|
||||
private var mUseAlternativeLayout = false // 是否使用特殊布局,隐藏顶部条数显示、额外顶部间距等
|
||||
|
||||
override fun getLayoutId() = 0
|
||||
|
||||
override fun getInflatedLayout() =
|
||||
@ -47,9 +51,11 @@ class CommentConversationFragment :
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
mViewModel = provideListViewModel()
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
mUseAlternativeLayout = arguments?.getBoolean(EntranceConsts.KEY_USE_ALTERNATIVE_LAYOUT) ?: false
|
||||
|
||||
mViewModel.getComment()
|
||||
mViewModel.positionInOriginList = arguments?.getInt(EntranceConsts.KEY_POSITION)
|
||||
?: -1
|
||||
mViewModel.positionInOriginList = arguments?.getInt(EntranceConsts.KEY_POSITION) ?: -1
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
@ -109,6 +115,14 @@ class CommentConversationFragment :
|
||||
inputContainer.bottomStarIv.visibility = View.GONE
|
||||
inputContainer.bottomStarTv.visibility = View.GONE
|
||||
|
||||
// 取消掉
|
||||
if (mUseAlternativeLayout) {
|
||||
toolbarContainer.root.visibility = View.GONE
|
||||
container.updateLayoutParams { this as FrameLayout.LayoutParams
|
||||
setMargins(0, 0, 0, 0)
|
||||
}
|
||||
}
|
||||
|
||||
inputContainer.replyTv.setRoundedColorBackground(R.color.background_space_2, 19F)
|
||||
inputContainer.replyTv.setDebouncedClickListener {
|
||||
mViewModel.commentDetail?.let { startCommentActivity(it) }
|
||||
|
||||
@ -2,6 +2,8 @@ package com.gh.gamecenter.qa.entity
|
||||
|
||||
import android.os.Parcelable
|
||||
import com.gh.gamecenter.common.entity.CommunityEntity
|
||||
import com.gh.gamecenter.common.entity.LinkEntity
|
||||
import com.gh.gamecenter.entity.ForumEntity
|
||||
import com.gh.gamecenter.feature.entity.UserEntity
|
||||
import com.gh.gamecenter.feature.entity.*
|
||||
import com.google.gson.annotations.SerializedName
|
||||
@ -42,6 +44,9 @@ class ArticleDetailEntity(
|
||||
var status: String? = "pass",//pass通过,fail未通过,pending审核中
|
||||
var original: String? = "",
|
||||
val source: SourceEntity? = null,
|
||||
@SerializedName("activity_tag")
|
||||
val activityTag: ActivityTagEntity? = null,
|
||||
var sections: List<SectionEntity> = ArrayList(),
|
||||
@SerializedName("section_id")
|
||||
var sectionIdList: List<String> = ArrayList()
|
||||
) : Parcelable {
|
||||
@ -55,4 +60,19 @@ class ArticleDetailEntity(
|
||||
}
|
||||
}
|
||||
|
||||
@Parcelize
|
||||
class SectionEntity(
|
||||
@SerializedName("_id")
|
||||
val id: String = "",
|
||||
val name: String = ""
|
||||
) : Parcelable
|
||||
|
||||
|
||||
@Parcelize
|
||||
class ActivityTagEntity(
|
||||
@SerializedName("_id")
|
||||
val id: String = "",
|
||||
val name: String = "",
|
||||
val link: LinkEntity? = null
|
||||
) : Parcelable
|
||||
|
||||
|
||||
@ -53,7 +53,10 @@ class QuestionsDetailEntity(
|
||||
var draftId: String = "",
|
||||
@SerializedName("images_info")
|
||||
var imagesInfo: List<ImageInfo> = ArrayList(),
|
||||
val source: SourceEntity? = null
|
||||
val source: SourceEntity? = null,
|
||||
@SerializedName("activity_tag")
|
||||
val activityTag: ActivityTagEntity? = null,
|
||||
var sections: List<SectionEntity> = ArrayList()
|
||||
) : Parcelable {
|
||||
|
||||
fun getFollowCount(): Int {
|
||||
|
||||
@ -401,20 +401,20 @@ class NewQuestionDetailFragment :
|
||||
mViewModel.getCommentText(questionDetail.count.answer, "回答")
|
||||
|
||||
ImageUtils.display(mBinding.userAvatar, questionDetail.user.icon)
|
||||
mBinding.forumTitleTv.text = questionDetail.community.name
|
||||
mBinding.userNameTv.text = questionDetail.community.name
|
||||
|
||||
mListRv.addOnScrollListener(object : RecyclerView.OnScrollListener() {
|
||||
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
|
||||
if (!mIsToolbarUserShow && mListRv.computeVerticalScrollOffset() > 56F.dip2px()) {
|
||||
mBinding.userAvatar.visibility = View.VISIBLE
|
||||
mAttentionMenu?.isVisible = questionDetail.user.id != UserManager.getInstance().userId
|
||||
mBinding.forumTitleTv.visibility = View.VISIBLE
|
||||
mBinding.forumTitleTv.text = questionDetail.user.name
|
||||
mBinding.userNameTv.visibility = View.VISIBLE
|
||||
mBinding.userNameTv.text = questionDetail.user.name
|
||||
mIsToolbarUserShow = true
|
||||
} else if (mIsToolbarUserShow && mListRv.computeVerticalScrollOffset() <= 56F.dip2px()) {
|
||||
mBinding.userAvatar.visibility = View.GONE
|
||||
mAttentionMenu?.isVisible = false
|
||||
mBinding.forumTitleTv.visibility = View.GONE
|
||||
mBinding.userNameTv.visibility = View.GONE
|
||||
mIsToolbarUserShow = false
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,16 +2,19 @@ package com.gh.gamecenter.qa.questions.newdetail
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.Activity
|
||||
import android.text.SpannableStringBuilder
|
||||
import android.text.Spanned
|
||||
import android.view.View
|
||||
import android.webkit.JavascriptInterface
|
||||
import android.webkit.WebView
|
||||
import android.widget.LinearLayout
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.appcompat.content.res.AppCompatResources
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.gh.common.DefaultUrlHandler
|
||||
import com.gh.gamecenter.core.runOnUiThread
|
||||
import com.gh.common.util.*
|
||||
import com.gh.common.util.DialogUtils
|
||||
import com.gh.common.util.LogUtils
|
||||
import com.gh.common.util.NewLogUtils
|
||||
import com.gh.common.view.RichEditor
|
||||
@ -19,9 +22,11 @@ import com.gh.gamecenter.ImageViewerActivity
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.callback.ConfirmListener
|
||||
import com.gh.gamecenter.common.utils.*
|
||||
import com.gh.gamecenter.core.runOnUiThread
|
||||
import com.gh.gamecenter.core.utils.*
|
||||
import com.gh.gamecenter.databinding.ItemArticleDetailContentBinding
|
||||
import com.gh.gamecenter.login.user.UserManager
|
||||
import com.gh.gamecenter.qa.article.detail.EditHistoryDialog
|
||||
import com.gh.gamecenter.qa.editor.OnLinkClickListener
|
||||
import com.gh.gamecenter.qa.entity.QuestionsDetailEntity
|
||||
import java.util.*
|
||||
@ -135,9 +140,14 @@ class QuestionDetailContentViewHolder(
|
||||
?: "", "提问帖", question.community.id, bbsType
|
||||
)
|
||||
}
|
||||
titleTv.text = question.title
|
||||
labelIv.visibility = View.VISIBLE
|
||||
labelIv.setImageDrawable(if (question.finish) R.drawable.ic_ask_solved_label.toDrawable() else R.drawable.ic_ask_unsolved_label.toDrawable())
|
||||
titleTv.text = SpannableStringBuilder(" ${question.title}").apply {
|
||||
setSpan(
|
||||
CenterImageSpan(
|
||||
binding.root.context,
|
||||
if (question.finish) R.drawable.ic_ask_solved_label else R.drawable.ic_ask_unsolved_label
|
||||
), 0, 1, Spanned.SPAN_EXCLUSIVE_INCLUSIVE
|
||||
)
|
||||
}
|
||||
userNameTv.text = question.user.name
|
||||
userIconIv.display(question.user.border, question.user.icon, question.user.auth?.icon)
|
||||
richEditor.setContentOwner(question.me.isContentOwner)
|
||||
@ -146,13 +156,20 @@ class QuestionDetailContentViewHolder(
|
||||
richEditor.setHtml(question.description, true)
|
||||
}
|
||||
|
||||
if (question.source != null && question.source.region.isNotEmpty()) {
|
||||
releaseTimeTv.text = "${NewsUtils.getFormattedTime(question.time.create)} · ${question.source.region}"
|
||||
} else {
|
||||
releaseTimeTv.text = "${NewsUtils.getFormattedTime(question.time.create)}"
|
||||
regionTv.goneIf(question.source?.region.isNullOrEmpty())
|
||||
regionTv.text = question.source?.region
|
||||
lastEditTimeTv.text = NewsUtils.getFormattedTime(question.time.edit)
|
||||
lastEditTimeTv.setDrawableEnd(
|
||||
if (question.time.create != question.time.edit) AppCompatResources.getDrawable(
|
||||
lastEditTimeTv.context,
|
||||
R.drawable.icon_revise
|
||||
) else null
|
||||
)
|
||||
lastEditTimeTv.setOnClickListener {
|
||||
if (lastEditTimeTv.context is AppCompatActivity && question.time.editHistory.isNotEmpty()) {
|
||||
EditHistoryDialog.show(lastEditTimeTv.context as AppCompatActivity, question.time.editHistory)
|
||||
}
|
||||
}
|
||||
lastEditTimeTv.goneIf(question.time.create == question.time.edit)
|
||||
lastEditTimeTv.text = "最后编辑于${NewsUtils.getFormattedTime(question.time.edit)}"
|
||||
|
||||
richEditor.visibility = View.VISIBLE
|
||||
question.community.let { entity ->
|
||||
@ -181,9 +198,29 @@ class QuestionDetailContentViewHolder(
|
||||
updateFollowBtn(question.me.isFollower)
|
||||
}
|
||||
|
||||
if (question.tagActivityId.isNotEmpty() && question.tagActivityName.isNotEmpty()) {
|
||||
activityNameTv.text = question.tagActivityName
|
||||
tagContainer.isVisible = question.sections.isNotEmpty() || question.activityTag != null
|
||||
if (question.sections.isNotEmpty() && question.sections[0].id.isNotEmpty() && question.sections[0].name.isNotEmpty()) {
|
||||
sectionNameTv.text = question.sections[0].name
|
||||
sectionNameTv.visibility = View.VISIBLE
|
||||
sectionNameTv.setOnClickListener {
|
||||
DirectUtils.directForumDetailSection(
|
||||
binding.root.context,
|
||||
question.community.id,
|
||||
question.sections[0].id,
|
||||
mEntrance
|
||||
)
|
||||
}
|
||||
} else {
|
||||
sectionNameTv.visibility = View.GONE
|
||||
}
|
||||
if (question.activityTag != null) {
|
||||
activityNameTv.text = question.activityTag.name
|
||||
activityNameTv.visibility = View.VISIBLE
|
||||
activityNameTv.setOnClickListener {
|
||||
question.activityTag.link?.let {
|
||||
DirectUtils.directToLinkPage(binding.root.context, it, mEntrance, "话题标签")
|
||||
}
|
||||
}
|
||||
} else {
|
||||
activityNameTv.visibility = View.GONE
|
||||
}
|
||||
|
||||
@ -1,8 +1,14 @@
|
||||
package com.gh.gamecenter.qa.video.detail.desc
|
||||
|
||||
import android.animation.ValueAnimator
|
||||
import android.graphics.Bitmap
|
||||
import android.text.Layout
|
||||
import android.text.SpannableStringBuilder
|
||||
import android.text.Spanned
|
||||
import android.view.Gravity
|
||||
import android.view.View
|
||||
import android.widget.ImageView
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.TextView
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.constraintlayout.widget.ConstraintLayout
|
||||
@ -18,13 +24,15 @@ import com.gh.gamecenter.common.base.BaseRecyclerViewHolder
|
||||
import com.gh.gamecenter.common.callback.ConfirmListener
|
||||
import com.gh.gamecenter.common.entity.NormalShareEntity
|
||||
import com.gh.gamecenter.common.utils.*
|
||||
import com.gh.gamecenter.core.utils.SpanBuilder
|
||||
import com.gh.gamecenter.core.utils.CenterImageSpan
|
||||
import com.gh.gamecenter.databinding.ItemVideoDescTopBinding
|
||||
import com.gh.gamecenter.feature.entity.ForumVideoEntity
|
||||
import com.gh.gamecenter.login.user.UserManager
|
||||
import com.gh.gamecenter.qa.dialog.MoreFunctionPanelDialog
|
||||
import com.gh.gamecenter.qa.video.detail.ForumVideoDetailViewModel
|
||||
import kotlin.math.max
|
||||
import splitties.views.dsl.core.add
|
||||
import splitties.views.dsl.core.lParams
|
||||
import splitties.views.dsl.core.wrapContent
|
||||
|
||||
class VideoDescTopViewHolder(
|
||||
val binding: ItemVideoDescTopBinding,
|
||||
@ -51,11 +59,29 @@ class VideoDescTopViewHolder(
|
||||
if (entity.me.isFollower) R.drawable.button_round_gray_light.toDrawable() else R.drawable.button_round_primary_light.toDrawable()
|
||||
setTextColor(if (entity.me.isFollower) R.color.text_subtitleDesc.toColor() else R.color.theme_font.toColor())
|
||||
}
|
||||
binding.titleTv.text = entity.title
|
||||
binding.titleTv.text = if (entity.getSimplifyChoicenessStatus() == "pass" || entity.original == "yes") {
|
||||
SpannableStringBuilder(" ${entity.title}").apply {
|
||||
getLabelBitmap(entity)?.let {
|
||||
setSpan(
|
||||
CenterImageSpan(
|
||||
binding.root.context,
|
||||
it
|
||||
), 0, 1, Spanned.SPAN_EXCLUSIVE_INCLUSIVE
|
||||
)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
entity.title
|
||||
}
|
||||
binding.desTv.text = entity.des
|
||||
binding.desTv.goneIf(entity.des.isEmpty())
|
||||
binding.activityNameTv.goneIf(entity.tagActivityName.isEmpty())
|
||||
binding.activityNameTv.text = entity.tagActivityName
|
||||
binding.activityNameTv.goneIf(entity.activityTag == null)
|
||||
binding.activityNameTv.text = entity.activityTag?.name
|
||||
binding.activityNameTv.setOnClickListener {
|
||||
entity.activityTag?.link?.let {
|
||||
DirectUtils.directToLinkPage(binding.root.context, it, "视频贴详情", "话题标签")
|
||||
}
|
||||
}
|
||||
binding.userAvatar.display(entity.user.border, entity.user.icon, entity.user.auth?.icon)
|
||||
binding.likeIv.setImageDrawable(if (entity.me.isVoted) R.drawable.ic_forum_video_detail_liked.toDrawable() else R.drawable.ic_forum_video_detail_like.toDrawable())
|
||||
binding.likeCountTv.text = entity.count.vote.toString()
|
||||
@ -66,16 +92,19 @@ class VideoDescTopViewHolder(
|
||||
binding.shareIv.setImageDrawable(R.drawable.ic_forum_video_detail_share.toDrawable())
|
||||
binding.shareTv.text = entity.share.toString()
|
||||
|
||||
if (entity.original == "yes") {
|
||||
binding.originalTv.visibility = View.VISIBLE
|
||||
binding.activityNameTv.layoutParams =
|
||||
(binding.activityNameTv.layoutParams as ConstraintLayout.LayoutParams).apply {
|
||||
leftMargin = 8f.dip2px()
|
||||
}
|
||||
}
|
||||
if (entity.getSimplifyChoicenessStatus() == "pass") {
|
||||
binding.titleTv.text =
|
||||
SpanBuilder(" ${entity.title}").image(0, 1, R.drawable.ic_essence).build()
|
||||
if (entity.sections.isNotEmpty() && entity.sections[0].id.isNotEmpty() && entity.sections[0].name.isNotEmpty()) {
|
||||
binding.sectionNameTv.text = entity.sections[0].name
|
||||
binding.sectionNameTv.visibility = View.VISIBLE
|
||||
binding.sectionNameTv.setOnClickListener {
|
||||
DirectUtils.directForumDetailSection(
|
||||
binding.root.context,
|
||||
entity.bbs?.id,
|
||||
entity.sections[0].id,
|
||||
"视频贴详情"
|
||||
)
|
||||
}
|
||||
} else {
|
||||
binding.sectionNameTv.visibility = View.GONE
|
||||
}
|
||||
initAnimation(entity)
|
||||
|
||||
@ -159,35 +188,25 @@ class VideoDescTopViewHolder(
|
||||
private fun initAnimation(entity: ForumVideoEntity) {
|
||||
binding.root.post {
|
||||
mShrinkHeight = if (mShrinkHeight == 0) {
|
||||
getTextViewHeight(binding.titleTv, 1)
|
||||
getTextViewHeight(binding.titleTv, 2)
|
||||
} else mShrinkHeight
|
||||
|
||||
mExpandHeight = if (mExpandHeight == 0) {
|
||||
var height = getTextViewHeight(binding.titleTv) +
|
||||
getTextViewHeight(binding.desTv) +
|
||||
(if (binding.desTv.visibility == View.VISIBLE) binding.desTv.marginTop else 0) +
|
||||
(if (binding.activityNameTv.visibility == View.VISIBLE || binding.originalTv.visibility == View.VISIBLE) binding.activityNameTv.marginTop else 0)
|
||||
if (binding.activityNameTv.visibility == View.VISIBLE || binding.originalTv.visibility == View.VISIBLE) {
|
||||
height += max(
|
||||
getTextViewHeight(binding.activityNameTv),
|
||||
binding.originalTv.measuredHeight
|
||||
)
|
||||
}
|
||||
height
|
||||
getTextViewHeight(binding.titleTv) + getTextViewHeight(binding.desTv) + (if (binding.desTv.visibility == View.VISIBLE) binding.desTv.marginTop else 0)
|
||||
} else mExpandHeight
|
||||
|
||||
if (mIsExpand) {
|
||||
binding.titleTv.maxLines = Int.MAX_VALUE
|
||||
updateTitleContainerHeight(mExpandHeight)
|
||||
} else {
|
||||
binding.titleTv.maxLines = 1
|
||||
binding.titleTv.maxLines = 2
|
||||
updateTitleContainerHeight(mShrinkHeight)
|
||||
}
|
||||
|
||||
//若标题未超过一行或无描述内容、活动标签、原创标签,箭头不显示
|
||||
//若标题未超过一行或无描述内容,箭头不显示
|
||||
val ellipsisCount =
|
||||
binding.titleTv.layout?.getEllipsisCount(binding.titleTv.lineCount - 1) ?: 0
|
||||
binding.expandMoreIv.goneIf(entity.des.isEmpty() && entity.tagActivityName.isEmpty() && entity.original != "yes" && ellipsisCount == 0)
|
||||
binding.expandMoreIv.goneIf(entity.des.isEmpty() && ellipsisCount == 0)
|
||||
}
|
||||
binding.expandMoreIv.setOnClickListener {
|
||||
NewLogUtils.logVideoDetailClick(if (!mIsExpand) "click_detail_tab_down" else "click_detail_tab_up")
|
||||
@ -209,7 +228,7 @@ class VideoDescTopViewHolder(
|
||||
}
|
||||
animator.doOnEnd {
|
||||
if (mIsExpand) {
|
||||
binding.titleTv.maxLines = 1
|
||||
binding.titleTv.maxLines = 2
|
||||
}
|
||||
mIsExpand = !mIsExpand
|
||||
binding.expandMoreIv.rotation = if (mIsExpand) 180f else 0f
|
||||
@ -250,8 +269,33 @@ class VideoDescTopViewHolder(
|
||||
private fun getTextViewHeight(view: TextView, lineCount: Int = 0): Int {
|
||||
if (view.visibility == View.GONE) return 0
|
||||
val layout: Layout = view.layout ?: return 0
|
||||
val desired: Int = layout.getLineTop(if (lineCount > 0) lineCount else view.lineCount)
|
||||
val desired: Int = try {
|
||||
layout.getLineTop(if (lineCount > 0) lineCount else view.lineCount)
|
||||
} catch (e: ArrayIndexOutOfBoundsException) {
|
||||
layout.getLineTop(view.lineCount)
|
||||
}
|
||||
val padding = view.compoundPaddingTop + view.compoundPaddingBottom
|
||||
return desired + padding
|
||||
}
|
||||
|
||||
private fun getLabelBitmap(entity: ForumVideoEntity): Bitmap? {
|
||||
val context = binding.root.context
|
||||
return LinearLayout(binding.root.context).apply {
|
||||
setVerticalGravity(Gravity.CENTER)
|
||||
if (entity.getSimplifyChoicenessStatus() == "pass") {
|
||||
add(ImageView(context).apply {
|
||||
setImageResource(R.drawable.ic_essence)
|
||||
}, lParams(wrapContent, wrapContent) {
|
||||
setMargins(0, 0, 4F.dip2px(), 0)
|
||||
})
|
||||
}
|
||||
if (entity.original == "yes") {
|
||||
add(ImageView(context).apply {
|
||||
setImageResource(R.drawable.label_original)
|
||||
}, lParams(wrapContent, wrapContent) {
|
||||
setMargins(0, 0, 8F.dip2px(), 0)
|
||||
})
|
||||
}
|
||||
}.convertViewToBitmap()
|
||||
}
|
||||
}
|
||||
@ -97,7 +97,7 @@ open class SearchDefaultFragment : BaseFragment<Any>() {
|
||||
val source = listOf(ExposureSource("首页搜索 -> 搜索榜单", "${rankList.title}-${rank.name}"))
|
||||
if (rank.link.type == "game") {
|
||||
rank.exposureEvent = ExposureEvent.createEvent(
|
||||
rank.toGameEntity().apply {
|
||||
rank.linkGame?.toGameEntity()?.apply {
|
||||
outerSequence = outIndex
|
||||
sequence = index
|
||||
},
|
||||
|
||||
@ -172,7 +172,7 @@ class SearchGameIndexAdapter(
|
||||
|| gameEntity.contentTag!!.server
|
||||
|| gameEntity.contentTag!!.isBbsExists)
|
||||
val isShowTagByMirror =
|
||||
if (gameEntity.shouldUseMirrorInfo()) isShowTag && gameEntity.mirrorData?.contentTagStatus == "on" else isShowTag
|
||||
if (gameEntity.shouldUseMirrorInfo()) isShowTag && gameEntity.obtainMirrorData()?.contentTagStatus == "on" else isShowTag
|
||||
tagContainer.goneIf(!isShowTagByMirror)
|
||||
if (isShowTagByMirror) {
|
||||
val screenWidth = mContext.resources.displayMetrics.widthPixels
|
||||
@ -228,7 +228,7 @@ class SearchGameIndexAdapter(
|
||||
StringUtils.buildString(
|
||||
entrance, "+(搜索-列表[", key, "=", "$type=",
|
||||
(holder.adapterPosition + 1).toString(), "])"
|
||||
), GameDetailFragment.INDEX_TRENDES, traceEvent = exposureEvent
|
||||
), GameDetailFragment.TAB_TRENDS, traceEvent = exposureEvent
|
||||
)
|
||||
|
||||
gameEntity.run {
|
||||
@ -290,7 +290,7 @@ class SearchGameIndexAdapter(
|
||||
StringUtils.buildString(
|
||||
entrance, "+(搜索-列表[", key, "=", "$type=",
|
||||
(holder.adapterPosition + 1).toString(), "])"
|
||||
), GameDetailFragment.INDEX_BBS, traceEvent = exposureEvent
|
||||
), GameDetailFragment.TAB_BBS, traceEvent = exposureEvent
|
||||
)
|
||||
|
||||
gameEntity.run {
|
||||
@ -308,7 +308,7 @@ class SearchGameIndexAdapter(
|
||||
}
|
||||
|
||||
if (tagContainer.childCount < 4 && gameEntity.contentTag!!.server) {
|
||||
if (!gameEntity.shouldUseMirrorInfo() || (gameEntity.shouldUseMirrorInfo() && gameEntity.mirrorData?.mirrorServer?.calendar?.isNotEmpty() == true)) {
|
||||
if (!gameEntity.shouldUseMirrorInfo() || (gameEntity.shouldUseMirrorInfo() && gameEntity.obtainMirrorData()?.mirrorServer?.calendar?.isNotEmpty() == true)) {
|
||||
val serverView = getContentTagView(
|
||||
R.drawable.ic_label_server,
|
||||
"",
|
||||
@ -373,7 +373,7 @@ class SearchGameIndexAdapter(
|
||||
SearchType.fromString(type).toChinese(),
|
||||
gameEntity.id,
|
||||
gameEntity.name,
|
||||
gameEntity.shouldUseMirrorInfo(),
|
||||
gameEntity.getMirrorPosition(),
|
||||
gameEntity.adIconActive
|
||||
)
|
||||
}
|
||||
@ -428,7 +428,7 @@ class SearchGameIndexAdapter(
|
||||
SearchType.fromString(type).toChinese(),
|
||||
gameEntity.id,
|
||||
gameEntity.name,
|
||||
gameEntity.shouldUseMirrorInfo(),
|
||||
gameEntity.getMirrorPosition(),
|
||||
gameEntity.adIconActive
|
||||
)
|
||||
}
|
||||
@ -476,7 +476,7 @@ class SearchGameIndexAdapter(
|
||||
SearchType.fromString(type).toChinese(),
|
||||
gameEntity.id,
|
||||
gameEntity.name,
|
||||
gameEntity.shouldUseMirrorInfo(),
|
||||
gameEntity.getMirrorPosition(),
|
||||
gameEntity.adIconActive
|
||||
)
|
||||
}
|
||||
|
||||
@ -152,7 +152,7 @@ class SearchGameResultAdapter(
|
||||
|| gameEntity.contentTag!!.isLibaoExists
|
||||
|| gameEntity.contentTag!!.server)
|
||||
val isShowTagByMirror =
|
||||
if (gameEntity.shouldUseMirrorInfo()) isShowTag && gameEntity.mirrorData?.contentTagStatus == "on" else isShowTag
|
||||
if (gameEntity.shouldUseMirrorInfo()) isShowTag && gameEntity.obtainMirrorData()?.contentTagStatus == "on" else isShowTag
|
||||
if (isShowTagByMirror) {
|
||||
topDivider.visibility = View.GONE
|
||||
} else {
|
||||
@ -244,7 +244,7 @@ class SearchGameResultAdapter(
|
||||
|| gameEntity.contentTag!!.server
|
||||
|| gameEntity.contentTag!!.isBbsExists)
|
||||
val isShowTagByMirror =
|
||||
if (gameEntity.shouldUseMirrorInfo()) isShowTag && gameEntity.mirrorData?.contentTagStatus == "on" else isShowTag
|
||||
if (gameEntity.shouldUseMirrorInfo()) isShowTag && gameEntity.obtainMirrorData()?.contentTagStatus == "on" else isShowTag
|
||||
tagContainer.goneIf(!isShowTagByMirror)
|
||||
if (isShowTagByMirror && gameEntity.contentTag != holder.contentTag) {
|
||||
holder.contentTag = gameEntity.contentTag
|
||||
@ -300,7 +300,7 @@ class SearchGameResultAdapter(
|
||||
StringUtils.buildString(
|
||||
entrance, "+(搜索-列表[", key, "=", "$type=",
|
||||
(holder.adapterPosition + 1).toString(), "])"
|
||||
), GameDetailFragment.INDEX_TRENDES, traceEvent = exposureEvent
|
||||
), GameDetailFragment.TAB_TRENDS, traceEvent = exposureEvent
|
||||
)
|
||||
|
||||
gameEntity.run {
|
||||
@ -360,7 +360,7 @@ class SearchGameResultAdapter(
|
||||
StringUtils.buildString(
|
||||
entrance, "+(搜索-列表[", key, "=", "$type=",
|
||||
(holder.adapterPosition + 1).toString(), "])"
|
||||
), GameDetailFragment.INDEX_BBS, traceEvent = exposureEvent
|
||||
), GameDetailFragment.TAB_BBS, traceEvent = exposureEvent
|
||||
)
|
||||
|
||||
gameEntity.run {
|
||||
@ -378,7 +378,7 @@ class SearchGameResultAdapter(
|
||||
}
|
||||
|
||||
if (tagContainer.childCount < 4 && gameEntity.contentTag!!.server) {
|
||||
if (!gameEntity.shouldUseMirrorInfo() || (gameEntity.shouldUseMirrorInfo() && gameEntity.mirrorData?.mirrorServer?.calendar?.isNotEmpty() == true)) {
|
||||
if (!gameEntity.shouldUseMirrorInfo() || (gameEntity.shouldUseMirrorInfo() && gameEntity.obtainMirrorData()?.mirrorServer?.calendar?.isNotEmpty() == true)) {
|
||||
val serverView = getContentTagView(
|
||||
R.drawable.ic_label_server,
|
||||
"",
|
||||
@ -438,7 +438,7 @@ class SearchGameResultAdapter(
|
||||
SearchType.fromString(type).toChinese(),
|
||||
gameEntity.id,
|
||||
gameEntity.name,
|
||||
gameEntity.shouldUseMirrorInfo(),
|
||||
gameEntity.getMirrorPosition(),
|
||||
gameEntity.adIconActive
|
||||
)
|
||||
|
||||
@ -491,7 +491,7 @@ class SearchGameResultAdapter(
|
||||
SearchType.fromString(type).toChinese(),
|
||||
gameEntity.id,
|
||||
gameEntity.name,
|
||||
gameEntity.shouldUseMirrorInfo(),
|
||||
gameEntity.getMirrorPosition(),
|
||||
gameEntity.adIconActive
|
||||
)
|
||||
|
||||
|
||||
@ -88,7 +88,7 @@ class GameServersActivity : DownloadToolbarActivity() {
|
||||
{ MtaHelper.onEvent("开服表", "Tab", if (mServersTest?.isChecked == true) "开测" else "开服") }
|
||||
// init viewpager
|
||||
mFragments.add(GameServersPublishFragment())
|
||||
mFragments.add(GameServersTestFragment())
|
||||
mFragments.add(GameServersTestFragment().with(intent.extras))
|
||||
mViewpager?.setScrollable(false)
|
||||
mViewpager?.offscreenPageLimit = 1
|
||||
mViewpager?.adapter = FragmentAdapter(supportFragmentManager, mFragments)
|
||||
|
||||
@ -155,6 +155,8 @@ class GameServersTestFragment : LazyFragment() {
|
||||
|
||||
val exposureSource = if (arguments?.getParcelable<ExposureSource>(EntranceConsts.KEY_EXPOSURE_SOURCE) != null) {
|
||||
listOf<ExposureSource>(arguments?.getParcelable(EntranceConsts.KEY_EXPOSURE_SOURCE)!!)
|
||||
} else if (requireArguments().getParcelableArrayList<ExposureSource>(EntranceConsts.KEY_EXPOSURE_SOURCE_LIST) != null) {
|
||||
requireArguments().getParcelableArrayList(EntranceConsts.KEY_EXPOSURE_SOURCE_LIST)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
|
||||
@ -7,6 +7,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.common.utils.updateStatusBarColor
|
||||
import com.gh.gamecenter.feature.exposure.ExposureEvent
|
||||
import java.util.ArrayList
|
||||
|
||||
class GameServerTestV2Activity : ToolBarActivity() {
|
||||
|
||||
@ -26,9 +28,15 @@ class GameServerTestV2Activity : ToolBarActivity() {
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun getIntent(context: Context, entrance: String): Intent {
|
||||
fun getIntent(context: Context, entrance: String, exposureEvent: ExposureEvent? = null): Intent {
|
||||
val bundle = Bundle()
|
||||
bundle.putString(EntranceConsts.KEY_ENTRANCE, entrance)
|
||||
exposureEvent?.let {
|
||||
bundle.putParcelableArrayList(
|
||||
EntranceConsts.KEY_EXPOSURE_SOURCE_LIST,
|
||||
ArrayList(exposureEvent.source)
|
||||
)
|
||||
}
|
||||
return getTargetIntent(
|
||||
context,
|
||||
GameServerTestV2Activity::class.java,
|
||||
|
||||
@ -86,6 +86,7 @@ class GameServerTestV2ListAdapter(
|
||||
if (isTheLastOfTheLatestConsecutiveGame) 16F.dip2px() else 8F.dip2px()
|
||||
)
|
||||
holder.bindGameItem(gameEntity, forceShowSubtitle = true)
|
||||
holder.binding.gameDes.setTextColor(R.color.text_title.toColor(context))
|
||||
initGameItemViewHolder(gameEntity, holder, position)
|
||||
}
|
||||
is GameBigImageViewHolder -> {
|
||||
@ -154,7 +155,7 @@ class GameServerTestV2ListAdapter(
|
||||
gameEntity,
|
||||
GameViewHolder(viewHolder.binding),
|
||||
true,
|
||||
"star&brief"
|
||||
// "star&brief"
|
||||
)
|
||||
viewHolder.binding.gameDes.text = gameEntity.brief
|
||||
viewHolder.itemView.setOnClickListener {
|
||||
|
||||
@ -187,6 +187,8 @@ class GameServerTestV2ListFragment :
|
||||
val exposureSource =
|
||||
if (requireArguments().getParcelable<ExposureSource>(EntranceConsts.KEY_EXPOSURE_SOURCE) != null) {
|
||||
listOf<ExposureSource>(requireArguments().getParcelable(EntranceConsts.KEY_EXPOSURE_SOURCE)!!)
|
||||
} else if (requireArguments().getParcelableArrayList<ExposureSource>(EntranceConsts.KEY_EXPOSURE_SOURCE_LIST) != null) {
|
||||
requireArguments().getParcelableArrayList(EntranceConsts.KEY_EXPOSURE_SOURCE_LIST)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
|
||||
@ -79,6 +79,7 @@ class DetailPlayerView @JvmOverloads constructor(context: Context, attrs: Attrib
|
||||
private var mVolumeObserver: VolumeObserver
|
||||
private var mScheduledHideDisposable: Disposable? = null //延迟隐藏mBottomContainer计时器
|
||||
private var mLastClickTime = 0L
|
||||
private var mLastGetContentLengthTime = 0L
|
||||
private var mLottieLike: LottieAnimationView? = null
|
||||
private var mHandler: Handler? = null
|
||||
private var weChatAnimate: AnimatorSet? = null
|
||||
@ -1049,7 +1050,11 @@ class DetailPlayerView @JvmOverloads constructor(context: Context, attrs: Attrib
|
||||
val videoTotalTime = duration / 1000
|
||||
val progress = if (videoTotalTime != 0) videoPlayTs.toFloat() / videoTotalTime.toFloat() * 100 else 0f
|
||||
if (mContentLength == 0.0) {
|
||||
mContentLength = ExoCacheManager.getContentLength(mVideoEntity!!.url) / 1024.0 / 1024.0
|
||||
val newGetContentLengthTime = System.currentTimeMillis()
|
||||
if (newGetContentLengthTime - mLastGetContentLengthTime > 5000) {
|
||||
mLastGetContentLengthTime = newGetContentLengthTime
|
||||
mContentLength = ExoCacheManager.getContentLength(mVideoEntity!!.url) / 1024.0 / 1024.0
|
||||
}
|
||||
}
|
||||
//https://exoplayer.dev/hello-world.html#a-note-on-threading
|
||||
runOnUiThread {
|
||||
|
||||
@ -149,10 +149,7 @@ class HomeRecentVGameAdapter(context: Context) : DiffUtilAdapter<VGameItemData>(
|
||||
}
|
||||
} else {
|
||||
binding.root.setOnClickListener {
|
||||
VHelper.installOrLaunch(
|
||||
binding.root.context,
|
||||
downloadEntity.packageName
|
||||
)
|
||||
VHelper.installOrLaunch(binding.root.context, downloadEntity)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -180,7 +180,7 @@ class VDownloadManagerAdapter(
|
||||
}
|
||||
|
||||
val downloadEntity = DownloadManager.getInstance().getDownloadEntitySnapshot(gameEntity)
|
||||
?: VHelper.getDownloadEntitySnapshot(gameEntity.id, gameEntity.getUniquePackageName())
|
||||
?: VHelper.getVDownloadEntitySnapshot(gameEntity.id, gameEntity.getUniquePackageName())
|
||||
|
||||
updateDownloadBtnAndDes(
|
||||
mContext,
|
||||
@ -527,7 +527,7 @@ class VDownloadManagerAdapter(
|
||||
btnText = context.getString(R.string.launch)
|
||||
setOnClickListener {
|
||||
CurrentActivityHolder.getCurrentActivity()?.let {
|
||||
VHelper.installOrLaunch(it, downloadEntity.packageName)
|
||||
VHelper.installOrLaunch(it, downloadEntity)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -126,6 +126,9 @@ object VHelper {
|
||||
// 是否已经尝试过重连
|
||||
private var mHasAlreadyTriedReConnect = false
|
||||
|
||||
// 临时的用来临时匹配安装完成时包名对应的游戏 ID 的 Map
|
||||
private var mTempPackageNameAndGameIdMap = hashMapOf<String, String>()
|
||||
|
||||
val vGameLiveData by lazy { mVGameDao.getAllLiveData() }
|
||||
|
||||
private val mVGameObserver by lazy {
|
||||
@ -385,7 +388,7 @@ object VHelper {
|
||||
@JvmStatic
|
||||
fun getVGameSnapshot(gameId: String? = null, packageName: String? = null): VGameEntity? {
|
||||
return mVGameSnapshotList.find {
|
||||
it.packageName == packageName && (gameId == null || it.downloadEntity.gameId == gameId)
|
||||
it.packageName == packageName && (gameId.isNullOrEmpty() || it.downloadEntity.gameId == gameId)
|
||||
}
|
||||
}
|
||||
|
||||
@ -552,6 +555,9 @@ object VHelper {
|
||||
|
||||
if (showDialogIfVSpaceIsNeeded(context, downloadEntity.gameId, downloadEntity.name)) return
|
||||
|
||||
// 更新此包名对应的 gameId Map
|
||||
mTempPackageNameAndGameIdMap[downloadEntity.packageName] = downloadEntity.gameId
|
||||
|
||||
// 当且仅当
|
||||
// 1. 全局安装完成启动游戏开关打开
|
||||
// 2. 服务连接不成功或是手动触发的安装
|
||||
@ -680,7 +686,9 @@ object VHelper {
|
||||
*/
|
||||
fun onInstallFinished(packageName: String, result: VGameInstallerResult) {
|
||||
runOnIoThread {
|
||||
val downloadEntity = getDownloadEntityByPackageName(packageName)
|
||||
val gameId = mTempPackageNameAndGameIdMap[packageName] ?: ""
|
||||
|
||||
val downloadEntity = getVDownloadEntity(gameId = gameId, packageName = packageName)
|
||||
|
||||
if (downloadEntity != null) {
|
||||
// 去掉更新标记
|
||||
@ -753,13 +761,19 @@ object VHelper {
|
||||
* 游戏是否正在安装中
|
||||
*/
|
||||
fun isInstalling(packageName: String): Boolean {
|
||||
val downloadEntity = getDownloadEntityByPackageName(packageName) ?: return false
|
||||
val gameId = mTempPackageNameAndGameIdMap[packageName] ?: ""
|
||||
val downloadEntity = getVDownloadEntity(gameId = gameId, packageName = packageName) ?: return false
|
||||
return (mInstallingVaPathSet.contains(downloadEntity.path))
|
||||
}
|
||||
|
||||
private fun getDownloadEntityByPackageName(packageName: String): DownloadEntity? {
|
||||
return DownloadManager.getInstance().getDownloadEntitySnapshotByPackageName(packageName)
|
||||
?: getDownloadEntitySnapshot(gameId = null, packageName = packageName)
|
||||
/**
|
||||
* 获取实体 (虽然实体是 DownloadEntity 其实就是游戏实体)
|
||||
* 优先从下载管理里获取(根据 gameId 获取)
|
||||
* 下载管理不存在时从畅玩游戏数据库的里获取
|
||||
*/
|
||||
private fun getVDownloadEntity(gameId: String, packageName: String): DownloadEntity? {
|
||||
return DownloadManager.getInstance().getDownloadEntitySnapshot("", gameId, true)
|
||||
?: getVDownloadEntitySnapshot(gameId = gameId, packageName = packageName)
|
||||
}
|
||||
|
||||
private fun insertInstalledGameToProvider(downloadEntity: DownloadEntity, fromRetry: Boolean = false) {
|
||||
@ -791,11 +805,23 @@ object VHelper {
|
||||
}
|
||||
}
|
||||
|
||||
fun installOrLaunch(context: Context, downloadEntity: DownloadEntity) {
|
||||
Utils.log(LOG_TAG, "检测是需要安装还是启动 ${downloadEntity.gameId}")
|
||||
|
||||
installOrLaunch(context, downloadEntity.packageName, downloadEntity.gameId)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun installOrLaunch(context: Context, gameEntity: GameEntity) {
|
||||
Utils.log(LOG_TAG, "检测是需要安装还是启动 ${gameEntity.id}")
|
||||
|
||||
installOrLaunch(context, gameEntity.getUniquePackageName() ?: "", gameEntity.id)
|
||||
}
|
||||
|
||||
/**
|
||||
* 安装或启动应用
|
||||
*/
|
||||
@JvmStatic
|
||||
fun installOrLaunch(context: Context, packageName: String) {
|
||||
private fun installOrLaunch(context: Context, packageName: String, gameId: String) {
|
||||
Utils.log(LOG_TAG, "检测是需要安装还是启动 $packageName")
|
||||
|
||||
validateVSpaceBeforeAction(context, null) {
|
||||
@ -809,7 +835,7 @@ object VHelper {
|
||||
}
|
||||
|
||||
// 检查下载管理是否有下载实体,有实体表明未安装成功
|
||||
val downloadEntity = getDownloadEntityByPackageName(packageName)
|
||||
val downloadEntity = getVDownloadEntity(gameId = gameId, packageName = packageName)
|
||||
|
||||
if (downloadEntity != null) {
|
||||
val downloadedFile = File(downloadEntity.path)
|
||||
@ -837,7 +863,7 @@ object VHelper {
|
||||
// 置空下载挂起回调(能 launch 游戏说明畅玩组件已安装)
|
||||
mPendingDownloadCallback = null
|
||||
|
||||
val downloadEntity = getDownloadEntityByPackageName(packageName)
|
||||
val downloadEntity = getVDownloadEntity(gameId = "", packageName = packageName)
|
||||
|
||||
val gameId = downloadEntity?.gameId ?: "unknown"
|
||||
val gameName = downloadEntity?.name ?: "unknown"
|
||||
@ -973,10 +999,10 @@ object VHelper {
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据游戏 ID 和包名获取下载快照
|
||||
* 根据游戏 ID 和包名获取畅玩游戏的实体快照
|
||||
*/
|
||||
@JvmStatic
|
||||
fun getDownloadEntitySnapshot(gameId: String?, packageName: String?): DownloadEntity? {
|
||||
fun getVDownloadEntitySnapshot(gameId: String?, packageName: String?): DownloadEntity? {
|
||||
return getVGameSnapshot(gameId, packageName)?.downloadEntity
|
||||
}
|
||||
|
||||
|
||||
@ -153,10 +153,7 @@ object VLoadCompleteWindowHelper {
|
||||
"启动",
|
||||
mAdapter.gameEntityList[mBinding.viewPager.currentItem].id
|
||||
)
|
||||
VHelper.installOrLaunch(
|
||||
activity,
|
||||
mAdapter.gameEntityList[mBinding.viewPager.currentItem].getApk()[0].packageName
|
||||
)
|
||||
VHelper.installOrLaunch(activity, mAdapter.gameEntityList[mBinding.viewPager.currentItem])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,8 +1,12 @@
|
||||
package com.gh.vspace.db
|
||||
|
||||
import androidx.room.TypeConverter
|
||||
import com.gh.gamecenter.common.utils.toObject
|
||||
import com.gh.gamecenter.common.utils.tryWithDefaultCatch
|
||||
import com.gh.gamecenter.core.utils.GsonUtils
|
||||
import com.lightgame.download.DownloadEntity
|
||||
import com.lightgame.download.DownloadStatus
|
||||
import org.json.JSONObject
|
||||
|
||||
class VGameConverter {
|
||||
|
||||
@ -13,7 +17,35 @@ class VGameConverter {
|
||||
|
||||
@TypeConverter
|
||||
fun convertString2DownloadEntity(string: String): DownloadEntity {
|
||||
return GsonUtils.fromJson(string, DownloadEntity::class.java)
|
||||
val downloadEntity = DownloadEntity()
|
||||
|
||||
val rawJsonObject = JSONObject(string)
|
||||
|
||||
val keys = rawJsonObject.keys()
|
||||
var tempSize = ""
|
||||
while (keys.hasNext()) {
|
||||
val key = keys.next()
|
||||
val value = rawJsonObject.optString(key)
|
||||
|
||||
if (value.startsWith("http")) {
|
||||
downloadEntity.url = value
|
||||
} else if (value.endsWith("apk")) {
|
||||
downloadEntity.path = value
|
||||
} else if (value.startsWith("{\"")) {
|
||||
downloadEntity.meta = value.toObject()
|
||||
downloadEntity.name = downloadEntity.meta["game_name"]
|
||||
} else if (value == tempSize) {
|
||||
tryWithDefaultCatch {
|
||||
downloadEntity.size = value.toLong()
|
||||
}
|
||||
} else {
|
||||
tempSize = value
|
||||
}
|
||||
}
|
||||
|
||||
downloadEntity.status = DownloadStatus.done
|
||||
|
||||
return downloadEntity
|
||||
}
|
||||
|
||||
}
|
||||
@ -80,7 +80,7 @@ class ShortcutManager private constructor() {
|
||||
*/
|
||||
fun tryCreateShortCut(context: Context, gameId: String, gamePkg: String, result: OnCreateShortcutResult) {
|
||||
VHelper.postOnInitialized {
|
||||
val downloadEntity = VHelper.getDownloadEntitySnapshot(gameId, gamePkg)
|
||||
val downloadEntity = VHelper.getVDownloadEntitySnapshot(gameId, gamePkg)
|
||||
runOnUiThread {
|
||||
if (downloadEntity == null) {
|
||||
result.failed()
|
||||
|
||||
@ -70,6 +70,7 @@ class WebFragment : LazyFragment(), IScrollable {
|
||||
private var mToolBoxEntity: ToolBoxEntity? = null
|
||||
|
||||
private var newsId: String? = null
|
||||
private var mBbsId: String? = null // 论坛 id
|
||||
private var mNavigationTitle: String? = null //导航栏标题
|
||||
private var mBackConfirmationContent: String? = null //返回确认弹窗内容
|
||||
private var mGameName: String? = null
|
||||
@ -290,6 +291,7 @@ class WebFragment : LazyFragment(), IScrollable {
|
||||
mIsBindWechat = args.getBoolean(KEY_IS_BIND_WECHAT, false)
|
||||
mIsTools = args.getBoolean(KEY_ISTOOLS, false)
|
||||
mQaType = args.getInt(KEY_QA_TYPE, -1)
|
||||
mBbsId = args.getString(EntranceConsts.KEY_BBS_ID)
|
||||
mAutoCompletionTitle = args.getBoolean(KEY_COMPLETION_TITLE, true)
|
||||
mNavigationTitle = args.getString(EntranceConsts.KEY_GAMENAME)
|
||||
newsId = args.getString(EntranceConsts.KEY_NEWSID)
|
||||
@ -304,7 +306,7 @@ class WebFragment : LazyFragment(), IScrollable {
|
||||
mLeaveWebpageToHandleTitle = args.getBoolean(KEY_LEAVE_WEB_PAGE_TO_HANDLE_TITLE, false)
|
||||
mWebUrl = dealWithUrl(args.getString(EntranceConsts.KEY_URL, ""))
|
||||
}
|
||||
mJsApi = DefaultJsApi(requireContext(), mEntrance, this)
|
||||
mJsApi = DefaultJsApi(requireContext(), mEntrance, this, mBbsId)
|
||||
}
|
||||
|
||||
@SuppressLint("SetJavaScriptEnabled")
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 2.2 KiB |
BIN
app/src/main/res/drawable-xxxhdpi/icon_section_heat.webp
Normal file
BIN
app/src/main/res/drawable-xxxhdpi/icon_section_heat.webp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.9 KiB |
BIN
app/src/main/res/drawable-xxxhdpi/icon_section_newest.webp
Normal file
BIN
app/src/main/res/drawable-xxxhdpi/icon_section_newest.webp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.3 KiB |
@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<solid android:color="@color/background_space" />
|
||||
<solid android:color="@color/item_game_test_v2_recommend_label" />
|
||||
<corners
|
||||
android:radius="4dp" />
|
||||
</shape>
|
||||
@ -3,7 +3,7 @@
|
||||
android:shape="rectangle">
|
||||
<stroke
|
||||
android:width="0.5dp"
|
||||
android:color="@color/divider" />
|
||||
android:color="@color/item_game_test_v2_stroke" />
|
||||
<corners android:radius="8dp" />
|
||||
<solid android:color="@color/background_white" />
|
||||
<solid android:color="@color/item_game_test_v2" />
|
||||
</shape>
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user