Compare commits
162 Commits
feature-ci
...
feature-me
| Author | SHA1 | Date | |
|---|---|---|---|
| 0cdf7053df | |||
| 9e67be67e6 | |||
| df2f52cf7a | |||
| 14ed8e6d13 | |||
| 4474991029 | |||
| c8614ce703 | |||
| 2472a6879d | |||
| f040691e24 | |||
| 3648dced06 | |||
| 94f94f5186 | |||
| fa03fc6d4c | |||
| f23eb48185 | |||
| 8c5568c24d | |||
| 1bdc1a6430 | |||
| b289e78a88 | |||
| ac4143fe0a | |||
| 938cb1c9cb | |||
| 7445f98086 | |||
| c2552096e1 | |||
| c6c0fe771a | |||
| 623708fed1 | |||
| faec33658d | |||
| 2fda01215a | |||
| ee6ec82d27 | |||
| 317cce1f56 | |||
| f29f5089fd | |||
| f5b71fdcb2 | |||
| 79c0e61a24 | |||
| bfeadf8c75 | |||
| b118309d4e | |||
| 5aab516058 | |||
| 3ef4214313 | |||
| dcca1b9ff9 | |||
| 7bdc7a946d | |||
| 55a92847c7 | |||
| b858365c1d | |||
| 92d2f7e701 | |||
| 0967df5751 | |||
| d6e5b88d95 | |||
| b08e653b99 | |||
| f539e45e18 | |||
| 6a6ff5b12a | |||
| b8ba5f85c9 | |||
| 67ed3cb919 | |||
| c973bd6b5e | |||
| 61e9bcb89d | |||
| 2d3f18a302 | |||
| 401d36a74e | |||
| bee52ba0bd | |||
| 6d2e0853ff | |||
| 3b23f086c8 | |||
| d50e4e044b | |||
| 84f56681d0 | |||
| 7fbb3eec86 | |||
| ef11044b50 | |||
| 26395038bd | |||
| 68b0691618 | |||
| f5a4e4ca06 | |||
| c75eacaf45 | |||
| aa5ecb8e6c | |||
| 00dda64279 | |||
| 2bd3be0088 | |||
| 3bff64af27 | |||
| 32210875da | |||
| db9d7d9d22 | |||
| 1f211356fd | |||
| 81b5b6b369 | |||
| 98e263f99a | |||
| 81b74e7077 | |||
| 083a893582 | |||
| 405d4b709f | |||
| 36942aab5a | |||
| e61b21ca49 | |||
| b9e7f4145a | |||
| 517b474a1e | |||
| dfac1e93b7 | |||
| d848081f62 | |||
| 2bac0feb2c | |||
| a602055f98 | |||
| 28ba14e9ec | |||
| c36fb04f81 | |||
| 7d26a66bc3 | |||
| 9451f9bae3 | |||
| ac18a678ff | |||
| bd2871788f | |||
| beeece1d0e | |||
| 1e9e39eea9 | |||
| 9162b0f67d | |||
| 46dd84aaf9 | |||
| e5e0d99abb | |||
| 6f34b16bba | |||
| 5b2512f16f | |||
| 9a1e0f1ae2 | |||
| a03b6b643f | |||
| 8b2cb8b40c | |||
| c2402bd4d2 | |||
| b724cde6ca | |||
| fd3058e0be | |||
| 03431ef3a3 | |||
| 23e2a79bee | |||
| 3aa14c9541 | |||
| 39fcc5ed63 | |||
| 577be922a6 | |||
| 19d128e98a | |||
| a8acf1d6c8 | |||
| ce0a301348 | |||
| 2567e520da | |||
| 2394cf837e | |||
| bf692569e6 | |||
| 090102ec5d | |||
| 61e9966de8 | |||
| fe26504f43 | |||
| e4d2036cc2 | |||
| 2627a4c39c | |||
| a44d454f13 | |||
| 0600daadde | |||
| f29b1a6124 | |||
| 1892d10040 | |||
| 9a8df13870 | |||
| 4eabeae5d5 | |||
| c4b1be9925 | |||
| b2a6393afd | |||
| b5c15940a1 | |||
| 3f6f55b265 | |||
| ba666da059 | |||
| 8b1f251c80 | |||
| 01aadbd64c | |||
| 6256b31cd9 | |||
| 8e4d1e7e6e | |||
| fa29e00864 | |||
| 1b412bf081 | |||
| 0d82b9ec71 | |||
| 1055d0c728 | |||
| a53183d405 | |||
| 11874c3984 | |||
| 47464b2864 | |||
| a2ed4987ed | |||
| 4392f9f20b | |||
| 8e43d0cae3 | |||
| f83f67553c | |||
| 14893acf4b | |||
| 1cbed03788 | |||
| 0eff89acfc | |||
| 560b6046ab | |||
| e898886659 | |||
| b1abadc145 | |||
| 05da2c3da4 | |||
| e83ece5520 | |||
| 08a86c778d | |||
| 58119a0bdb | |||
| 8d9c57e972 | |||
| b216d33d6b | |||
| 4fe062ea40 | |||
| 7d678085d5 | |||
| acae755461 | |||
| f29d3b4e29 | |||
| e1907fcea8 | |||
| 76564b2414 | |||
| c72d34b4f7 | |||
| 8145f389a9 | |||
| 45a8f9683e | |||
| 572cbba819 |
@ -1,12 +1,57 @@
|
||||
stages:
|
||||
- analysis
|
||||
- sendmail
|
||||
- android-build && analysis
|
||||
- docker-build && sendmail
|
||||
- deploy-trigger
|
||||
|
||||
## 代码检查
|
||||
android_build:
|
||||
tags:
|
||||
- offline-test
|
||||
stage: android-build && analysis
|
||||
image: hub.shanqu.cc/devops/ci-android:jdk11
|
||||
variables:
|
||||
KUBERNETES_CPU_LIMIT: "16"
|
||||
GIT_SUBMODULE_STRATEGY: recursive
|
||||
Apk_Path: "app/build/outputs/apk/**/release/*.apk"
|
||||
script:
|
||||
- export GRADLE_USER_HOME=./.gradle
|
||||
- chmod +x ./gradlew
|
||||
- ./scripts/meta_build.sh --config_id 6400549c21c2c94ead074500 --sdk_platform toutiao --sdk_version 5.3.0 --channel BD-GHZS-ZP-KY --activate_reporting_ratio 60 --first_lanuch_jump e1wibGlua190eXBlXCI6XCJcIixcImxpbmtfaWRcIjpcIlwiLFwibGlua190ZXh0XCI6XCJcIixcImhvbWVfaW5kZXhcIjpcIlwiLFwiYm90dG9tX2luZGV4XCI6XCJcIn0= --unix_timestamp 1677657618 --output ./release/com.gh.gamecenter_5.17.4_694_BD-GHZS-ZP-KY_toutiao_5.3.0_1677657618.apk
|
||||
- rm -rf ./.gradle/caches/build-cache-1
|
||||
cache:
|
||||
paths:
|
||||
- .gradle
|
||||
artifacts:
|
||||
paths:
|
||||
- Dockerfile
|
||||
expire_in: 15 mins
|
||||
only:
|
||||
- feature-meta_build
|
||||
|
||||
# 构建推送docker镜像
|
||||
docker-build:
|
||||
tags:
|
||||
- offline-test
|
||||
stage: docker-build && sendmail
|
||||
image: hub.shanqu.cc/library/docker:latest
|
||||
variables:
|
||||
GIT_STRATEGY: none
|
||||
script:
|
||||
- projectPath=`echo $CI_PROJECT_PATH | sed 's#/#-#g'`
|
||||
- docker build -t registry.cn-shenzhen.aliyuncs.com/ghzs/$projectPath:latest .
|
||||
- docker push registry.cn-shenzhen.aliyuncs.com/ghzs/$projectPath:latest
|
||||
- docker run -e PROJECTKEY=$projectPath -e EMAIL=$GITLAB_USER_EMAIL -e BRANCH=$CI_COMMIT_REF_NAME --name send-email --rm hub.shanqu.cc/platform/send-sonar-report:latest
|
||||
cache:
|
||||
paths:
|
||||
- .gradle
|
||||
policy: pull
|
||||
only:
|
||||
- feature-meta_build
|
||||
|
||||
# 代码检查
|
||||
sonarqube_analysis:
|
||||
tags:
|
||||
- offline-test
|
||||
stage: analysis
|
||||
stage: android-build && analysis
|
||||
image: sonarsource/sonar-scanner-cli:latest
|
||||
dependencies: [] #禁止传递来的artifact
|
||||
script:
|
||||
@ -27,17 +72,14 @@ sonarqube_analysis:
|
||||
-Dsonar.gitlab.merge_request_discussion=true
|
||||
-Dsonar.java.binaries=. # 如果不使用Maven或Gradle进行分析,则必须手动提供测试二进制文件
|
||||
only:
|
||||
- dev
|
||||
|
||||
## 发送简易检测结果报告
|
||||
send_sonar_report:
|
||||
tags:
|
||||
- offline-test
|
||||
stage: sendmail
|
||||
image: hub.shanqu.cc/library/docker:latest
|
||||
dependencies: [] #禁止传递来的artifact
|
||||
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
|
||||
only:
|
||||
- dev
|
||||
- feature-meta_build
|
||||
|
||||
## 触发多项目构建
|
||||
trigger_job:
|
||||
stage: deploy-trigger
|
||||
variables:
|
||||
BUILD_PROJECT_NAME: $CI_PROJECT_PATH
|
||||
trigger:
|
||||
project: devops/automation/build-eci
|
||||
branch: dev
|
||||
|
||||
|
||||
8
.gitmodules
vendored
8
.gitmodules
vendored
@ -1,13 +1,13 @@
|
||||
[submodule "libraries/LGLibrary"]
|
||||
path = libraries/LGLibrary
|
||||
url = git@git.shanqu.cc:android/common-library.git
|
||||
url = ../../../android/common-library.git
|
||||
branch = master
|
||||
[submodule "vspace-bridge"]
|
||||
path = vspace-bridge
|
||||
url = git@git.shanqu.cc:cwzs/android/vspace-bridge.git
|
||||
url = ../../../cwzs/android/vspace-bridge.git
|
||||
[submodule "module_common/src/debug/assets/assistant-android-mock"]
|
||||
path = module_common/src/debug/assets/assistant-android-mock
|
||||
url = git@git.shanqu.cc:halo/android/assistant-android-mock.git
|
||||
url = ../../../halo/android/assistant-android-mock.git
|
||||
[submodule "ndownload"]
|
||||
path = ndownload
|
||||
url = git@git.shanqu.cc:android/ndownload.git
|
||||
url = ../../../android/ndownload.git
|
||||
|
||||
15
Dockerfile
Normal file
15
Dockerfile
Normal file
@ -0,0 +1,15 @@
|
||||
FROM openjdk:11-jdk
|
||||
WORKDIR /project
|
||||
SHELL ["/bin/bash", "-c"]
|
||||
#配置SDK环境变量
|
||||
ENV ANDROID_SDK_ROOT /usr/lib/sdk
|
||||
ENV ANDROID_HOME /usr/lib/sdk
|
||||
ENV PATH $ANDROID_SDK_ROOT:$PATH
|
||||
ENV PATH=$PATH:${ANDROID_HOME}/cmdline-tools/cmdline-tools/bin/
|
||||
ENV GRADLE_USER_HOME /project/.gradle
|
||||
RUN source ~/.bashrc
|
||||
RUN sed -i "s@http://\(deb\|security\).debian.org@https://mirrors.aliyun.com@g" /etc/apt/sources.list \
|
||||
&& apt-get --quiet update --yes \
|
||||
&& apt-get --quiet install --yes lib32stdc++6 lib32z1 libncurses5 util-linux bash tzdata librdkafka-dev pkgconf \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
COPY .gradle /project/.gradle
|
||||
@ -9,6 +9,9 @@ import groovy.xml.XmlUtil
|
||||
|
||||
android {
|
||||
|
||||
String CONFIG_ID = ""
|
||||
String FIRST_LAUNCH = ""
|
||||
|
||||
buildFeatures {
|
||||
viewBinding true
|
||||
dataBinding true
|
||||
@ -67,9 +70,13 @@ android {
|
||||
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt', 'proguard-fresco.txt'
|
||||
|
||||
/**
|
||||
* All third-party appid/appkey
|
||||
*/
|
||||
// 推广用的配置 id
|
||||
buildConfigField "String", "CONFIG_ID", "\"${CONFIG_ID}\""
|
||||
|
||||
// 首次启动的跳转配置
|
||||
buildConfigField "String", "FIRST_LAUNCH", "\"${FIRST_LAUNCH}\""
|
||||
|
||||
// All third-party appid/appkey
|
||||
buildConfigField "String", "API_HOST", "\"${API_HOST}\""
|
||||
buildConfigField "String", "NEW_API_HOST", "\"${NEW_API_HOST}\""
|
||||
buildConfigField "String", "VAPI_HOST", "\"${VAPI_HOST}\""
|
||||
@ -127,7 +134,7 @@ android {
|
||||
variantFilter { variant ->
|
||||
def names = variant.flavors*.name
|
||||
def isDebugType = variant.buildType.name == "debug"
|
||||
if ((names.contains("tea") || name.contains("kuaishou")) && isDebugType) {
|
||||
if ((names.contains("tea") || name.contains("kuaishou") || name.contains("gdt")) && isDebugType) {
|
||||
setIgnore(true)
|
||||
}
|
||||
}
|
||||
@ -147,6 +154,9 @@ android {
|
||||
kuaishou {
|
||||
java.srcDirs = ['src/main/java', 'src/kuaishou/java']
|
||||
}
|
||||
gdt {
|
||||
java.srcDirs = ['src/main/java', 'src/gdt/java']
|
||||
}
|
||||
}
|
||||
|
||||
productFlavors {
|
||||
@ -194,6 +204,16 @@ android {
|
||||
buildConfigField "String", "QUICK_LOGIN_APPID", "\"${QUICK_LOGIN_APPID}\""
|
||||
buildConfigField "String", "QUICK_LOGIN_APPKEY", "\"${QUICK_LOGIN_APPKEY}\""
|
||||
}
|
||||
|
||||
gdt {
|
||||
dimension "env"
|
||||
|
||||
buildConfigField "String", "DEV_API_HOST", "\"${API_HOST}\""
|
||||
buildConfigField "String", "NEW_DEV_API_HOST", "\"${NEW_API_HOST}\""
|
||||
buildConfigField "String", "DEV_VAPI_HOST", "\"${VAPI_HOST}\""
|
||||
buildConfigField "String", "QUICK_LOGIN_APPID", "\"${QUICK_LOGIN_APPID}\""
|
||||
buildConfigField "String", "QUICK_LOGIN_APPKEY", "\"${QUICK_LOGIN_APPKEY}\""
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -209,6 +229,7 @@ dependencies {
|
||||
|
||||
teaImplementation fileTree(include: ['*.jar', '*.aar'], dir: 'src/tea/libs')
|
||||
kuaishouImplementation fileTree(include: ['*.jar', '*.aar'], dir: 'src/kuaishou/libs')
|
||||
gdtImplementation fileTree(include: ['*.jar', '*.aar'], dir: 'src/gdt/libs')
|
||||
testImplementation 'junit:junit:4.12'
|
||||
|
||||
debugImplementation "com.squareup.leakcanary:leakcanary-android:${leakcanary}"
|
||||
@ -216,8 +237,7 @@ dependencies {
|
||||
|
||||
// debugImplementation "com.gu.android:toolargetool:${toolargetool}" // 需要使用调试时才启用
|
||||
debugImplementation "com.github.nichbar:WhatTheStack:${whatTheStack}"
|
||||
debugImplementation "io.github.didi.dokit:dokitx:${dokit}"
|
||||
|
||||
// debugImplementation "io.github.didi.dokit:dokitx:${dokit}"
|
||||
|
||||
implementation "androidx.multidex:multidex:${multiDex}"
|
||||
implementation "androidx.fragment:fragment-ktx:${fragment}"
|
||||
@ -289,12 +309,17 @@ dependencies {
|
||||
// implementation(project(':module_setting_compose')) {
|
||||
// exclude group: 'androidx.swiperefreshlayout'
|
||||
// }
|
||||
implementation(project(':module_core_feature')){
|
||||
implementation(project(':module_core_feature')) {
|
||||
exclude group: 'androidx.swiperefreshlayout'
|
||||
}
|
||||
implementation(project(':module_feedback')) {
|
||||
exclude group: 'androidx.swiperefreshlayout'
|
||||
}
|
||||
implementation(project(':module_sensors_data')) {
|
||||
exclude group: 'androidx.swiperefreshlayout'
|
||||
}
|
||||
implementation(project(':module_vpn'))
|
||||
implementation(project(':module_pkg'))
|
||||
// 默认不接入光能模块,提高编译速度
|
||||
// debugImplementation(project(':module_energy')) {
|
||||
// exclude group: 'androidx.swiperefreshlayout'
|
||||
|
||||
@ -69,4 +69,14 @@
|
||||
-keep class com.lzf.easyfloat.* {*;}
|
||||
|
||||
### dokit
|
||||
-keep class com.didichuxing.** {*;}
|
||||
-keep class com.didichuxing.** {*;}
|
||||
|
||||
### 广点通SDK
|
||||
-dontwarn com.qq.gdt.action.**
|
||||
-keep class com.qq.gdt.action.** {*;}
|
||||
-keep public class com.tencent.turingfd.sdk.**
|
||||
|
||||
-keepclasseswithmembers class * {
|
||||
native <methods>;
|
||||
}
|
||||
|
||||
|
||||
37
app/src/gdt/java/com/gh/gamecenter/GdtHelper.kt
Normal file
37
app/src/gdt/java/com/gh/gamecenter/GdtHelper.kt
Normal file
@ -0,0 +1,37 @@
|
||||
package com.gh.gamecenter
|
||||
|
||||
import android.app.Application
|
||||
import com.lightgame.utils.Utils
|
||||
import com.qq.gdt.action.ActionParam
|
||||
import com.qq.gdt.action.ActionType
|
||||
import com.qq.gdt.action.GDTAction
|
||||
import org.json.JSONObject
|
||||
|
||||
object GdtHelper {
|
||||
private const val USER_ACTION_SET_ID = "1201041887"
|
||||
private const val APP_SECRET_ID = "c29cc5c48cf540c43b4b97363bb09216"
|
||||
|
||||
private const val KS_USER_ACTION_SET_ID = "1201032128"
|
||||
private const val KS_APP_SECRET_ID = "9bdbbb81d4e0bd333a2a581f9ee36986"
|
||||
|
||||
@JvmStatic
|
||||
fun init(application: Application, channel: String) {
|
||||
if (channel == "KS_GDT_GHZS_MC01") {
|
||||
GDTAction.init(application, KS_USER_ACTION_SET_ID, KS_APP_SECRET_ID, channel)
|
||||
} else {
|
||||
GDTAction.init(application, USER_ACTION_SET_ID, APP_SECRET_ID, channel)
|
||||
}
|
||||
Utils.log("init GdtHelper")
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun logAction(type: String) {
|
||||
when (type) {
|
||||
"EVENT_ACTIVE" -> GDTAction.logAction(ActionType.START_APP)
|
||||
"active_register" -> GDTAction.logAction(ActionType.REGISTER)
|
||||
"EVENT_NEXTDAY_STAY" -> GDTAction.logAction(ActionType.START_APP, JSONObject().apply {
|
||||
put(ActionParam.Key.LENGTH_OF_STAY, 1)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,48 @@
|
||||
package com.gh.gamecenter.provider
|
||||
|
||||
import android.app.Activity
|
||||
import android.app.Application
|
||||
import android.text.TextUtils
|
||||
import com.gh.gamecenter.GdtHelper
|
||||
import com.gh.gamecenter.core.provider.IFlavorProvider
|
||||
import com.gh.gamecenter.core.utils.SPUtils
|
||||
import com.gh.gamecenter.core.utils.TimeUtils
|
||||
import com.halo.assistant.HaloApp
|
||||
import com.leon.channel.helper.ChannelReaderUtil
|
||||
|
||||
class FlavorProviderImp : IFlavorProvider {
|
||||
|
||||
override fun init(application: Application, activity: Activity) {
|
||||
GdtHelper.init(application, getChannelStr(application))
|
||||
|
||||
if (HaloApp.getInstance().isBrandNewInstall) {
|
||||
logEvent("EVENT_ACTIVE")
|
||||
SPUtils.setLong("TIME_OF_BRAND_NEW_INSTALL", System.currentTimeMillis() / 1000)
|
||||
} else {
|
||||
val shouldSendRetentionLogEvent =
|
||||
SPUtils.getBoolean("SHOULD_SEND_RETENTION_EVENT", true)
|
||||
val installTimeNotToday =
|
||||
!TimeUtils.isToday(SPUtils.getLong("TIME_OF_BRAND_NEW_INSTALL", System.currentTimeMillis() / 1000))
|
||||
if (shouldSendRetentionLogEvent && installTimeNotToday) {
|
||||
logEvent("EVENT_NEXTDAY_STAY")
|
||||
SPUtils.setBoolean("SHOULD_SEND_RETENTION_EVENT", false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun getChannelStr(application: Application): String {
|
||||
var channel = ChannelReaderUtil.getChannel(application)
|
||||
if (channel == null || TextUtils.isEmpty(channel.trim())) {
|
||||
channel = GDT_DEFAULT_CHANNEL
|
||||
}
|
||||
return channel
|
||||
}
|
||||
|
||||
override fun logEvent(content: String) {
|
||||
GdtHelper.logAction(content)
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val GDT_DEFAULT_CHANNEL = "GDT_GHZS_01"
|
||||
}
|
||||
}
|
||||
BIN
app/src/gdt/libs/GDTActionSDK.min.1.8.4.aar
Normal file
BIN
app/src/gdt/libs/GDTActionSDK.min.1.8.4.aar
Normal file
Binary file not shown.
@ -18,9 +18,9 @@ import kotlin.concurrent.fixedRateTimer
|
||||
|
||||
object FixedRateJobHelper {
|
||||
private const val CHECKER_PERIOD: Long = 15 * 1000L
|
||||
private const val TIME_PERIOD: Long = 600 * 1000L
|
||||
private const val LOGHUB_PERIOD: Long = 120 * 1000L
|
||||
private const val EXPOSURE_PERIOD: Long = 300 * 1000L
|
||||
private const val TIME_PERIOD: Long = 10 * 60 * 1000L
|
||||
private const val LOGHUB_PERIOD: Long = 2 * 60 * 1000L
|
||||
private const val EXPOSURE_PERIOD: Long = 5 * 60 * 1000L
|
||||
private const val REGION_SETTING_PERIOD: Long = 30 * 1000L
|
||||
private const val VIDEO_RECORD_PERIOD: Long = 60 * 1000L
|
||||
|
||||
@ -35,9 +35,11 @@ object FixedRateJobHelper {
|
||||
@JvmStatic
|
||||
fun begin() {
|
||||
doOnMainProcessOnly {
|
||||
// 时间检查,每15秒检查一次
|
||||
fixedRateTimer("Global-Fixed-Rate-Timer", initialDelay = 100, period = CHECKER_PERIOD) {
|
||||
val elapsedTime = mExecuteCount * CHECKER_PERIOD
|
||||
// 时间校对,10分钟一次
|
||||
if ((mExecuteCount * CHECKER_PERIOD) % TIME_PERIOD == 0L) {
|
||||
if (elapsedTime % TIME_PERIOD == 0L) {
|
||||
RetrofitManager.getInstance().api.time
|
||||
.subscribeOn(Schedulers.io())
|
||||
.subscribe(object : Response<TimeEntity>() {
|
||||
@ -51,14 +53,14 @@ object FixedRateJobHelper {
|
||||
}
|
||||
|
||||
// 提交曝光数据
|
||||
if ((mExecuteCount * CHECKER_PERIOD) % EXPOSURE_PERIOD == 0L) {
|
||||
if (elapsedTime % EXPOSURE_PERIOD == 0L) {
|
||||
runOnUiThread {
|
||||
ExposureManager.commitSavedExposureEvents(true)
|
||||
}
|
||||
}
|
||||
|
||||
// 分片检测下载进度
|
||||
if ((mExecuteCount * CHECKER_PERIOD) % DOWNLOAD_HEARTBEAT_SHEET_PERIOD == 0L) {
|
||||
if (elapsedTime % DOWNLOAD_HEARTBEAT_SHEET_PERIOD == 0L) {
|
||||
tryCatchInRelease {
|
||||
val upload = (mExecuteCount * CHECKER_PERIOD) % DOWNLOAD_HEARTBEAT_PERIOD == 0L
|
||||
DownloadDataHelper.uploadDownloadHeartbeat(upload)
|
||||
@ -66,30 +68,29 @@ object FixedRateJobHelper {
|
||||
}
|
||||
|
||||
// 提交普通 loghub 数据
|
||||
if ((mExecuteCount * CHECKER_PERIOD) % LOGHUB_PERIOD == 0L) {
|
||||
if (elapsedTime % LOGHUB_PERIOD == 0L) {
|
||||
runOnUiThread {
|
||||
LoghubUtils.commitSavedLoghubEvents(true)
|
||||
}
|
||||
}
|
||||
|
||||
// 更新游戏屏蔽信息
|
||||
if ((mExecuteCount * CHECKER_PERIOD) % REGION_SETTING_PERIOD == 0L) {
|
||||
if (elapsedTime % REGION_SETTING_PERIOD == 0L) {
|
||||
if (HaloApp.getInstance().isRunningForeground) {
|
||||
RegionSettingHelper.getRegionSetting()
|
||||
}
|
||||
}
|
||||
|
||||
// 提交视频浏览记录数据
|
||||
if ((mExecuteCount * CHECKER_PERIOD) % VIDEO_RECORD_PERIOD == 0L) {
|
||||
if (elapsedTime % VIDEO_RECORD_PERIOD == 0L) {
|
||||
VideoRecordUtils.commitVideoRecord()
|
||||
}
|
||||
|
||||
// 获取启动广告
|
||||
if ((mExecuteCount * CHECKER_PERIOD) % STARTUP_AD == 0L) {
|
||||
// 获取启动广告 (第一次不需要获取)
|
||||
if (elapsedTime % STARTUP_AD == 0L && mExecuteCount != 0) {
|
||||
AdHelper.getSettingAdCache()
|
||||
}
|
||||
|
||||
// ExposureUtils.logADownloadCompleteExposureEvent(GameEntity(id = mExecuteCount.toString(), name = "测试曝光上传"), platform = "", trace = null, downloadType = ExposureUtils.DownloadType.DOWNLOAD)
|
||||
mExecuteCount++
|
||||
}
|
||||
}
|
||||
|
||||
@ -21,6 +21,7 @@ import com.gh.gamecenter.common.utils.DarkModeUtils;
|
||||
import com.gh.gamecenter.common.utils.EnvHelper;
|
||||
import com.gh.gamecenter.core.utils.GsonUtils;
|
||||
import com.gh.gamecenter.core.utils.SPUtils;
|
||||
import com.gh.gamecenter.core.utils.UrlFilterUtils;
|
||||
import com.gh.gamecenter.entity.GameGuidePopupEntity;
|
||||
import com.gh.gamecenter.entity.NewApiSettingsEntity;
|
||||
import com.gh.gamecenter.entity.NewSettingsEntity;
|
||||
@ -76,8 +77,6 @@ public class Config {
|
||||
|
||||
public static final String FIX_DOWNLOAD_KEY = "isFixDownload";
|
||||
public static final String FIX_PLUGIN_KEY = "isFixPlugin";
|
||||
public static final String FIX_ARTICLE_KEY = "isFixArticle";
|
||||
public static final String FIX_COMMUNITY_KEY = "isFixCommunity";
|
||||
|
||||
public static final int VIDEO_PAGE_SIZE = 21; // 视频列表大多都是一行3个
|
||||
|
||||
@ -134,6 +133,18 @@ public class Config {
|
||||
return !"off".equals(getSettings().getGameSmooth());
|
||||
}
|
||||
|
||||
/**
|
||||
* VPN 开关选项是否开启
|
||||
*/
|
||||
public static boolean isVpnOptionEnabled() {
|
||||
if (mNewApiSettingsEntity == null
|
||||
|| mNewApiSettingsEntity.getInstall() == null
|
||||
|| mNewApiSettingsEntity.getInstall().getVpnRequired() == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return mNewApiSettingsEntity.getInstall().getVpnRequired().getShouldShowVpnOption();
|
||||
}
|
||||
|
||||
public static boolean isShowPlugin(String gameId) {
|
||||
SharedPreferences preferences = getPreferences();
|
||||
@ -343,6 +354,10 @@ public class Config {
|
||||
@SuppressLint("CheckResult")
|
||||
public static void getGhzsSettings() {
|
||||
String channel = HaloApp.getInstance().getChannel();
|
||||
|
||||
// 把请求提前,避免请求过多阻塞,首页显示广告时老是用到上一次的缓存
|
||||
getNewSettings(channel);
|
||||
|
||||
RetrofitManager.getInstance()
|
||||
.getApi().getSettings(PackageUtils.getGhVersionName(), channel)
|
||||
.subscribeOn(Schedulers.io())
|
||||
@ -392,27 +407,6 @@ public class Config {
|
||||
});
|
||||
}
|
||||
|
||||
if (mNewApiSettingsEntity == null) {
|
||||
RetrofitManager.getInstance()
|
||||
.getNewApi().getNewSettings(PackageUtils.getGhVersionName(), channel)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(new BiResponse<NewApiSettingsEntity>() {
|
||||
@Override
|
||||
public void onSuccess(NewApiSettingsEntity data) {
|
||||
mNewApiSettingsEntity = data;
|
||||
mNightModeSetting = data.getNightMode();
|
||||
mNewSimulatorEntity = data.getSimulator();
|
||||
if (HaloApp.getInstance().isNewForThisVersion && mNightModeSetting != null && mNightModeSetting.getInstall()) {
|
||||
DarkModeUtils.INSTANCE.updateFollowSystemDarkModeToSp(true);
|
||||
DarkModeUtils.INSTANCE.initDarkMode();
|
||||
}
|
||||
AdHelper.prefetchStartUpAd(mNewApiSettingsEntity);
|
||||
SPUtils.setString(Constants.SP_NEW_API_SETTINGS, GsonUtils.toJson(data));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
RetrofitManager.getInstance()
|
||||
.getApi().getGameGuidePopup(Build.MANUFACTURER, Build.VERSION.RELEASE, Build.MODEL, channel, BuildConfig.VERSION_NAME)
|
||||
.subscribeOn(Schedulers.io())
|
||||
@ -444,4 +438,34 @@ public class Config {
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("CheckResult")
|
||||
private static void getNewSettings(String channel) {
|
||||
if (mNewApiSettingsEntity == null) {
|
||||
|
||||
String filterString = UrlFilterUtils.getFilterQuery(
|
||||
"manufacturer", Build.MANUFACTURER,
|
||||
"model", Build.MODEL,
|
||||
"android_sdk_version", String.valueOf(Build.VERSION.SDK_INT));
|
||||
|
||||
RetrofitManager.getInstance()
|
||||
.getNewApi().getNewSettings(PackageUtils.getGhVersionName(), channel, filterString)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(new BiResponse<NewApiSettingsEntity>() {
|
||||
@Override
|
||||
public void onSuccess(NewApiSettingsEntity data) {
|
||||
mNewApiSettingsEntity = data;
|
||||
mNightModeSetting = data.getNightMode();
|
||||
mNewSimulatorEntity = data.getSimulator();
|
||||
if (HaloApp.getInstance().isNewForThisVersion && mNightModeSetting != null && mNightModeSetting.getInstall()) {
|
||||
DarkModeUtils.INSTANCE.updateFollowSystemDarkModeToSp(true);
|
||||
DarkModeUtils.INSTANCE.initDarkMode();
|
||||
}
|
||||
AdHelper.prefetchStartUpAd(mNewApiSettingsEntity);
|
||||
SPUtils.setString(Constants.SP_NEW_API_SETTINGS, GsonUtils.toJson(data));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -31,7 +31,6 @@ import com.gh.common.chain.PackageCheckHandler;
|
||||
import com.gh.common.chain.ValidateVSpaceHandler;
|
||||
import com.gh.common.chain.VersionNumberHandler;
|
||||
import com.gh.common.constant.Config;
|
||||
import com.gh.gamecenter.feature.exposure.ExposureEvent;
|
||||
import com.gh.common.filter.RegionSetting;
|
||||
import com.gh.common.filter.RegionSettingHelper;
|
||||
import com.gh.common.history.HistoryHelper;
|
||||
@ -46,11 +45,7 @@ import com.gh.common.util.LogUtils;
|
||||
import com.gh.common.util.NewsUtils;
|
||||
import com.gh.common.util.PackageInstaller;
|
||||
import com.gh.common.util.PackageUtils;
|
||||
import com.gh.gamecenter.feature.utils.PlatformUtils;
|
||||
import com.gh.common.util.ReservationHelper;
|
||||
import com.gh.gamecenter.feature.view.DownloadButton;
|
||||
import com.gh.gamecenter.feature.view.GameIconView;
|
||||
import com.gh.gamecenter.common.view.NoEllipsizeSpaceTextView;
|
||||
import com.gh.download.DownloadManager;
|
||||
import com.gh.download.dialog.DownloadDialog;
|
||||
import com.gh.gamecenter.DownloadManagerActivity;
|
||||
@ -58,25 +53,29 @@ import com.gh.gamecenter.R;
|
||||
import com.gh.gamecenter.WebActivity;
|
||||
import com.gh.gamecenter.common.baselist.LoadStatus;
|
||||
import com.gh.gamecenter.common.callback.OnViewClickListener;
|
||||
import com.gh.gamecenter.common.entity.LinkEntity;
|
||||
import com.gh.gamecenter.common.eventbus.EBReuse;
|
||||
import com.gh.gamecenter.common.utils.DarkModeUtils;
|
||||
import com.gh.gamecenter.common.utils.ExtensionsKt;
|
||||
import com.gh.gamecenter.common.utils.ImageUtils;
|
||||
import com.gh.gamecenter.common.utils.DarkModeUtils;
|
||||
import com.gh.gamecenter.common.view.DrawableView;
|
||||
import com.gh.gamecenter.core.utils.DisplayUtils;
|
||||
import com.gh.gamecenter.core.utils.MtaHelper;
|
||||
import com.gh.gamecenter.core.utils.NumberUtils;
|
||||
import com.gh.gamecenter.databinding.KaifuDetailItemRowBinding;
|
||||
import com.gh.gamecenter.feature.entity.ApkEntity;
|
||||
import com.gh.gamecenter.feature.entity.CommunityVideoEntity;
|
||||
import com.gh.gamecenter.feature.entity.GameEntity;
|
||||
import com.gh.gamecenter.common.entity.LinkEntity;
|
||||
import com.gh.gamecenter.feature.entity.PluginLocation;
|
||||
import com.gh.gamecenter.feature.entity.ServerCalendarEntity;
|
||||
import com.gh.gamecenter.feature.entity.TagStyleEntity;
|
||||
import com.gh.gamecenter.feature.entity.TestEntity;
|
||||
import com.gh.gamecenter.common.eventbus.EBReuse;
|
||||
import com.gh.gamecenter.feature.exposure.ExposureEvent;
|
||||
import com.gh.gamecenter.feature.utils.PlatformUtils;
|
||||
import com.gh.gamecenter.feature.view.DownloadButton;
|
||||
import com.gh.gamecenter.feature.view.GameIconView;
|
||||
import com.gh.gamecenter.gamedetail.dialog.GamePermissionDialogFragment;
|
||||
import com.gh.gamecenter.manager.PackagesManager;
|
||||
import com.gh.gamecenter.feature.entity.CommunityVideoEntity;
|
||||
import com.gh.vspace.VDownloadManagerActivity;
|
||||
import com.gh.vspace.VHelper;
|
||||
import com.lightgame.download.DownloadEntity;
|
||||
@ -785,7 +784,7 @@ public class BindingAdapters {
|
||||
}
|
||||
}
|
||||
|
||||
public static void setGameName(NoEllipsizeSpaceTextView view, GameEntity game, boolean isShowPlatform, @Nullable Boolean isShowSuffix) {
|
||||
public static void setGameName(TextView view, GameEntity game, boolean isShowPlatform, @Nullable Boolean isShowSuffix) {
|
||||
if (isShowSuffix == null) isShowSuffix = true; // 默认显示
|
||||
String gameName;
|
||||
if (isShowPlatform && game.getApk().size() > 0) {
|
||||
|
||||
@ -28,6 +28,7 @@ object RegionSettingHelper {
|
||||
private const val SP_SETTING = "region_setting"
|
||||
const val SP_SETTING_FAILURE = "region_setting_failure"
|
||||
|
||||
@JvmStatic
|
||||
fun shouldThisGameDisplayMirrorInfo(gameId: String): Boolean {
|
||||
return mDisplayMirrorIfoGameIdSet?.contains(gameId) ?: false
|
||||
}
|
||||
|
||||
@ -2,17 +2,17 @@ package com.gh.common.provider
|
||||
|
||||
import android.content.Context
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.TextView
|
||||
import com.alibaba.android.arouter.facade.annotation.Route
|
||||
import com.gh.common.databind.BindingAdapters
|
||||
import com.gh.gamecenter.common.constant.RouteConsts
|
||||
import com.gh.gamecenter.common.view.NoEllipsizeSpaceTextView
|
||||
import com.gh.gamecenter.feature.entity.GameEntity
|
||||
import com.gh.gamecenter.feature.provider.IBindingAdaptersProvider
|
||||
|
||||
@Route(path = RouteConsts.provider.bindingAdapters, name = "BindingAdapters暴露服务")
|
||||
class BindingAdaptersProviderImpl : IBindingAdaptersProvider {
|
||||
override fun setGameName(
|
||||
view: NoEllipsizeSpaceTextView,
|
||||
view: TextView,
|
||||
game: GameEntity,
|
||||
isShowPlatform: Boolean,
|
||||
isShowSuffix: Boolean
|
||||
|
||||
@ -13,8 +13,10 @@ import com.gh.base.GlobalActivityManager;
|
||||
import com.gh.gamecenter.BuildConfig;
|
||||
import com.gh.gamecenter.common.base.activity.BaseActivity;
|
||||
import com.gh.gamecenter.common.constant.Constants;
|
||||
import com.gh.gamecenter.common.eventbus.EBReuse;
|
||||
import com.gh.gamecenter.common.exposure.meta.MetaUtil;
|
||||
import com.gh.gamecenter.common.retrofit.BiResponse;
|
||||
import com.gh.gamecenter.common.utils.SensorsBridge;
|
||||
import com.gh.gamecenter.core.AppExecutor;
|
||||
import com.gh.gamecenter.core.utils.GsonUtils;
|
||||
import com.gh.gamecenter.core.utils.MtaHelper;
|
||||
@ -30,6 +32,8 @@ import com.halo.assistant.HaloApp;
|
||||
import com.lightgame.config.CommonDebug;
|
||||
import com.lightgame.utils.Utils;
|
||||
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
import io.sentry.Sentry;
|
||||
import io.sentry.android.core.SentryAndroid;
|
||||
@ -114,6 +118,8 @@ public class DataUtils {
|
||||
String originalGid = HaloApp.getInstance().getGid();
|
||||
HaloApp.getInstance().setGid(gid);
|
||||
|
||||
SensorsBridge.setGid(gid);
|
||||
|
||||
// 避免重复调用
|
||||
if (!TextUtils.isEmpty(gid) && !gid.equals(originalGid)) {
|
||||
GameSubstituteRepositoryHelper.updateSubstitutableGames();
|
||||
@ -170,6 +176,8 @@ public class DataUtils {
|
||||
values.put(GhContentProvider.KEY_IS_ADULT, false);
|
||||
}
|
||||
|
||||
EventBus.getDefault().post(new EBReuse(Constants.EB_REALNAME_RESULT));
|
||||
|
||||
// new GhContentProvider().localInsert( HaloApp.getInstance().getApplication(),values);
|
||||
try {
|
||||
// Unknown URL content://com.gh.gamecenter.provider/certification
|
||||
|
||||
@ -28,6 +28,7 @@ import com.gh.gamecenter.common.constant.EntranceConsts
|
||||
import com.gh.gamecenter.common.constant.EntranceConsts.*
|
||||
import com.gh.gamecenter.common.constant.RouteConsts
|
||||
import com.gh.gamecenter.common.entity.*
|
||||
import com.gh.gamecenter.common.entity.Display
|
||||
import com.gh.gamecenter.common.retrofit.Response
|
||||
import com.gh.gamecenter.common.utils.*
|
||||
import com.gh.gamecenter.core.runOnIoThread
|
||||
@ -186,7 +187,8 @@ object DirectUtils {
|
||||
"game_list",
|
||||
"game_list_detail",
|
||||
"bbs_video",
|
||||
"explore_column"
|
||||
"explore_column",
|
||||
"column_test_v2"
|
||||
)
|
||||
|
||||
fun directToLinkPage(
|
||||
|
||||
@ -371,6 +371,14 @@ object DownloadObserver {
|
||||
type = ExposureUtils.DownloadType.PLUGIN_DOWNLOAD
|
||||
}
|
||||
|
||||
if (downloadEntity.isVGame()) {
|
||||
SensorsBridge.trackEvent(
|
||||
"HaloFunGameDownloadDone",
|
||||
"game_name", downloadEntity.name,
|
||||
"game_id", downloadEntity.gameId
|
||||
)
|
||||
}
|
||||
|
||||
var downloadSpeed = 0L
|
||||
val elapsedTimeString = downloadEntity.meta[DownloadConfig.KEY_DOWNLOAD_ELAPSED_TIME]
|
||||
if (elapsedTimeString != null) {
|
||||
@ -393,7 +401,9 @@ object DownloadObserver {
|
||||
id = downloadEntity.gameId,
|
||||
mName = downloadEntity.name.removeSuffix(Constants.GAME_NAME_DECORATOR),
|
||||
gameVersion = downloadEntity.versionName ?: "",
|
||||
isPlatformRecommend = isPlatformRecommend
|
||||
isPlatformRecommend = isPlatformRecommend,
|
||||
adIconActive = downloadEntity.meta[Constants.AD_ICON_ACTIVE].toBoolean(),
|
||||
isAdData = downloadEntity.meta[Constants.IS_AD_DATA].toBoolean()
|
||||
),
|
||||
downloadEntity.platform,
|
||||
downloadEntity.exposureTrace,
|
||||
|
||||
@ -318,6 +318,32 @@ public class LibaoUtils {
|
||||
}
|
||||
}
|
||||
|
||||
// 类型为复制的,不需要登录也可以直接复制
|
||||
if ("copy".equals(libaoEntity.getReceiveMethod())) {
|
||||
if ("finish".equals(libaoEntity.getStatus())) {
|
||||
libaoBtn.setText(R.string.libao_finish);
|
||||
libaoBtn.setBackgroundResource(R.drawable.button_border_round_gray);
|
||||
libaoBtn.setTextColor(context.getResources().getColor(R.color.button_gray));
|
||||
libaoBtn.setOnClickListener(v -> ToastUtils.toast("兑换码领取已结束"));
|
||||
} else {
|
||||
libaoBtn.setText(R.string.libao_copy);
|
||||
libaoBtn.setTextColor(ExtensionsKt.toColor(R.color.white, context));
|
||||
libaoBtn.setBackgroundResource(R.drawable.button_normal_round_style);
|
||||
libaoBtn.setOnClickListener(v -> {
|
||||
LogUtils.uploadReceiveGift(
|
||||
"game_gift_code_successful",
|
||||
libaoEntity.getId(),
|
||||
libaoEntity.getName(),
|
||||
"游戏详情",
|
||||
libaoEntity.getGame().getId(),
|
||||
libaoEntity.getGame().getName()
|
||||
);
|
||||
ExtensionsKt.copyTextAndToast(libaoEntity.getCode(), libaoEntity.getToast());
|
||||
});
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
libaoBtn.setOnClickListener(v -> {
|
||||
String btnStatus = libaoBtn.getText().toString();
|
||||
// 领取限制
|
||||
|
||||
@ -1028,7 +1028,7 @@ public class LogUtils {
|
||||
JSONObject object = new JSONObject();
|
||||
JSONObject payloadObject = new JSONObject();
|
||||
try {
|
||||
object.put(KEY_EVENT, event);//game_gift_get_successful领取礼包、game_gift_dig_successful淘号
|
||||
object.put(KEY_EVENT, event);//game_gift_get_successful领取礼包、game_gift_dig_successful淘号、game_gift_code_successful复制礼包
|
||||
payloadObject.put("gift_id", giftId);
|
||||
payloadObject.put("gift_name", giftName);
|
||||
payloadObject.put("location", location);
|
||||
|
||||
@ -808,13 +808,24 @@ object NewFlatLogUtils {
|
||||
}
|
||||
|
||||
//点击兴趣推荐卡片
|
||||
fun logDiscoverPageRecommendedInterestCardClick(sequence: Int, linkText: String, linkType: String, linkId: String) {
|
||||
fun logDiscoverPageRecommendedInterestCardClick(
|
||||
sequence: Int,
|
||||
linkText: String,
|
||||
linkType: String,
|
||||
linkId: String,
|
||||
entrance: String,
|
||||
blockName: String = ""
|
||||
) {
|
||||
val json = json {
|
||||
KEY_EVENT to "discover_page_recommended_interest_card_click"
|
||||
"sequence" to sequence
|
||||
"link_text" to linkText
|
||||
"link_type" to linkType
|
||||
"link_id" to linkId
|
||||
"entrance" to entrance
|
||||
if (blockName.isNotEmpty()) {
|
||||
"block_name" to blockName
|
||||
}
|
||||
parseAndPutMeta().invoke(this)
|
||||
}
|
||||
log(json)
|
||||
@ -1424,4 +1435,158 @@ object NewFlatLogUtils {
|
||||
}
|
||||
log(json, "event", false)
|
||||
}
|
||||
|
||||
/**
|
||||
* 新游开测首页/板块,点击右上角(全部/更多)
|
||||
*/
|
||||
fun logGameTestV2MoreClick(
|
||||
text: String,
|
||||
location: String,
|
||||
blockId: String = "",
|
||||
blockName: String = "",
|
||||
linkType: String = "",
|
||||
linkId: String = "",
|
||||
linkText: String = ""
|
||||
) {
|
||||
val json = json {
|
||||
"event" to "game_test_home_more_click"
|
||||
"text" to text //右上角文案,包括:全部、更多
|
||||
"location" to location //新游开测所处位置,包括:首页、版块
|
||||
"block_id" to blockId //新游开测所处位置为“版块”,上报版块ID
|
||||
"block_name" to blockName //新游开测所处位置为“版块”,上报版块名称
|
||||
"link_type" to linkType //右上角文案为“更多”时的链接类型
|
||||
"link_id" to linkId //右上角文案为“更多”时的链接ID
|
||||
"link_text" to linkText //右上角文案为“更多”时的跳转链接
|
||||
parseAndPutMeta().invoke(this)
|
||||
}
|
||||
log(json, "event", false)
|
||||
}
|
||||
|
||||
/**
|
||||
* 新游开测首页/板块,点击推荐标签
|
||||
*/
|
||||
fun logGameTestV2RecommendLabelClick(
|
||||
location: String,
|
||||
blockId: String = "",
|
||||
blockName: String = "",
|
||||
tagId: String = "",
|
||||
text: String = "",
|
||||
sequence: Int = 0,
|
||||
linkType: String = "",
|
||||
linkId: String = "",
|
||||
linkText: String = ""
|
||||
) {
|
||||
val json = json {
|
||||
"event" to "game_test_home_recommend_tag_click"
|
||||
"location" to location //新游开测所处位置,包括:首页、版块
|
||||
"block_id" to blockId //新游开测所处位置为“版块”,上报版块ID
|
||||
"block_name" to blockName //新游开测所处位置为“版块”,上报版块名称
|
||||
"tag_id" to tagId //点击推荐标签的ID
|
||||
"text" to text //点击推荐标签的文案
|
||||
"sequence" to sequence //点击推荐标签在所有标签中所处位置,从左往右依次计算
|
||||
"link_type" to linkType //点击推荐标签的链接类型
|
||||
"link_id" to linkId //点击推荐标签的链接ID
|
||||
"link_text" to linkText //点击推荐标签的跳转链接
|
||||
parseAndPutMeta().invoke(this)
|
||||
}
|
||||
log(json, "event", false)
|
||||
}
|
||||
|
||||
/**
|
||||
* 新游开测首页点击时间轴
|
||||
*/
|
||||
fun logGameTestV2TimeLineClick(
|
||||
action: String,
|
||||
type: String,
|
||||
time: Long,
|
||||
sequence: Int,
|
||||
){
|
||||
val json = json {
|
||||
"event" to "game_test_home_timeline_click"
|
||||
"action" to action //类型包括: 1.自动定位:滑动游戏时间轴自动更换定位 2.手动点击:手动点击时间轴的定位
|
||||
"type" to type //类型包括“推荐/全部”,时间轴定位在“推荐”时记“推荐”,其余位置则记“全部”
|
||||
"game_test_start" to time //节点时间字符串 2023-03-10 转时间戳
|
||||
"sequence" to sequence //时间类型为“全部”时,时间轴排除“推荐”,从左往右依次计算,记录在时间轴实际上所处的位置顺序,例如:12.30排在“推荐”后面,则记录“1”
|
||||
parseAndPutMeta().invoke(this)
|
||||
}
|
||||
log(json, "event", false)
|
||||
}
|
||||
|
||||
/**
|
||||
* 新游开测条目完整展示时长上报
|
||||
*/
|
||||
fun logGameTestV2ItemViewTime(
|
||||
location: String,
|
||||
blockId: String = "",
|
||||
blockName: String = "",
|
||||
interval: Long = 0,
|
||||
type: String = "",
|
||||
startTime: Long = 0,
|
||||
sequence: Int = 0,
|
||||
){
|
||||
val json = json {
|
||||
"event" to "game_test_home_view"
|
||||
"location" to location //新游开测所处位置,包括:首页、版块
|
||||
"block_id" to blockId //新游开测所处位置为“版块”,上报版块ID
|
||||
"block_name" to blockName //新游开测所处位置为“版块”,上报版块名称
|
||||
"interval" to interval //内容在屏幕可见范围完整展示的时长
|
||||
"type" to type //触发事件时所停留的时间定位;类型包括“推荐/全部”,时间轴定位在“推荐”时记“推荐”,其余位置则记“全部”
|
||||
"game_test_start" to startTime //触发事件时所停留的时间定位;时间类型为“全部”时,记录具体的月份日期 ;例如:12.30、12.31
|
||||
"sequence" to sequence //点击推荐标签在所有标签中所处位置,从左往右依次计算
|
||||
parseAndPutMeta().invoke(this)
|
||||
}
|
||||
log(json, "event", false)
|
||||
}
|
||||
|
||||
//发现页下拉刷新
|
||||
fun logDiscoverPageDropDownRefresh(refreshCount: Int) {
|
||||
val json = json {
|
||||
"event" to "discover_page_drop_down_refresh"
|
||||
"count_num" to refreshCount
|
||||
parseAndPutMeta().invoke(this)
|
||||
}
|
||||
log(json, "event", false)
|
||||
}
|
||||
|
||||
//更换头像弹窗点击
|
||||
fun logChangeAvatarDialogClick(button: String) {
|
||||
val json = json {
|
||||
"event" to "profile_picture_change_dialog_click"
|
||||
"button" to button
|
||||
parseAndPutMeta().invoke(this)
|
||||
}
|
||||
log(json, "event", false)
|
||||
}
|
||||
|
||||
//默认头像弹窗点击
|
||||
fun logDefaultAvatarDialogClick(button: String) {
|
||||
val json = json {
|
||||
"event" to "profile_picture_default_dialog_click"
|
||||
"button" to button
|
||||
parseAndPutMeta().invoke(this)
|
||||
}
|
||||
log(json, "event", false)
|
||||
}
|
||||
|
||||
fun logVpnHintDialogShow(gameId: String, gameName: String) {
|
||||
val json = json {
|
||||
KEY_EVENT to "profile_picture_default_dialog_click"
|
||||
KEY_GAME_ID to gameId
|
||||
KEY_GAME_NAME to gameName
|
||||
parseAndPutMeta().invoke(this)
|
||||
}
|
||||
log(json, "event", false)
|
||||
}
|
||||
|
||||
fun logVpnHintDialogClick(gameId: String, gameName: String, button: String) {
|
||||
val json = json {
|
||||
KEY_EVENT to "profile_picture_default_dialog_click"
|
||||
KEY_GAME_ID to gameId
|
||||
KEY_GAME_NAME to gameName
|
||||
"button" to button
|
||||
parseAndPutMeta().invoke(this)
|
||||
}
|
||||
log(json, "event", false)
|
||||
}
|
||||
|
||||
}
|
||||
@ -137,7 +137,7 @@ object NewLogUtils {
|
||||
}
|
||||
|
||||
// 游戏详情点击顶部标签
|
||||
fun logGameDetailTagClick(gameId: String, gameName: String, tagId: String, tagName: String) {
|
||||
fun logGameDetailTagClick(gameId: String, gameName: String, tagId: String, tagName: String, isTop: Boolean) {
|
||||
val json = json {
|
||||
KEY_EVENT to "game_type_tag_click_jump"
|
||||
KEY_META to LogUtils.getMetaObject()
|
||||
@ -145,6 +145,7 @@ object NewLogUtils {
|
||||
KEY_GAME_NAME to gameName
|
||||
"type_tag_id" to tagId
|
||||
"type_tag_name" to tagName
|
||||
"is_top_type_tag" to isTop
|
||||
KEY_TIMESTAMP to System.currentTimeMillis() / 1000
|
||||
}
|
||||
log(json, LOG_STORE_EVENT)
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
package com.gh.common.util
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.view.View
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.content.FileProvider
|
||||
import com.gh.common.dialog.InstallPermissionDialogFragment
|
||||
@ -13,25 +13,18 @@ import com.gh.common.xapk.XapkInstaller
|
||||
import com.gh.download.server.BrowserInstallHelper
|
||||
import com.gh.gamecenter.BuildConfig
|
||||
import com.gh.gamecenter.common.constant.Constants
|
||||
import com.gh.gamecenter.common.retrofit.BiResponse
|
||||
import com.gh.gamecenter.common.utils.DialogHelper
|
||||
import com.gh.gamecenter.common.utils.getExtension
|
||||
import com.gh.gamecenter.common.utils.getMetaExtra
|
||||
import com.gh.gamecenter.common.utils.toRequestBody
|
||||
import com.gh.gamecenter.core.utils.CurrentActivityHolder
|
||||
import com.gh.gamecenter.core.utils.MD5Utils
|
||||
import com.gh.gamecenter.core.utils.SPUtils
|
||||
import com.gh.gamecenter.core.utils.ToastUtils
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager
|
||||
import com.gh.gamecenter.vpn.VpnHelper
|
||||
import com.gh.vspace.VHelper
|
||||
import com.halo.assistant.HaloApp
|
||||
import com.lightgame.download.DownloadEntity
|
||||
import com.lightgame.download.FileUtils
|
||||
import com.lightgame.utils.Utils
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
import okhttp3.ResponseBody
|
||||
import retrofit2.HttpException
|
||||
import java.io.File
|
||||
|
||||
object PackageInstaller {
|
||||
@ -64,15 +57,17 @@ object PackageInstaller {
|
||||
return
|
||||
}
|
||||
|
||||
// TODO 此处可能遇到 activity 是 WXEntryActivity
|
||||
// TODO 当 activity 全部出栈,但是应用还在下载游戏,下载完会唤不起安装!
|
||||
// 已知问题
|
||||
// 1. 此处可能遇到 activity 是 WXEntryActivity,因为 WXEntryActivity 不是 AppCompatActivity 调不起弹窗
|
||||
// 2. 当 activity 全部出栈,但是应用还在下载游戏,下载完会唤不起安装
|
||||
if (currentActivity is AppCompatActivity && !currentActivity.isFinishing) {
|
||||
InstallPermissionDialogFragment.show(currentActivity, downloadEntity) { isFromPermissionGrantedCallback ->
|
||||
// 取消状态栏下载完成的通知,若存在
|
||||
downloadEntity.meta[Constants.MARK_ALREADY_TRIGGERED_INSTALLATION] = "YES"
|
||||
DownloadNotificationHelper.addOrUpdateDownloadNotification(downloadEntity)
|
||||
|
||||
if (isFromPermissionGrantedCallback && Build.VERSION.SDK_INT >= 31) {
|
||||
// 安卓12后的设备,需要重启应用来继续解压 XAPK 文件
|
||||
if (isFromPermissionGrantedCallback && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
||||
val pm = context.packageManager
|
||||
val intent = pm.getLaunchIntentForPackage(context.packageName)
|
||||
val mainIntent = Intent.makeRestartActivityTask(intent!!.component)
|
||||
@ -82,7 +77,7 @@ object PackageInstaller {
|
||||
if (isXapk) {
|
||||
XapkInstaller.install(context, downloadEntity, showUnzipToast)
|
||||
} else {
|
||||
install(context, downloadEntity.isPlugin, downloadEntity.path)
|
||||
install(context, downloadEntity.isPlugin, downloadEntity.path, downloadEntity)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -94,9 +89,11 @@ object PackageInstaller {
|
||||
*
|
||||
* 除非特殊情况,请勿使用此方法进行应用安装操作
|
||||
* 除非你已经确定该文件一定是Apk
|
||||
*
|
||||
* @param downloadEntity 仅用来记录日志用,非必须可为空
|
||||
*/
|
||||
@JvmStatic
|
||||
fun install(context: Context, isPluggin: Boolean = false, pkgPath: String?) {
|
||||
fun install(context: Context, isPluggin: Boolean = false, pkgPath: String?, downloadEntity: DownloadEntity? = null) {
|
||||
if (pkgPath.isNullOrEmpty()) {
|
||||
ToastUtils.toast("下载文件异常")
|
||||
return
|
||||
@ -112,20 +109,13 @@ object PackageInstaller {
|
||||
}
|
||||
|
||||
if (PackageUtils.isCanLaunchSetup(context, pkgPath)) {
|
||||
// val app = HaloApp.getInstance()
|
||||
val currentActivity = CurrentActivityHolder.getCurrentActivity()
|
||||
|
||||
HaloApp.put(Constants.LAST_INSTALL_GAME, pkgPath)
|
||||
|
||||
// val downloadEntity =
|
||||
// DownloadManager.getInstance().allDownloadEntity.firstOrNull {
|
||||
// it.path == pkgPath
|
||||
// }
|
||||
// if (downloadEntity != null) {
|
||||
// showCertificateDialogIfNeededBeforeInstall(app, downloadEntity, pkgPath)
|
||||
// } else {
|
||||
val installIntent = getInstallIntent(context, pkgPath)
|
||||
context.startActivity(installIntent)
|
||||
// }
|
||||
if (VpnHelper.shouldUseVpn() && currentActivity is AppCompatActivity) {
|
||||
turnOnVpnThenInstall(currentActivity, pkgPath, downloadEntity)
|
||||
} else {
|
||||
install(context, pkgPath)
|
||||
}
|
||||
} else {
|
||||
if (isPluggin) {
|
||||
DialogHelper.showPluginDialog(context) {
|
||||
@ -143,47 +133,13 @@ object PackageInstaller {
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("CheckResult")
|
||||
fun showCertificateDialogIfNeededBeforeInstall(context: Context, downloadEntity: DownloadEntity, pkgPath: String) {
|
||||
val isOverwrite = LunchType.UPDATE.name == SPUtils.getString(Constants.SP_INSTALL_TYPE)
|
||||
val hashMap = hashMapOf(Pair("url", downloadEntity.url), Pair("overwrite", isOverwrite))
|
||||
RetrofitManager.getInstance().api.postCertificationCheck(hashMap.toRequestBody())
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(object : BiResponse<ResponseBody>() {
|
||||
override fun onSuccess(data: ResponseBody) {
|
||||
val installIntent = getInstallIntent(context, pkgPath)
|
||||
context.startActivity(installIntent)
|
||||
}
|
||||
|
||||
override fun onFailure(exception: Exception) {
|
||||
super.onFailure(exception)
|
||||
|
||||
if (exception is HttpException) {
|
||||
val resultString =
|
||||
(exception as HttpException).response().errorBody()
|
||||
?.string()
|
||||
// 未实名
|
||||
when {
|
||||
resultString?.contains("403117") == true -> {
|
||||
RealNameHelper.showRealNameUncertificatedDialog(
|
||||
downloadEntity
|
||||
)
|
||||
}
|
||||
resultString?.contains("403118") == true -> {
|
||||
RealNameHelper.showRealNameUnqualifiedDialog(
|
||||
downloadEntity
|
||||
)
|
||||
}
|
||||
resultString?.contains("400004") == true -> {
|
||||
ToastUtils.toast("安装服务异常,缺少参数")
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ToastUtils.toast("安装服务异常,${exception.localizedMessage}请稍候再试")
|
||||
}
|
||||
}
|
||||
})
|
||||
/**
|
||||
* 最终执行安装的方法
|
||||
*/
|
||||
private fun install(context: Context, pkgPath: String) {
|
||||
HaloApp.put(Constants.LAST_INSTALL_GAME, pkgPath)
|
||||
val installIntent = getInstallIntent(context, pkgPath)
|
||||
context.startActivity(installIntent)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -271,4 +227,71 @@ object PackageInstaller {
|
||||
fun createDownloadId(gameName: String?): String {
|
||||
return MD5Utils.getContentMD5(gameName + "_" + System.currentTimeMillis())
|
||||
}
|
||||
|
||||
/**
|
||||
* 启动 VPN 然后安装应用 (若没有授权会先提醒授权 VPN ,若拒绝授权会回落到直接执行安装)
|
||||
*/
|
||||
private fun turnOnVpnThenInstall(currentActivity: AppCompatActivity,
|
||||
pkgPath: String,
|
||||
downloadEntity: DownloadEntity?) {
|
||||
if (VpnHelper.isVpnPermissionGranted(currentActivity) == true) {
|
||||
VpnHelper.startVpn(currentActivity) { shouldShowVpnError ->
|
||||
if (shouldShowVpnError) {
|
||||
ToastUtils.toast("安装防护功能启动失败")
|
||||
}
|
||||
install(currentActivity, pkgPath)
|
||||
}
|
||||
} else {
|
||||
val isTheFirstTimeToShowVpnHintDialog = VpnHelper.isTheFistTimeToShowVpnHintDialog()
|
||||
|
||||
downloadEntity?.let {
|
||||
NewFlatLogUtils.logVpnHintDialogShow(it.gameId, it.name)
|
||||
}
|
||||
|
||||
// 将 VPN 提示弹窗标记为已读(已读后的下一次显示"不再提醒"按钮)
|
||||
VpnHelper.setVpnHintDialogShowed()
|
||||
DialogHelper.showGuideDialog(
|
||||
context = currentActivity,
|
||||
title = "建议开启安装防护",
|
||||
content = "为了帮助您安装官方的光环助手游戏包,并加速安装进程,避免安装游戏时被手机厂商替换,导致重复下载浪费流量及手机存储空间,建议您开启安装防护功能,光环助手将向您申请开启VPN权限",
|
||||
confirmText = "立即授权开启防护",
|
||||
cancelText = "不再提醒",
|
||||
confirmClickCallback = {
|
||||
VpnHelper.startVpn(currentActivity) { shouldShowVpnError ->
|
||||
if (shouldShowVpnError) {
|
||||
ToastUtils.toast("安装防护功能启动失败")
|
||||
}
|
||||
install(currentActivity, pkgPath)
|
||||
}
|
||||
|
||||
downloadEntity?.let {
|
||||
NewFlatLogUtils.logVpnHintDialogClick(it.gameId, it.name, "立即授权")
|
||||
}
|
||||
},
|
||||
cancelClickCallback = {
|
||||
VpnHelper.ignoreVpnHintDialog()
|
||||
install(currentActivity, pkgPath)
|
||||
downloadEntity?.let {
|
||||
NewFlatLogUtils.logVpnHintDialogClick(it.gameId, it.name, "不再提醒")
|
||||
}
|
||||
},
|
||||
extraConfig = DialogHelper.Config(
|
||||
showCloseIcon = true,
|
||||
showAlternativeCancelStyle = !isTheFirstTimeToShowVpnHintDialog
|
||||
),
|
||||
uiModificationCallback = { binding, dialog ->
|
||||
binding.cancelTv.visibility = View.GONE
|
||||
binding.closeContainer.setOnClickListener {
|
||||
install(currentActivity, pkgPath)
|
||||
dialog.dismiss()
|
||||
|
||||
downloadEntity?.let {
|
||||
NewFlatLogUtils.logVpnHintDialogClick(it.gameId, it.name, "关闭按钮")
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -23,6 +23,7 @@ import androidx.webkit.WebViewCompat;
|
||||
import com.android.apksig.ApkVerifier;
|
||||
import com.android.apksig.internal.apk.ApkSigningBlockUtilsLite;
|
||||
import com.g00fy2.versioncompare.Version;
|
||||
import com.gh.common.filter.RegionSettingHelper;
|
||||
import com.gh.common.xapk.XapkInstaller;
|
||||
import com.gh.gamecenter.BuildConfig;
|
||||
import com.gh.gamecenter.common.constant.Constants;
|
||||
@ -139,6 +140,11 @@ public class PackageUtils {
|
||||
}
|
||||
}
|
||||
|
||||
// 镜像游戏,使用镜像 Apk 替换掉原来的 ApkNormal
|
||||
if (RegionSettingHelper.shouldThisGameDisplayMirrorInfo(gameEntity.getId())) {
|
||||
gameEntity.setApkNormal(gameEntity.getApk());
|
||||
}
|
||||
|
||||
// 非插件游戏更新
|
||||
for (ApkEntity apkEntity : gameEntity.getApkNormal()) {
|
||||
|
||||
|
||||
@ -12,10 +12,7 @@ import android.widget.LinearLayout
|
||||
import android.widget.TextView
|
||||
import androidx.core.content.ContextCompat
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.utils.DarkModeUtils
|
||||
import com.gh.gamecenter.common.utils.dip2px
|
||||
import com.gh.gamecenter.common.utils.sp2px
|
||||
import com.gh.gamecenter.common.utils.toColor
|
||||
import com.gh.gamecenter.common.utils.*
|
||||
import com.gh.gamecenter.core.utils.DisplayUtils
|
||||
import com.gh.gamecenter.feature.entity.TagStyleEntity
|
||||
import kotlin.math.ceil
|
||||
@ -41,12 +38,12 @@ class FlexLinearLayout @JvmOverloads constructor(context: Context, attrs: Attrib
|
||||
gravity = Gravity.CENTER_VERTICAL
|
||||
|
||||
val ta = context.obtainStyledAttributes(attrs, R.styleable.FlexLinearLayout)
|
||||
mItemHeight = ta.getDimensionPixelSize(R.styleable.FlexLinearLayout_itemHeight, 20f.dip2px())
|
||||
mPadding = ta.getDimensionPixelSize(R.styleable.FlexLinearLayout_itemPadding, 5f.dip2px())
|
||||
mMargin = ta.getDimensionPixelSize(R.styleable.FlexLinearLayout_itemMargin, 4f.dip2px())
|
||||
mTextSize = ta.getDimension(R.styleable.FlexLinearLayout_itemTextSize, 10f.sp2px().toFloat())
|
||||
mLastItemWidth = ta.getDimensionPixelSize(R.styleable.FlexLinearLayout_lastItemWidth, 18f.dip2px())
|
||||
mStrokeWidth = ta.getDimensionPixelSize(R.styleable.FlexLinearLayout_strokeWidth, 0.5f.dip2px())
|
||||
mItemHeight = ta.getDimensionPixelSize(R.styleable.FlexLinearLayout_itemHeight, 20F.dip2px())
|
||||
mPadding = ta.getDimensionPixelSize(R.styleable.FlexLinearLayout_itemPadding, 5F.dip2px())
|
||||
mMargin = ta.getDimensionPixelSize(R.styleable.FlexLinearLayout_itemMargin, 4F.dip2px())
|
||||
mTextSize = ta.getDimension(R.styleable.FlexLinearLayout_itemTextSize, 10F.sp2px().toFloat())
|
||||
mLastItemWidth = ta.getDimensionPixelSize(R.styleable.FlexLinearLayout_lastItemWidth, 18F.dip2px())
|
||||
mStrokeWidth = ta.getDimensionPixelSize(R.styleable.FlexLinearLayout_strokeWidth, 0.5F.dip2px())
|
||||
|
||||
ta.recycle()
|
||||
}
|
||||
@ -95,7 +92,7 @@ class FlexLinearLayout @JvmOverloads constructor(context: Context, attrs: Attrib
|
||||
layoutParams = params
|
||||
setImageDrawable(ContextCompat.getDrawable(context, R.drawable.ic_game_detail_label_more))
|
||||
if (DarkModeUtils.isDarkModeOn(context)) setColorFilter(R.color.text_title.toColor(context))
|
||||
background = createBackgroundDrawable()
|
||||
background = createNormalBackgroundDrawable()
|
||||
scaleType = ImageView.ScaleType.CENTER
|
||||
}
|
||||
imageView.setOnClickListener {
|
||||
@ -111,27 +108,33 @@ class FlexLinearLayout @JvmOverloads constructor(context: Context, attrs: Attrib
|
||||
includeFontPadding = false
|
||||
textSize = DisplayUtils.px2sp(context, mTextSize).toFloat()
|
||||
gravity = Gravity.CENTER
|
||||
setTextColor(R.color.text_title.toColor(context))
|
||||
|
||||
val params = LayoutParams(LayoutParams.WRAP_CONTENT, mItemHeight)
|
||||
params.setMargins(0, 0, mMargin, 0)
|
||||
setPadding(mPadding, 0, mPadding, 0)
|
||||
layoutParams = params
|
||||
|
||||
val gradientDrawable = createBackgroundDrawable()
|
||||
background = gradientDrawable
|
||||
setTextColor(if (tag.isTop) "#${tag.color}".hexStringToIntColor() else R.color.text_title.toColor(context))
|
||||
background = if (tag.isTop) createTopBackgroundDrawable(tag) else createNormalBackgroundDrawable()
|
||||
setOnClickListener {
|
||||
onClickListener?.onItemClickListener(tag)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun createBackgroundDrawable(): GradientDrawable {
|
||||
private fun createNormalBackgroundDrawable(): GradientDrawable {
|
||||
val gradientDrawable = GradientDrawable()
|
||||
val isDarkModeOn = DarkModeUtils.isDarkModeOn(context)
|
||||
gradientDrawable.setColor(Color.TRANSPARENT)
|
||||
gradientDrawable.setStroke(mStrokeWidth, Color.parseColor(if (isDarkModeOn) "#33FFFFFF" else "#CCCCCC"))
|
||||
gradientDrawable.cornerRadius = DisplayUtils.dip2px(2f).toFloat()
|
||||
gradientDrawable.cornerRadius = 2F.dip2px().toFloat()
|
||||
return gradientDrawable
|
||||
}
|
||||
|
||||
private fun createTopBackgroundDrawable(tag: TagStyleEntity): GradientDrawable {
|
||||
val gradientDrawable = GradientDrawable()
|
||||
gradientDrawable.setColor("#${tag.background}".hexStringToIntColor())
|
||||
gradientDrawable.cornerRadius = 2F.dip2px().toFloat()
|
||||
return gradientDrawable
|
||||
}
|
||||
|
||||
|
||||
@ -22,6 +22,7 @@ import com.gh.gamecenter.common.utils.DialogHelper;
|
||||
import com.gh.gamecenter.common.utils.EnvHelper;
|
||||
import com.gh.gamecenter.common.utils.ExtensionsKt;
|
||||
import com.gh.gamecenter.common.utils.ImageUtils;
|
||||
import com.gh.gamecenter.common.utils.NetworkUtils;
|
||||
import com.gh.gamecenter.core.utils.DisplayUtils;
|
||||
import com.gh.gamecenter.core.utils.EmptyCallback;
|
||||
import com.gh.gamecenter.core.utils.GsonUtils;
|
||||
@ -139,6 +140,7 @@ public class RichEditor extends WebView {
|
||||
setVerticalScrollBarEnabled(false);
|
||||
setHorizontalScrollBarEnabled(false);
|
||||
getSettings().setJavaScriptEnabled(true);
|
||||
getSettings().setDomStorageEnabled(true);
|
||||
setWebChromeClient(new WebChromeClient()); // 不要重写这个方法否则无法加载
|
||||
setWebViewClient(createWebViewClient());
|
||||
|
||||
@ -573,6 +575,13 @@ public class RichEditor extends WebView {
|
||||
exec("javascript:RE.formatBlock();");
|
||||
}
|
||||
|
||||
/**
|
||||
* 调用 JS 方法,告诉网页端该 url 对应视频播放的进度
|
||||
*/
|
||||
public void onVideoPlayedCallback(String url, int position) {
|
||||
exec("javascript:RE.onVideoPlayedCallback('" + url + "', '" + position + "')");
|
||||
}
|
||||
|
||||
public String getText() {
|
||||
return HtmlUtils.stripHtml(mContents);
|
||||
}
|
||||
@ -586,7 +595,7 @@ public class RichEditor extends WebView {
|
||||
return String.format("#%06X", (0xFFFFFF & color));
|
||||
}
|
||||
|
||||
protected void exec(final String trigger) {
|
||||
public void exec(final String trigger) {
|
||||
if (isReady) {
|
||||
load(trigger);
|
||||
} else {
|
||||
@ -708,7 +717,9 @@ public class RichEditor extends WebView {
|
||||
|
||||
@JavascriptInterface
|
||||
public void onPageFinished() {
|
||||
mPageFinishedListener.onPageFinished();
|
||||
if (mPageFinishedListener != null) {
|
||||
mPageFinishedListener.onPageFinished();
|
||||
}
|
||||
}
|
||||
|
||||
@JavascriptInterface
|
||||
@ -721,6 +732,16 @@ public class RichEditor extends WebView {
|
||||
return PackageUtils.getGhVersionCode();
|
||||
}
|
||||
|
||||
@JavascriptInterface
|
||||
public boolean isNetworkConnected() {
|
||||
return NetworkUtils.isNetworkConnected(HaloApp.getInstance());
|
||||
}
|
||||
|
||||
@JavascriptInterface
|
||||
public boolean isWifiConnected() {
|
||||
return NetworkUtils.isWifiConnected(HaloApp.getInstance());
|
||||
}
|
||||
|
||||
/**
|
||||
* 显示toast
|
||||
*
|
||||
|
||||
@ -152,7 +152,7 @@ object XapkInstaller : IXapkUnzipListener {
|
||||
return@execute
|
||||
}
|
||||
|
||||
PackageInstaller.install(mContext, downloadEntity.isPlugin, pkgPath)
|
||||
PackageInstaller.install(mContext, downloadEntity.isPlugin, pkgPath, downloadEntity)
|
||||
|
||||
downloadEntity.meta[XAPK_UNZIP_PERCENT] = "100.0"
|
||||
downloadEntity.meta[XAPK_UNZIP_STATUS] = XapkUnzipStatus.SUCCESS.name
|
||||
|
||||
@ -16,6 +16,7 @@ import androidx.lifecycle.LiveData;
|
||||
import androidx.lifecycle.MutableLiveData;
|
||||
|
||||
import com.gh.gamecenter.common.utils.ExtensionsKt;
|
||||
import com.gh.gamecenter.common.utils.SensorsBridge;
|
||||
import com.gh.gamecenter.core.AppExecutor;
|
||||
import com.gh.gamecenter.common.constant.Constants;
|
||||
import com.gh.gamecenter.feature.exposure.ExposureEvent;
|
||||
@ -326,6 +327,8 @@ public class DownloadManager implements DownloadStatusListener {
|
||||
ExtensionsKt.addMetaExtra(downloadEntity, Constants.GAME_ICON_SUBSCRIPT, gameEntity.getIconSubscript());
|
||||
ExtensionsKt.addMetaExtra(downloadEntity, Constants.IS_PLATFORM_RECOMMEND, apkEntity.getRecommend() != null ? "true" : "false");
|
||||
ExtensionsKt.addMetaExtra(downloadEntity, Constants.GAME_NAME, gameEntity.getName());
|
||||
ExtensionsKt.addMetaExtra(downloadEntity, Constants.AD_ICON_ACTIVE, String.valueOf(gameEntity.getAdIconActive()));
|
||||
ExtensionsKt.addMetaExtra(downloadEntity, Constants.IS_AD_DATA, String.valueOf(gameEntity.isAdData()));
|
||||
if (gameEntity.getIconFloat() != null) {
|
||||
ExtensionsKt.addMetaExtra(downloadEntity, Constants.GAME_ICON_FLOAT_TOP_TEXT, gameEntity.getIconFloat().getUpperLeftText());
|
||||
ExtensionsKt.addMetaExtra(downloadEntity, Constants.GAME_ICON_FLOAT_TOP_COLOR, gameEntity.getIconFloat().getUpperLeftColor());
|
||||
@ -340,6 +343,10 @@ public class DownloadManager implements DownloadStatusListener {
|
||||
ExtensionsKt.addMetaExtra(downloadEntity, Constants.SMOOTH_GAME, "true");
|
||||
ExtensionsKt.addMetaExtra(downloadEntity, Constants.EXTRA_DOWNLOAD_TYPE, Constants.SMOOTH_GAME);
|
||||
ExtensionsKt.addMetaExtra(downloadEntity, DownloadConfig.KEY_PROGRESS_CALLBACK_INTERVAL, "200");
|
||||
|
||||
SensorsBridge.trackEvent("HaloFunGameDownloadClick",
|
||||
"game_name", gameEntity.getName(),
|
||||
"game_id", gameEntity.getId());
|
||||
}
|
||||
|
||||
HashMap<String, String> map = PageSwitchDataHelper.popLastPageData();
|
||||
@ -1270,7 +1277,8 @@ public class DownloadManager implements DownloadStatusListener {
|
||||
*/
|
||||
public static void updateDownloadMetaMap() {
|
||||
String isOverwrite;
|
||||
if (LunchType.UPDATE.name().equals(SPUtils.getString(Constants.SP_INSTALL_TYPE))) {
|
||||
String installType = SPUtils.getString(Constants.SP_INSTALL_TYPE);
|
||||
if (LunchType.UPDATE.name().equals(installType)) {
|
||||
isOverwrite = "true";
|
||||
} else {
|
||||
isOverwrite = "false";
|
||||
@ -1285,6 +1293,7 @@ public class DownloadManager implements DownloadStatusListener {
|
||||
map.put(HttpDnsManager.IMEI, MetaUtil.getBase64EncodedIMEI());
|
||||
map.put(HttpDnsManager.TOKEN, UserManager.getInstance().getToken());
|
||||
map.put(HttpDnsManager.IS_OVERWRITE, isOverwrite);
|
||||
map.put(HttpDnsManager.INSTALL_TYPE, installType);
|
||||
|
||||
HttpDnsManager.metaMap = map;
|
||||
}
|
||||
|
||||
@ -83,7 +83,7 @@ class DownloadDialogAdapter(
|
||||
holder.binding.root.layoutParams = this
|
||||
}
|
||||
val section = listData[position].section
|
||||
holder.binding.title.text = if (section == DownloadDialogSectionType.OTHER) "其它版本" else "我的版本"
|
||||
holder.binding.title.text = if (section == DownloadDialogSectionType.OTHER) "更多版本" else "我的版本"
|
||||
holder.binding.otherVersionHint.goneIf(section != DownloadDialogSectionType.OTHER)
|
||||
}
|
||||
is DownloadDialogLinkItemViewHolder -> {
|
||||
|
||||
@ -38,21 +38,21 @@ import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView
|
||||
import com.facebook.drawee.backends.pipeline.Fresco
|
||||
import com.facebook.imagepipeline.core.ImagePipeline
|
||||
import com.facebook.imagepipeline.request.ImageRequest
|
||||
import com.gh.gamecenter.common.base.activity.BaseActivity
|
||||
import com.gh.common.constant.Config
|
||||
import com.gh.gamecenter.core.runOnIoThread
|
||||
import com.gh.gamecenter.common.base.activity.BaseActivity
|
||||
import com.gh.gamecenter.common.constant.EntranceConsts
|
||||
import com.gh.gamecenter.common.entity.CommunityEntity
|
||||
import com.gh.gamecenter.common.retrofit.Response
|
||||
import com.gh.gamecenter.common.utils.*
|
||||
import com.gh.gamecenter.common.utils.ImageUtils.getTransformedUrl
|
||||
import com.gh.gamecenter.common.view.DraggableBigImageView
|
||||
import com.gh.gamecenter.common.view.Gh_RelativeLayout
|
||||
import com.gh.gamecenter.common.utils.*
|
||||
import com.gh.gamecenter.core.runOnIoThread
|
||||
import com.gh.gamecenter.core.utils.*
|
||||
import com.gh.gamecenter.databinding.ActivityViewimageBinding
|
||||
import com.gh.gamecenter.common.entity.CommunityEntity
|
||||
import com.gh.gamecenter.entity.ImageInfoEntity
|
||||
import com.gh.gamecenter.qa.article.detail.ArticleDetailActivity
|
||||
import com.gh.gamecenter.feature.entity.AnswerEntity
|
||||
import com.gh.gamecenter.common.retrofit.Response
|
||||
import com.gh.gamecenter.qa.article.detail.ArticleDetailActivity
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager
|
||||
import com.github.piasy.biv.view.BigImageView
|
||||
import com.github.piasy.biv.view.FrescoImageViewFactory
|
||||
@ -849,9 +849,9 @@ class ImageViewerActivity : BaseActivity(), OnPageChangeListener {
|
||||
// ssiv.resetScaleAndCenter()
|
||||
// }
|
||||
// })
|
||||
ssiv.setOnClickListener {
|
||||
onBackPressed()
|
||||
}
|
||||
}
|
||||
imageView.setOnClickListener {
|
||||
onBackPressed()
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@ -36,10 +36,10 @@ import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.content.res.AppCompatResources;
|
||||
import androidx.constraintlayout.widget.ConstraintLayout;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.lifecycle.ViewModelProviders;
|
||||
import androidx.vectordrawable.graphics.drawable.VectorDrawableCompat;
|
||||
|
||||
import com.facebook.drawee.view.SimpleDraweeView;
|
||||
import com.gh.common.DefaultUrlHandler;
|
||||
@ -307,15 +307,15 @@ public class MainActivity extends BaseActivity {
|
||||
checkDialog();
|
||||
}
|
||||
|
||||
// 默认配置为空时重试
|
||||
if (Config.getSettings() == null) {
|
||||
Config.getGhzsSettings();
|
||||
}
|
||||
|
||||
// 耗时操作
|
||||
AppExecutor.getIoExecutor().execute(() -> {
|
||||
// 上传数据
|
||||
DataCollectionManager.getInstance().upload();
|
||||
// 获取默认配置
|
||||
|
||||
if (Config.getSettings() == null) {
|
||||
Config.getGhzsSettings();
|
||||
}
|
||||
|
||||
// 初始化PlatformUtils
|
||||
PlatformUtils.getInstance(getApplicationContext());
|
||||
@ -507,7 +507,27 @@ public class MainActivity extends BaseActivity {
|
||||
|
||||
private void observeStartUpAd() {
|
||||
final StartupAdEntity startUpAd = AdHelper.getStartUpAd();
|
||||
|
||||
if (startUpAd != null && !TextUtils.isEmpty(startUpAd.getImg())) {
|
||||
// 根据接口返回的广告时间,判断该图片广告是否还有必要显示
|
||||
boolean isAdValid = false;
|
||||
if (startUpAd.getTime() != null) {
|
||||
long currentTimeInSecond = System.currentTimeMillis() / 1000;
|
||||
if (currentTimeInSecond > startUpAd.getTime().getStart()
|
||||
&& currentTimeInSecond < startUpAd.getTime().getEnd()) {
|
||||
isAdValid = true;
|
||||
}
|
||||
} else {
|
||||
// 接口没有返回开始和结束时间时,默认有效
|
||||
isAdValid = true;
|
||||
}
|
||||
|
||||
// 图片广告无效,跳过
|
||||
if (!isAdValid) {
|
||||
hideStartUpAd();
|
||||
return;
|
||||
}
|
||||
|
||||
final String showedTodayTimestamp = SPUtils.getString(Constants.SP_STARTUP_AD_TIMESTAMP, "");
|
||||
final String rule = startUpAd.getRule();
|
||||
switch (rule) {
|
||||
@ -594,7 +614,7 @@ public class MainActivity extends BaseActivity {
|
||||
SimpleDraweeView adImage = findViewById(R.id.adImage);
|
||||
startAdContainer.setVisibility(View.VISIBLE);
|
||||
jumpDetailBtn.setText(ad.getDesc());
|
||||
ExtensionsKt.setDrawableEnd(jumpDetailBtn, VectorDrawableCompat.create(getResources(), R.drawable.ic_startup_ad_arrow, null), null, null);
|
||||
ExtensionsKt.setDrawableEnd(jumpDetailBtn, AppCompatResources.getDrawable(this, R.drawable.ic_startup_ad_arrow), null, null);
|
||||
ImageUtils.display(adImage, ad.getImg());
|
||||
startAdContainer.setOnClickListener(v -> {
|
||||
// do nothing 只是为了点击拦截事件,避免传递到下面的页面
|
||||
@ -987,7 +1007,7 @@ public class MainActivity extends BaseActivity {
|
||||
public void onEventMainThread(EBNetworkState busNetworkState) {
|
||||
if (busNetworkState.isNetworkConnected()) {
|
||||
if (Config.getSettings() == null) {
|
||||
AppExecutor.getIoExecutor().execute(Config::getGhzsSettings);
|
||||
Config.getGhzsSettings();
|
||||
}
|
||||
|
||||
mPackageViewModel.checkData();
|
||||
|
||||
@ -35,6 +35,7 @@ import com.gh.gamecenter.core.runOnIoThread
|
||||
import com.gh.gamecenter.core.utils.*
|
||||
import com.gh.gamecenter.entity.PrivacyPolicyEntity
|
||||
import com.gh.gamecenter.feature.utils.PlatformUtils
|
||||
import com.gh.gamecenter.pkg.PkgHelper
|
||||
import com.gh.vspace.VHelper
|
||||
import com.halo.assistant.HaloApp
|
||||
import com.lightgame.download.FileUtils
|
||||
@ -273,6 +274,8 @@ class SplashScreenActivity : BaseActivity() {
|
||||
|
||||
private fun doFlavorInit() {
|
||||
HaloApp.getInstance().flavorProvider.init(HaloApp.getInstance(), this)
|
||||
|
||||
SensorsBridge.init(HaloApp.getInstance(), HaloApp.getInstance().channel)
|
||||
}
|
||||
|
||||
private fun getGitLogString(): String {
|
||||
@ -347,7 +350,6 @@ class SplashScreenActivity : BaseActivity() {
|
||||
|
||||
private fun prefetchData() {
|
||||
runOnIoThread {
|
||||
Config.getGhzsSettings()
|
||||
mViewModel?.deviceDialogSetting()
|
||||
mViewModel?.filterDetailTags()
|
||||
mViewModel?.authDialog()
|
||||
@ -356,6 +358,10 @@ class SplashScreenActivity : BaseActivity() {
|
||||
checkAndPostUsageStats()
|
||||
updateGameSubstituteRepository()
|
||||
|
||||
if (BuildConfig.CONFIG_ID.isNotEmpty()) {
|
||||
PkgHelper.requestPkgConfig(BuildConfig.CONFIG_ID)
|
||||
}
|
||||
|
||||
// 获取自动刷新的cd,获取版本对应表
|
||||
val time = mSharedPreferences!!.getString("refresh_time", null)
|
||||
val format = SimpleDateFormat("yyyy-MM-dd", Locale.getDefault())
|
||||
@ -438,7 +444,7 @@ class SplashScreenActivity : BaseActivity() {
|
||||
if (position == mPics.size - 1) {
|
||||
val tvSkip = view.findViewById<TextView>(R.id.splsh_guide_tv_skip)
|
||||
// 如果屏幕特短,或者是平板的横屏显示,把图片改成按高度显示
|
||||
if (DisplayUtils.isUltraShortScreen()) {
|
||||
if (DisplayUtils.isUltraShortScreen(this@SplashScreenActivity)) {
|
||||
ivImage.scaleType = ImageView.ScaleType.CENTER_INSIDE
|
||||
}
|
||||
tvSkip.setOnClickListener {
|
||||
|
||||
@ -202,7 +202,7 @@ public class LibaoDetailAdapter extends BaseRecyclerAdapter<ViewHolder> {
|
||||
if (mLibaoEntity.getGame() != null) {
|
||||
holder.binding.libaodetailGameIcon.displayGameIcon(mLibaoEntity.getGame().getIcon(), mLibaoEntity.getGame().getIconSubscript(), mLibaoEntity.getGame().getIconFloat());
|
||||
GameEntity gameEntity = mLibaoEntity.getGame().toGameEntity();
|
||||
GameItemViewHolder.initGameSubtitle(gameEntity, holder.binding.gameSubtitleTv, null, null, false, null);
|
||||
GameItemViewHolder.initGameSubtitleAndAdLabel(gameEntity, holder.binding.gameSubtitleTv, null, null, false, null, false, null);
|
||||
} else {
|
||||
holder.binding.libaodetailGameIcon.displayGameIcon(mLibaoEntity.getIcon(), null, mLibaoEntity.getGame().getIconFloat());
|
||||
}
|
||||
|
||||
@ -12,7 +12,6 @@ import com.facebook.drawee.view.SimpleDraweeView;
|
||||
import com.gh.gamecenter.R;
|
||||
import com.gh.gamecenter.common.utils.ExtensionsKt;
|
||||
import com.gh.gamecenter.common.view.DrawableView;
|
||||
import com.gh.gamecenter.common.view.NoEllipsizeSpaceTextView;
|
||||
import com.gh.gamecenter.feature.databinding.GameItemBinding;
|
||||
import com.gh.gamecenter.feature.entity.ColorEntity;
|
||||
import com.gh.gamecenter.feature.entity.GameEntity;
|
||||
@ -22,7 +21,7 @@ import com.gh.gamecenter.feature.view.GameIconView;
|
||||
public class GameViewHolder extends RecyclerView.ViewHolder {
|
||||
|
||||
public GameIconView gameThumb;
|
||||
public NoEllipsizeSpaceTextView gameName;
|
||||
public TextView gameName;
|
||||
public DownloadButton gameDownloadBtn;
|
||||
public TextView gameDes;
|
||||
public LinearLayout gameLabelList;
|
||||
|
||||
@ -27,8 +27,8 @@ import com.gh.gamecenter.databinding.AmwayCommentItemBinding
|
||||
import com.gh.gamecenter.eventbus.EBDownloadStatus
|
||||
import com.gh.gamecenter.feature.exposure.ExposureEvent
|
||||
import com.gh.gamecenter.feature.exposure.ExposureSource
|
||||
import com.gh.gamecenter.game.GameAndPosition
|
||||
import com.gh.gamecenter.feature.game.GameItemViewHolder
|
||||
import com.gh.gamecenter.game.GameAndPosition
|
||||
import com.gh.gamecenter.game.vertical.GameVerticalAdapter
|
||||
import com.gh.gamecenter.gamedetail.rating.RatingFragment
|
||||
import com.gh.gamecenter.gamedetail.rating.RatingReplyActivity
|
||||
@ -240,7 +240,7 @@ class AmwayAdapter(
|
||||
}
|
||||
|
||||
itemData.exposureEvent = ExposureEvent.createEvent(gameEntity, basicExposureSource)
|
||||
GameItemViewHolder.initGameSubtitle(gameEntity, binding.gameSubtitleTv)
|
||||
GameItemViewHolder.initGameSubtitleAndAdLabel(gameEntity, binding.gameSubtitleTv)
|
||||
|
||||
binding.gameContainer.setOnClickListener {
|
||||
GameDetailActivity.startGameDetailActivity(
|
||||
|
||||
@ -2,8 +2,8 @@ package com.gh.gamecenter.amway.search
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import androidx.appcompat.content.res.AppCompatResources
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.vectordrawable.graphics.drawable.VectorDrawableCompat
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.utils.*
|
||||
import com.gh.gamecenter.databinding.FragmentAmwaySearchDefaultBinding
|
||||
@ -65,11 +65,12 @@ class AmwaySearchDefaultFragment : SearchDefaultFragment() {
|
||||
headTitle.textSize = 16F
|
||||
headActionTv.text = "清空"
|
||||
headActionTv.setTextColor(R.color.text_subtitleDesc.toColor(requireContext()))
|
||||
headActionTv.setDrawableStart(VectorDrawableCompat.create(
|
||||
resources,
|
||||
R.drawable.search_history_delete,
|
||||
null
|
||||
))
|
||||
headActionTv.setDrawableStart(
|
||||
AppCompatResources.getDrawable(
|
||||
requireContext(),
|
||||
R.drawable.search_history_delete
|
||||
)
|
||||
)
|
||||
headActionTv.setOnClickListener {
|
||||
DialogHelper.showCenterWarningDialog(requireContext(), "清空记录", "确定清空历史搜索记录?", confirmClickCallback = {
|
||||
mSearchDao.deleteAll()
|
||||
|
||||
@ -221,7 +221,6 @@ class CategoryV2ListAdapter(
|
||||
|
||||
inner class CategoryGameItemViewHolder(val binding: CategoryGameItemBinding) :
|
||||
BaseRecyclerViewHolder<Any>(binding.root) {
|
||||
|
||||
fun bindGameItem(gameEntity: GameEntity) {
|
||||
binding.run {
|
||||
gameIconView.displayGameIcon(gameEntity)
|
||||
@ -240,7 +239,7 @@ class CategoryV2ListAdapter(
|
||||
)
|
||||
gameDes.text = gameEntity.decoratedDes
|
||||
|
||||
GameItemViewHolder.initGameSubtitle(gameEntity, gameSubtitleTv, gameDesSpace, root)
|
||||
GameItemViewHolder.initGameSubtitleAndAdLabel(gameEntity, gameSubtitleTv)
|
||||
}
|
||||
}
|
||||
|
||||
@ -279,6 +278,8 @@ class CategoryV2ListAdapter(
|
||||
recommendContainer = binding.recommendContainer
|
||||
recommendTv = binding.recommendTv
|
||||
recommendIv = binding.recommendIv
|
||||
multiVersionDownloadTv = binding.multiVersionDownloadTv
|
||||
gameDownloadTips = binding.downloadTipsLottie
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -7,9 +7,6 @@ import android.view.ViewGroup
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.gh.common.constant.Config
|
||||
import com.gh.common.databind.BindingAdapters
|
||||
import com.gh.gamecenter.feature.exposure.ExposureEvent
|
||||
import com.gh.gamecenter.feature.exposure.ExposureSource
|
||||
import com.gh.gamecenter.feature.exposure.ExposureType
|
||||
import com.gh.common.exposure.IExposable
|
||||
import com.gh.common.util.DirectUtils
|
||||
import com.gh.common.util.DownloadItemUtils
|
||||
@ -34,12 +31,15 @@ import com.gh.gamecenter.databinding.ItemRecommendInterestImageBinding
|
||||
import com.gh.gamecenter.discovery.DiscoveryFragment.Companion.INTERESTED_GAME_REQUEST_CODE
|
||||
import com.gh.gamecenter.discovery.interestedgame.InterestedGameActivity
|
||||
import com.gh.gamecenter.entity.DiscoveryGameCardLabel
|
||||
import com.gh.gamecenter.feature.entity.GameEntity
|
||||
import com.gh.gamecenter.eventbus.EBDownloadStatus
|
||||
import com.gh.gamecenter.eventbus.EBSkip
|
||||
import com.gh.gamecenter.feature.entity.GameEntity
|
||||
import com.gh.gamecenter.feature.exposure.ExposureEvent
|
||||
import com.gh.gamecenter.feature.exposure.ExposureSource
|
||||
import com.gh.gamecenter.feature.exposure.ExposureType
|
||||
import com.gh.gamecenter.feature.game.GameItemViewHolder
|
||||
import com.gh.gamecenter.fragment.MainWrapperFragment
|
||||
import com.gh.gamecenter.fragment.MainWrapperRepository
|
||||
import com.gh.gamecenter.feature.game.GameItemViewHolder
|
||||
import com.lightgame.download.DownloadEntity
|
||||
import org.greenrobot.eventbus.EventBus
|
||||
|
||||
@ -248,7 +248,8 @@ class DiscoveryAdapter(
|
||||
position,
|
||||
label.text ?: "",
|
||||
label.type ?: "",
|
||||
label.link ?: ""
|
||||
label.link ?: "",
|
||||
"发现详情页"
|
||||
)
|
||||
}
|
||||
|
||||
@ -315,8 +316,6 @@ class DiscoveryAdapter(
|
||||
gameKaifuType.setBackgroundColor(R.color.theme.toColor(root.context))
|
||||
gameName.setTextColor(R.color.text_title.toColor(root.context))
|
||||
gameDes.setTextColor(R.color.text_subtitleDesc.toColor(root.context))
|
||||
downloadSpeed.setTextColor(R.color.text_subtitleDesc.toColor(root.context))
|
||||
downloadPercentage.setTextColor(R.color.theme_font.toColor(root.context))
|
||||
|
||||
gameIconView.displayGameIcon(gameEntity)
|
||||
BindingAdapters.setGameName(gameName, gameEntity, false, null)
|
||||
@ -338,8 +337,6 @@ class DiscoveryAdapter(
|
||||
gameDes.visibleIf(gameEntity.recommendTag.isNotEmpty()) {
|
||||
gameDes.text = "根据 “${gameEntity.recommendTag}” 兴趣推荐"
|
||||
}
|
||||
//type: recommend 专题游戏 | ad 广告游戏 | filter 算法游戏
|
||||
adLabelTv.goneIf(!(gameEntity.type == "ad" && gameEntity.adIconActive))
|
||||
if (gameEntity.type == "ad" && gameEntity.adIconActive) {
|
||||
recommendReasonTv.visibility = View.GONE
|
||||
} else {
|
||||
@ -360,11 +357,15 @@ class DiscoveryAdapter(
|
||||
recommendReasonTv.visibility = View.VISIBLE
|
||||
}
|
||||
}
|
||||
GameItemViewHolder.initGameSubtitle(gameEntity, gameSubtitleTv) {
|
||||
gameDesSpace.post {
|
||||
gameSubtitleTv.maxWidthExcludeZero(if (gameEntity.type == "ad" && gameEntity.adIconActive) gameDesSpace.width - 25F.dip2px() else gameDesSpace.width)
|
||||
}
|
||||
}
|
||||
//type: recommend 专题游戏 | ad 广告游戏 | filter 算法游戏
|
||||
GameItemViewHolder.initGameSubtitleAndAdLabel(
|
||||
gameEntity,
|
||||
gameSubtitleTv,
|
||||
gameNameContainer,
|
||||
gameName,
|
||||
gameEntity.type == "ad" && gameEntity.adIconActive,
|
||||
adLabelTv
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -57,6 +57,9 @@ class DiscoveryFragment : LazyListFragment<DiscoveryItemData, DiscoveryViewModel
|
||||
private var mPageBottomVisibleCount = 0
|
||||
private lateinit var mExposureListener: ExposureListener
|
||||
|
||||
//下拉刷新次数
|
||||
private var mRefreshCount = 0
|
||||
|
||||
private val dataWatcher = object : DataWatcher() {
|
||||
override fun onDataChanged(downloadEntity: DownloadEntity) {
|
||||
mAdapter?.notifyItemByDownload(downloadEntity)
|
||||
@ -75,6 +78,11 @@ class DiscoveryFragment : LazyListFragment<DiscoveryItemData, DiscoveryViewModel
|
||||
mCachedView.setBackgroundColor(R.color.background_white.toColor(requireContext()))
|
||||
}
|
||||
|
||||
override fun onRefresh() {
|
||||
super.onRefresh()
|
||||
NewFlatLogUtils.logDiscoverPageDropDownRefresh(++mRefreshCount)
|
||||
}
|
||||
|
||||
override fun initSkeletonScreen() {
|
||||
if (mSkeletonScreenView == null) return
|
||||
mSkeletonScreen = Skeleton.bind(mSkeletonScreenView)
|
||||
|
||||
13
app/src/main/java/com/gh/gamecenter/entity/DefaultAvatar.kt
Normal file
13
app/src/main/java/com/gh/gamecenter/entity/DefaultAvatar.kt
Normal file
@ -0,0 +1,13 @@
|
||||
package com.gh.gamecenter.entity
|
||||
|
||||
import android.os.Parcelable
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import kotlinx.parcelize.Parcelize
|
||||
|
||||
@Parcelize
|
||||
data class DefaultAvatar(
|
||||
@SerializedName("_id")
|
||||
val id: String = "",
|
||||
val url: String = "",
|
||||
val order: String = ""
|
||||
) : Parcelable
|
||||
@ -1,11 +1,13 @@
|
||||
package com.gh.gamecenter.entity
|
||||
|
||||
import android.os.Parcelable
|
||||
import com.gh.gamecenter.common.entity.LinkEntity
|
||||
import com.gh.gamecenter.feature.entity.MeEntity
|
||||
import com.gh.gamecenter.feature.entity.SimpleGame
|
||||
import com.gh.gamecenter.feature.entity.UserEntity
|
||||
import com.gh.gamecenter.feature.entity.ZoneEntity
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import kotlinx.parcelize.Parcelize
|
||||
|
||||
class ForumDetailEntity(
|
||||
@SerializedName("_id")
|
||||
@ -21,7 +23,11 @@ class ForumDetailEntity(
|
||||
var zone: ZoneEntity? = null,
|
||||
var me: MeEntity = MeEntity(),
|
||||
var type: String = "", //game_bbs/official_bbs
|
||||
var hot: Int = 0 // 热度值
|
||||
var hot: Int = 0, // 热度值
|
||||
@SerializedName("hot_rank")
|
||||
var hotRank: Int = 0, // 热度排名
|
||||
@SerializedName("background_layer_color")
|
||||
var backgroundLayerColor: String = "" // 背景图色值
|
||||
) {
|
||||
|
||||
class TopLinkEntity(
|
||||
@ -41,6 +47,13 @@ class ForumDetailEntity(
|
||||
var fontColor: String = ""
|
||||
)
|
||||
|
||||
@Parcelize
|
||||
class Section(
|
||||
@SerializedName("_id")
|
||||
var id: String = "",
|
||||
var name: String = ""
|
||||
) : Parcelable
|
||||
|
||||
fun convertForumDetailEntityToForumEntity(): ForumEntity {
|
||||
val forumEntity = ForumEntity()
|
||||
forumEntity.id = id
|
||||
|
||||
@ -24,6 +24,8 @@ data class HomeContent(
|
||||
val recommendText: String = "",
|
||||
@SerializedName("common_collection")
|
||||
val commonCollection: CommonCollectionEntity? = null,
|
||||
@SerializedName("column_test_v2_data")
|
||||
val testV2Data: HomeItemTestV2Entity? = null,
|
||||
val image: String = "",
|
||||
@SerializedName("first_line_recommend")
|
||||
val firstLineRecommend: String = "",
|
||||
|
||||
@ -0,0 +1,91 @@
|
||||
package com.gh.gamecenter.entity
|
||||
|
||||
import android.os.Parcelable
|
||||
import androidx.annotation.Keep
|
||||
import androidx.room.Entity
|
||||
import com.gh.gamecenter.common.entity.LinkEntity
|
||||
import com.gh.gamecenter.feature.entity.GameEntity
|
||||
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import kotlinx.parcelize.Parcelize
|
||||
|
||||
|
||||
/**
|
||||
* @author : liujiarui
|
||||
* date : 2023/3/3
|
||||
* description : 首页-推荐tab-新游开测 item 实体类
|
||||
*/
|
||||
@Keep
|
||||
@Entity
|
||||
@Parcelize
|
||||
data class HomeItemTestV2Entity(
|
||||
@SerializedName("action")
|
||||
val action: String = "",
|
||||
@SerializedName("count")
|
||||
val count: Int = 0,
|
||||
@SerializedName("limit")
|
||||
val limit: Int = 0,
|
||||
@SerializedName("page_id")
|
||||
val pageId: String = "",
|
||||
@SerializedName("recommend_label")
|
||||
val recommendLabel: List<RecommendLabel> = listOf(),
|
||||
@SerializedName("right_top")
|
||||
val rightTop: RightTop = RightTop(),
|
||||
@SerializedName("start_id")
|
||||
val startId: String = "",
|
||||
@SerializedName("start_point")
|
||||
val startPoint: Map<String, String> = mapOf(), // key 时间轴名称,value 当前时间轴第一个游戏id
|
||||
@SerializedName("data_count")
|
||||
val dataCount: Map<String, Int> = mapOf(), //key 时间轴名称,value 当前时间轴所包含的游戏数量
|
||||
@SerializedName("time_type")
|
||||
val timeType: String = "",
|
||||
// 首屏游戏列表
|
||||
val data: List<GameData> = emptyList()
|
||||
) : Parcelable
|
||||
|
||||
@Keep
|
||||
@Entity
|
||||
@Parcelize
|
||||
data class RecommendLabel(
|
||||
@SerializedName("_id")
|
||||
val id: String = "",
|
||||
@SerializedName("link")
|
||||
val link: LinkEntity = LinkEntity(),
|
||||
@SerializedName("text")
|
||||
val text: String = ""
|
||||
) : Parcelable
|
||||
|
||||
@Keep
|
||||
@Entity
|
||||
@Parcelize
|
||||
data class RightTop(
|
||||
@SerializedName("link")
|
||||
val link: LinkEntity = LinkEntity(),
|
||||
@SerializedName("text")
|
||||
val text: String = ""
|
||||
) : Parcelable
|
||||
|
||||
|
||||
@Keep
|
||||
@Entity
|
||||
@Parcelize
|
||||
data class GameData(
|
||||
@SerializedName("start_midnight")
|
||||
val startMidnight: Long = 0L,
|
||||
@SerializedName("time_type")
|
||||
val timeType: String = "",//时间轴(recommend:推荐、xxxx-xx-xx:全部(比如:2023-01-01))
|
||||
var games: List<GameEntity> = emptyList()
|
||||
) : Parcelable
|
||||
|
||||
/**
|
||||
* 新游开测游戏列表包装类
|
||||
*/
|
||||
@Keep
|
||||
data class GameDataWrapper(
|
||||
var index: Int,
|
||||
val pageId: String = "",
|
||||
val timeType: String = "",
|
||||
val gameData: GameEntity? = null,
|
||||
var isPlaceHolder: Boolean = false, //占位标识
|
||||
var isSpace: Boolean = false, //空条目标识
|
||||
)
|
||||
@ -42,7 +42,10 @@ data class LibaoEntity(
|
||||
@SerializedName("activity_link")
|
||||
var activityLink: ActivityLink = ActivityLink(), //关联活动链接数据
|
||||
@SerializedName("app_and_plugin_hide")
|
||||
var appAndPluginHide: Boolean = false, //app和插件内不显示
|
||||
var appAndPluginHide: Boolean = false, // app和插件内不显示
|
||||
@SerializedName("receive_method")
|
||||
var receiveMethod: String = "", // 当值为 copy 时,仅领取不能进入详情
|
||||
var toast: String = "", // 点击游戏详情页的领取按钮时的 toast 内容
|
||||
|
||||
//本地字段
|
||||
var clickReceiveBtnIn: Boolean = false//是否是点击列表领取按钮进入
|
||||
|
||||
@ -11,7 +11,8 @@ class NewApiSettingsEntity(
|
||||
var startAd: StartupAdEntity? = null,//开屏图片广告
|
||||
var startup: StartupAdEntity? = null,//启动文案广告
|
||||
@SerializedName("user_interested_game")
|
||||
var userInterestedGame: Boolean = false //偏好设置状态开关
|
||||
var userInterestedGame: Boolean = false, //偏好设置状态开关
|
||||
var install: Install, // 安装相关的
|
||||
) {
|
||||
/**
|
||||
*
|
||||
@ -24,4 +25,17 @@ class NewApiSettingsEntity(
|
||||
val setting: Boolean,
|
||||
val install: Boolean
|
||||
)
|
||||
|
||||
// VPN 配置
|
||||
class Install(
|
||||
@SerializedName("vpn_required")
|
||||
val vpnRequired: VpnSetting? = null
|
||||
)
|
||||
|
||||
class VpnSetting(
|
||||
@SerializedName("current_device")
|
||||
val shouldShowVpnOption: Boolean,
|
||||
@SerializedName("packages")
|
||||
val vpnMatchedPackagesName: HashSet<String>
|
||||
)
|
||||
}
|
||||
@ -11,5 +11,8 @@ class StartupAdEntity(
|
||||
val jump: LinkEntity,
|
||||
val img: String = "",
|
||||
// 显示规则: none无, each每一次打开, everyday每一天一次, once一次
|
||||
val rule: String = ""
|
||||
)
|
||||
val rule: String = "",
|
||||
val time: TimeEntity? = null
|
||||
) {
|
||||
class TimeEntity(val start: Long = 0, val end: Long = 0)
|
||||
}
|
||||
@ -43,6 +43,9 @@ data class SubjectEntity(
|
||||
@SerializedName("game_list_collection")
|
||||
var gameListCollection: List<GamesCollectionEntity>? = null,
|
||||
|
||||
@SerializedName("column_test_v2_data")
|
||||
val testV2Data: HomeItemTestV2Entity? = null,
|
||||
|
||||
@SerializedName("show_name")
|
||||
var showName: Boolean = true, // 是否显示“专题名字”,true、false
|
||||
@SerializedName("show_suffix")
|
||||
|
||||
@ -17,6 +17,10 @@ import com.gh.gamecenter.common.baselist.ListAdapter
|
||||
import com.gh.gamecenter.common.utils.goneIf
|
||||
import com.gh.gamecenter.databinding.CommunityAnswerItemBinding
|
||||
import com.gh.gamecenter.common.entity.CommunityEntity
|
||||
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.databinding.ItemForumArticleHeadBinding
|
||||
import com.gh.gamecenter.forum.home.ForumArticleAskItemViewHolder
|
||||
import com.gh.gamecenter.qa.article.detail.ArticleDetailActivity
|
||||
import com.gh.gamecenter.feature.entity.AnswerEntity
|
||||
@ -24,15 +28,29 @@ import com.gh.gamecenter.feature.entity.Questions
|
||||
import com.gh.gamecenter.qa.questions.newdetail.NewQuestionDetailActivity
|
||||
import com.gh.gamecenter.qa.video.detail.ForumVideoDetailActivity
|
||||
|
||||
class ForumArticleAskListAdapter(context: Context, val bbsId: String, val mEntrance: String, val path: String) :
|
||||
class ForumArticleAskListAdapter(
|
||||
context: Context,
|
||||
val bbsId: String,
|
||||
val entrance: String,
|
||||
val path: String,
|
||||
val viewModel: ForumArticleAskListViewModel,
|
||||
val onCheckCallback: (String) -> Unit
|
||||
) :
|
||||
ListAdapter<AnswerEntity>(context), ISyncAdapterHandler {
|
||||
|
||||
private var mDefOrderList = listOf("回复", "发布")
|
||||
private var mVideoOrderList = listOf("推荐", "发布")
|
||||
private var mFilterPosition = 0
|
||||
|
||||
override fun areItemsTheSame(oldItem: AnswerEntity?, newItem: AnswerEntity?): Boolean {
|
||||
return oldItem?.id == newItem?.id
|
||||
}
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
|
||||
return when (viewType) {
|
||||
ItemViewType.ITEM_HEADER -> {
|
||||
ForumArticleHeadViewHolder(parent.toBinding())
|
||||
}
|
||||
ItemViewType.ITEM_FOOTER -> {
|
||||
FooterViewHolder(mLayoutInflater.inflate(R.layout.refresh_footerview, parent, false))
|
||||
}
|
||||
@ -51,6 +69,7 @@ class ForumArticleAskListAdapter(context: Context, val bbsId: String, val mEntra
|
||||
}
|
||||
|
||||
override fun getItemViewType(position: Int): Int {
|
||||
if (position == 0) return ItemViewType.ITEM_HEADER
|
||||
if (position == itemCount - 1) return ItemViewType.ITEM_FOOTER
|
||||
return ItemViewType.ITEM_BODY
|
||||
}
|
||||
@ -62,6 +81,7 @@ class ForumArticleAskListAdapter(context: Context, val bbsId: String, val mEntra
|
||||
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
|
||||
when (getItemViewType(position)) {
|
||||
ItemViewType.ITEM_BODY -> {
|
||||
val articlePosition = position - 1
|
||||
val answer = mEntityList[position]
|
||||
if (answer.type != "answer") {
|
||||
val questions = Questions()
|
||||
@ -80,7 +100,7 @@ class ForumArticleAskListAdapter(context: Context, val bbsId: String, val mEntra
|
||||
val answerViewHolder = holder as ForumArticleAskItemViewHolder
|
||||
val binding = answerViewHolder.binding
|
||||
binding.forumNameLl.visibility = View.GONE
|
||||
binding.topLine.goneIf(position == 0)
|
||||
binding.topLine.goneIf(articlePosition == 0)
|
||||
|
||||
val params = binding.includeVoteAndComment.root.layoutParams as LinearLayout.LayoutParams
|
||||
params.width = LinearLayout.LayoutParams.MATCH_PARENT
|
||||
@ -89,12 +109,12 @@ class ForumArticleAskListAdapter(context: Context, val bbsId: String, val mEntra
|
||||
binding.includeVoteAndComment.root.layoutParams = params
|
||||
|
||||
val tabInfo = "${path}tab"
|
||||
answerViewHolder.bindForumAnswerItem(answer, mEntrance, path, position)
|
||||
answerViewHolder.bindForumAnswerItem(answer, entrance, path, articlePosition)
|
||||
answerViewHolder.itemView.setOnClickListener {
|
||||
val entrance = BaseActivity.mergeEntranceAndPath(mEntrance, path)
|
||||
val entrance = BaseActivity.mergeEntranceAndPath(entrance, path)
|
||||
val userId = answer.user.id ?: ""
|
||||
val contentId = answer.id ?: ""
|
||||
val sequence = position + 1
|
||||
val sequence = articlePosition + 1
|
||||
val bbsType = if (answer.bbs.type == "official_bbs") "综合论坛" else "游戏论坛"
|
||||
when (answer.type) {
|
||||
"community_article" -> {
|
||||
@ -118,7 +138,7 @@ class ForumArticleAskListAdapter(context: Context, val bbsId: String, val mEntra
|
||||
mContext,
|
||||
CommunityEntity(bbsId),
|
||||
answer.id!!,
|
||||
mEntrance,
|
||||
entrance,
|
||||
path
|
||||
)
|
||||
)
|
||||
@ -160,7 +180,7 @@ class ForumArticleAskListAdapter(context: Context, val bbsId: String, val mEntra
|
||||
mContext.startActivity(
|
||||
NewQuestionDetailActivity.getIntent(
|
||||
mContext, answer.id
|
||||
?: "", mEntrance, path
|
||||
?: "", entrance, path
|
||||
)
|
||||
)
|
||||
}
|
||||
@ -183,7 +203,7 @@ class ForumArticleAskListAdapter(context: Context, val bbsId: String, val mEntra
|
||||
mContext.startActivity(
|
||||
NewQuestionDetailActivity.getCommentIntent(
|
||||
mContext, answer.questions.id, answer.id
|
||||
?: "", mEntrance, path
|
||||
?: "", entrance, path
|
||||
)
|
||||
)
|
||||
}
|
||||
@ -197,6 +217,31 @@ class ForumArticleAskListAdapter(context: Context, val bbsId: String, val mEntra
|
||||
footerViewHolder.hint.textSize = 12f
|
||||
footerViewHolder.hint.setTextColor(ContextCompat.getColor(mContext, R.color.aaaaaa))
|
||||
}
|
||||
ItemViewType.ITEM_HEADER -> {
|
||||
if (holder is ForumArticleHeadViewHolder) {
|
||||
val articleListHead = if (path == "全部") {
|
||||
viewModel.selectedSection.name
|
||||
} else path
|
||||
holder.binding.root.setBackgroundColor(R.color.background_white.toColor(mContext))
|
||||
holder.binding.articleListHeadTv.setTextColor(R.color.text_title.toColor(mContext))
|
||||
holder.binding.articleListHeadTv.text = "${articleListHead}列表"
|
||||
|
||||
holder.binding.orderSfv.run {
|
||||
setContainerBackground(R.drawable.button_round_f5f5f5.toDrawable(mContext))
|
||||
setIndicatorBackground(R.drawable.bg_game_collection_sfv_indicator.toDrawable(mContext))
|
||||
setTextColor(
|
||||
R.color.text_subtitle.toColor(mContext),
|
||||
R.color.text_subtitleDesc.toColor(mContext)
|
||||
)
|
||||
|
||||
setItemList(if (path == "视频") mVideoOrderList else mDefOrderList, mFilterPosition)
|
||||
setOnCheckedCallback { position ->
|
||||
mFilterPosition = position
|
||||
onCheckCallback.invoke((if (path == "视频") mVideoOrderList else mDefOrderList)[position])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -205,4 +250,6 @@ class ForumArticleAskListAdapter(context: Context, val bbsId: String, val mEntra
|
||||
val entity = mEntityList[position]
|
||||
return Pair(entity.id ?: "", entity)
|
||||
}
|
||||
|
||||
class ForumArticleHeadViewHolder(val binding: ItemForumArticleHeadBinding) : RecyclerView.ViewHolder(binding.root)
|
||||
}
|
||||
@ -18,6 +18,7 @@ import com.gh.gamecenter.core.AppExecutor
|
||||
import com.gh.gamecenter.core.iinterface.IScrollable
|
||||
import com.gh.gamecenter.core.utils.MD5Utils
|
||||
import com.gh.gamecenter.databinding.FragmentListBaseSkeletonBinding
|
||||
import com.gh.gamecenter.entity.ForumDetailEntity
|
||||
import com.gh.gamecenter.eventbus.EBDeleteDetail
|
||||
import com.gh.gamecenter.eventbus.EBTypeChange
|
||||
import com.gh.gamecenter.eventbus.EBUserFollow
|
||||
@ -39,6 +40,9 @@ class ForumArticleAskListFragment : LazyListFragment<AnswerEntity, ForumArticleA
|
||||
private var bbsId: String = ""
|
||||
private var mListReachTop = true
|
||||
|
||||
var filter = "回复"
|
||||
var videoFilter = "推荐"
|
||||
|
||||
override fun getRealLayoutId(): Int = R.layout.fragment_list_base_skeleton
|
||||
|
||||
override fun onRealLayoutInflated(inflatedView: View) {
|
||||
@ -47,8 +51,10 @@ class ForumArticleAskListFragment : LazyListFragment<AnswerEntity, ForumArticleA
|
||||
}
|
||||
|
||||
override fun provideListViewModel(): ForumArticleAskListViewModel {
|
||||
val factory = ForumArticleAskListViewModel.Factory(bbsId, mPath)
|
||||
mViewModel = viewModelProvider(factory)
|
||||
if (mViewModel == null) {
|
||||
val factory = ForumArticleAskListViewModel.Factory(bbsId, mPath)
|
||||
mViewModel = viewModelProvider(factory)
|
||||
}
|
||||
return mViewModel!!
|
||||
}
|
||||
|
||||
@ -56,8 +62,11 @@ class ForumArticleAskListFragment : LazyListFragment<AnswerEntity, ForumArticleA
|
||||
requireContext(),
|
||||
bbsId,
|
||||
mEntrance,
|
||||
mPath
|
||||
).apply { mAdapter = this }
|
||||
mPath,
|
||||
mViewModel!!
|
||||
) {
|
||||
onRefresh(it)
|
||||
}.apply { mAdapter = this }
|
||||
|
||||
override fun getItemDecoration() = null
|
||||
|
||||
@ -167,9 +176,11 @@ class ForumArticleAskListFragment : LazyListFragment<AnswerEntity, ForumArticleA
|
||||
|
||||
fun onRefresh(filter: String) {
|
||||
if (mPath == "全部" || mPath == "问答") {
|
||||
this.filter = filter
|
||||
mViewModel?.sort = if (filter == "发布") "time.create" else "time.reply"
|
||||
}
|
||||
if (mPath == "视频") {
|
||||
videoFilter = filter
|
||||
mViewModel?.videoSort = if (filter == "推荐") "recommend" else "time.upload"
|
||||
}
|
||||
onRefresh()
|
||||
@ -308,6 +319,11 @@ class ForumArticleAskListFragment : LazyListFragment<AnswerEntity, ForumArticleA
|
||||
}
|
||||
}
|
||||
|
||||
fun setSection(section: ForumDetailEntity.Section) {
|
||||
mViewModel?.selectedSection = section
|
||||
onRefresh()
|
||||
}
|
||||
|
||||
override fun onDarkModeChanged() {
|
||||
super.onDarkModeChanged()
|
||||
mAdapter?.run { notifyItemRangeChanged(0, itemCount) }
|
||||
|
||||
@ -8,6 +8,7 @@ import com.gh.gamecenter.common.constant.EntranceConsts
|
||||
import com.gh.gamecenter.core.utils.PageSwitchDataHelper
|
||||
import com.gh.gamecenter.core.utils.SPUtils
|
||||
import com.gh.gamecenter.core.utils.UrlFilterUtils
|
||||
import com.gh.gamecenter.entity.ForumDetailEntity
|
||||
import com.gh.gamecenter.feature.entity.ForumVideoEntity
|
||||
import com.gh.gamecenter.feature.entity.AnswerEntity
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager
|
||||
@ -18,6 +19,8 @@ class ForumArticleAskListViewModel(application: Application, val bbsId: String =
|
||||
ListViewModel<AnswerEntity, AnswerEntity>(application) {
|
||||
|
||||
var sort: String = "time.reply"
|
||||
var filter: String = "section_id"
|
||||
var selectedSection = ForumDetailEntity.Section("", "全部")
|
||||
var videoSort: String = "recommend"
|
||||
var videoList = arrayListOf<ForumVideoEntity>()
|
||||
|
||||
@ -27,6 +30,10 @@ class ForumArticleAskListViewModel(application: Application, val bbsId: String =
|
||||
val data = PageSwitchDataHelper.popLastPageData()
|
||||
val map = hashMapOf<String, Any?>()
|
||||
|
||||
if (selectedSection.id.isNotEmpty()) {
|
||||
map["filter"] = UrlFilterUtils.getFilterQuery(filter, selectedSection.id)
|
||||
}
|
||||
|
||||
if (data != null && data.containsKey(EntranceConsts.KEY_TOP_ID)) {
|
||||
map["top_id"] = data[EntranceConsts.KEY_TOP_ID]
|
||||
}
|
||||
@ -79,7 +86,7 @@ class ForumArticleAskListViewModel(application: Application, val bbsId: String =
|
||||
it.transformForumVideoEntity()
|
||||
})
|
||||
|
||||
mResultLiveData.postValue(list)
|
||||
mResultLiveData.postValue(ArrayList(list).apply { add(0, AnswerEntity().apply { id = "" }) })
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -52,6 +52,15 @@ class ForumDetailActivity : BaseActivity() {
|
||||
intent.putExtra(EntranceConsts.KEY_ENTRANCE, entrance)
|
||||
return intent
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun getTrendsIntent(context: Context, bbsId: String, entrance: String): Intent {
|
||||
val intent = Intent(context, ForumDetailActivity::class.java)
|
||||
intent.putExtra(EntranceConsts.KEY_BBS_ID, bbsId)
|
||||
intent.putExtra(EntranceConsts.KEY_SCROLL_TO_TRENDS, true)
|
||||
intent.putExtra(EntranceConsts.KEY_ENTRANCE, entrance)
|
||||
return intent
|
||||
}
|
||||
}
|
||||
|
||||
override fun handleBackPressed(): Boolean {
|
||||
|
||||
@ -4,7 +4,9 @@ import android.animation.ValueAnimator
|
||||
import android.app.Activity
|
||||
import android.content.Intent
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.Color
|
||||
import android.graphics.drawable.ColorDrawable
|
||||
import android.graphics.drawable.GradientDrawable
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.view.Gravity
|
||||
@ -12,14 +14,22 @@ 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 androidx.annotation.RequiresApi
|
||||
import androidx.appcompat.content.res.AppCompatResources
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.graphics.ColorUtils
|
||||
import androidx.core.os.bundleOf
|
||||
import androidx.core.view.ViewCompat
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.lifecycle.Observer
|
||||
import androidx.recyclerview.widget.DefaultItemAnimator
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import androidx.viewpager.widget.PagerAdapter
|
||||
import com.ethanhua.skeleton.Skeleton
|
||||
import com.ethanhua.skeleton.ViewSkeletonScreen
|
||||
import com.facebook.drawee.drawable.ScalingUtils
|
||||
@ -32,6 +42,7 @@ import com.gh.gamecenter.GameDetailActivity
|
||||
import com.gh.gamecenter.NewsDetailActivity
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.base.TrackableDialog
|
||||
import com.gh.gamecenter.common.base.adapter.FragmentStateAdapter
|
||||
import com.gh.gamecenter.common.base.fragment.BaseFragment_TabLayout
|
||||
import com.gh.gamecenter.common.base.fragment.BaseLazyTabFragment
|
||||
import com.gh.gamecenter.common.callback.BiCallback
|
||||
@ -40,11 +51,11 @@ import com.gh.gamecenter.common.constant.EntranceConsts
|
||||
import com.gh.gamecenter.common.entity.CommunityEntity
|
||||
import com.gh.gamecenter.common.mvvm.Status
|
||||
import com.gh.gamecenter.common.utils.*
|
||||
import com.gh.gamecenter.common.view.SegmentedFilterView
|
||||
import com.gh.gamecenter.core.iinterface.IScrollable
|
||||
import com.gh.gamecenter.core.runOnUiThread
|
||||
import com.gh.gamecenter.core.utils.*
|
||||
import com.gh.gamecenter.databinding.FragmentForumDetailBinding
|
||||
import com.gh.gamecenter.databinding.PopupForumDetailSectionsBinding
|
||||
import com.gh.gamecenter.entity.*
|
||||
import com.gh.gamecenter.eventbus.EBForumFollowChange
|
||||
import com.gh.gamecenter.eventbus.EBTypeChange
|
||||
@ -52,15 +63,17 @@ import com.gh.gamecenter.forum.home.CommunityHomeFragment
|
||||
import com.gh.gamecenter.forum.moderator.ApplyModeratorActivity
|
||||
import com.gh.gamecenter.forum.moderator.ModeratorListActivity
|
||||
import com.gh.gamecenter.forum.search.ForumOrUserSearchActivity
|
||||
import com.gh.gamecenter.gamedetail.GameDetailFragment
|
||||
import com.gh.gamecenter.login.user.UserManager
|
||||
import com.gh.gamecenter.qa.article.edit.ArticleEditActivity
|
||||
import com.gh.gamecenter.feature.entity.AnswerEntity
|
||||
import com.gh.gamecenter.feature.entity.ForumVideoEntity
|
||||
import com.gh.gamecenter.feature.entity.GameEntity
|
||||
import com.gh.gamecenter.feature.entity.UserEntity
|
||||
import com.gh.gamecenter.gamedetail.fuli.FuLiFragment
|
||||
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.halo.assistant.fragment.WebFragment
|
||||
import org.greenrobot.eventbus.EventBus
|
||||
import org.greenrobot.eventbus.Subscribe
|
||||
import org.greenrobot.eventbus.ThreadMode
|
||||
@ -70,24 +83,27 @@ class ForumDetailFragment : BaseLazyTabFragment(), IScrollable {
|
||||
|
||||
private var mAllForumArticleAskListFragment: ForumArticleAskListFragment? = null
|
||||
private var mEssenceForumArticleAskListFragment: ForumArticleAskListFragment? = null
|
||||
private var mTrendsFragment: Fragment? = null
|
||||
private var mAskForumArticleAskListFragment: ForumArticleAskListFragment? = null
|
||||
private var mVideoForumArticleAskListFragment: ForumArticleAskListFragment? = null
|
||||
private var mBbsId: String = ""
|
||||
private var mBbsType: String = ""
|
||||
private var mViewModel: ForumDetailViewModel? = null
|
||||
private var mForumDetail: ForumDetailEntity? = null
|
||||
private var mForumSectionAdapter: ForumSectionAdapter? = null
|
||||
private var mPopupWindow: PopupWindow? = null
|
||||
private lateinit var mBinding: FragmentForumDetailBinding
|
||||
private lateinit var mSkeleton: ViewSkeletonScreen
|
||||
|
||||
private var mFilter = "回复"
|
||||
private var mVideoFilter = "推荐"
|
||||
private var mLastPosition = 0
|
||||
private var mAppbarReachTop = true
|
||||
private var mDefOrderList = listOf("回复", "发布")
|
||||
private var mVideoOrderList = listOf("推荐", "发布")
|
||||
private var mIsExpand = false
|
||||
private var mStatus: ApplyModeratorStatusEntity = ApplyModeratorStatusEntity()
|
||||
private var mIsToolbarWhite = false
|
||||
private var mShowSections = false
|
||||
|
||||
private var mAskIndex = INDEX_ASK
|
||||
private var mVideoIndex = INDEX_VIDEO
|
||||
|
||||
override fun initFragmentList(fragments: MutableList<Fragment>) {
|
||||
mAllForumArticleAskListFragment = ForumArticleAskListFragment().with(
|
||||
@ -128,6 +144,9 @@ class ForumDetailFragment : BaseLazyTabFragment(), IScrollable {
|
||||
"精华" -> {
|
||||
mEssenceForumArticleAskListFragment = fragment as ForumArticleAskListFragment
|
||||
}
|
||||
"专区" -> {
|
||||
mTrendsFragment = fragment
|
||||
}
|
||||
"问答" -> {
|
||||
mAskForumArticleAskListFragment = fragment as ForumArticleAskListFragment
|
||||
}
|
||||
@ -144,6 +163,10 @@ class ForumDetailFragment : BaseLazyTabFragment(), IScrollable {
|
||||
tabTitleList.add(TAB_TITLE_VIDEO)
|
||||
}
|
||||
|
||||
override fun providePagerAdapter(): PagerAdapter {
|
||||
return FragmentStateAdapter(childFragmentManager, mFragmentsList, mTabTitleList)
|
||||
}
|
||||
|
||||
override fun getInflatedLayout(): View {
|
||||
mBinding = FragmentForumDetailBinding.bind(layoutInflater.inflate(R.layout.fragment_forum_detail, null, false))
|
||||
return mBinding.root
|
||||
@ -202,12 +225,17 @@ class ForumDetailFragment : BaseLazyTabFragment(), IScrollable {
|
||||
mAppbarReachTop = abs(verticalOffset) <= 2
|
||||
if (mViewPager.currentItem < mFragmentsList.size) {
|
||||
mFragmentsList.safelyGetInRelease(mViewPager.currentItem)?.run {
|
||||
mBinding.refreshLayout.isEnabled = mAppbarReachTop
|
||||
&& (this as ForumArticleAskListFragment).isListReachTop()
|
||||
if (this is ForumArticleAskListFragment) {
|
||||
mBinding.refreshLayout.isEnabled = mAppbarReachTop && isListReachTop()
|
||||
} else {
|
||||
mBinding.refreshLayout.isEnabled = false
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
initSection()
|
||||
|
||||
mSkeleton = Skeleton.bind(mBinding.skeletonContainer)
|
||||
.shimmer(true)
|
||||
.angle(Constants.SHIMMER_ANGLE)
|
||||
@ -269,25 +297,35 @@ class ForumDetailFragment : BaseLazyTabFragment(), IScrollable {
|
||||
})
|
||||
mViewPager.doOnPageSelected {
|
||||
mBinding.run {
|
||||
allOrderSfv.goneIf(it != INDEX_ALL)
|
||||
askOrderSfv.goneIf(it != INDEX_ASK)
|
||||
videoOrderSfv.goneIf(it != INDEX_VIDEO)
|
||||
sectionContainer.goneIf(it != INDEX_ALL || !mShowSections)
|
||||
}
|
||||
MtaHelper.onEvent("论坛详情", getKeyValue(mLastPosition), getKeyValue(it))
|
||||
mLastPosition = it
|
||||
if (it < mFragmentsList.size) {
|
||||
(mFragmentsList.safelyGetInRelease(it) as ForumArticleAskListFragment).refreshScrollHelper()
|
||||
val fragment = mFragmentsList.safelyGetInRelease(it)
|
||||
if (fragment is ForumArticleAskListFragment) {
|
||||
fragment.refreshScrollHelper()
|
||||
mBinding.refreshLayout.isEnabled = mAppbarReachTop && fragment.isListReachTop()
|
||||
} else {
|
||||
mBinding.refreshLayout.isEnabled = false
|
||||
}
|
||||
}
|
||||
when (it) {
|
||||
INDEX_ALL -> NewLogUtils.logForumDetailEnterOrClick("click_all_tab", mBbsId, mBbsType, "", mFilter)
|
||||
INDEX_ALL -> NewLogUtils.logForumDetailEnterOrClick(
|
||||
"click_all_tab",
|
||||
mBbsId,
|
||||
mBbsType,
|
||||
"",
|
||||
mAllForumArticleAskListFragment?.filter ?: "回复"
|
||||
)
|
||||
INDEX_ESSENCE -> NewLogUtils.logForumDetailEnterOrClick("click_essence_tab", mBbsId, mBbsType)
|
||||
INDEX_ASK -> NewLogUtils.logForumDetailEnterOrClick("click_question_tab", mBbsId, mBbsType)
|
||||
INDEX_VIDEO -> NewLogUtils.logForumDetailEnterOrClick(
|
||||
mAskIndex -> NewLogUtils.logForumDetailEnterOrClick("click_question_tab", mBbsId, mBbsType)
|
||||
mVideoIndex -> NewLogUtils.logForumDetailEnterOrClick(
|
||||
"click_video_tab",
|
||||
mBbsId,
|
||||
mBbsType,
|
||||
"",
|
||||
mVideoFilter
|
||||
mVideoForumArticleAskListFragment?.videoFilter ?: "推荐"
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -298,16 +336,42 @@ class ForumDetailFragment : BaseLazyTabFragment(), IScrollable {
|
||||
if (mEssenceForumArticleAskListFragment != null && mViewPager.currentItem == INDEX_ESSENCE) {
|
||||
mEssenceForumArticleAskListFragment?.refresh()
|
||||
}
|
||||
if (mAskForumArticleAskListFragment != null && mViewPager.currentItem == INDEX_ASK) {
|
||||
if (mAskForumArticleAskListFragment != null && mViewPager.currentItem == mAskIndex) {
|
||||
mAskForumArticleAskListFragment?.refresh()
|
||||
}
|
||||
if (mVideoForumArticleAskListFragment != null && mViewPager.currentItem == INDEX_VIDEO) {
|
||||
if (mVideoForumArticleAskListFragment != null && mViewPager.currentItem == mVideoIndex) {
|
||||
mVideoForumArticleAskListFragment?.refresh()
|
||||
}
|
||||
}
|
||||
LogUtils.uploadAccessToBbs(mBbsId, "论坛详情")
|
||||
}
|
||||
|
||||
private fun initSection() {
|
||||
mForumSectionAdapter = ForumSectionAdapter(requireContext(), mViewModel!!) {
|
||||
mAllForumArticleAskListFragment?.setSection(
|
||||
mViewModel?.selectedSection ?: ForumDetailEntity.Section(
|
||||
"",
|
||||
"全部"
|
||||
)
|
||||
)
|
||||
}
|
||||
mBinding.sectionRv.run {
|
||||
layoutManager = LinearLayoutManager(requireContext(), RecyclerView.HORIZONTAL, false)
|
||||
adapter = mForumSectionAdapter
|
||||
(itemAnimator as DefaultItemAnimator).supportsChangeAnimations = false
|
||||
}
|
||||
mViewModel?.sectionListLiveData?.observe(this) {
|
||||
if (!it.isNullOrEmpty() && it.size >= 2) {
|
||||
mShowSections = true
|
||||
mBinding.sectionContainer.visibility = View.VISIBLE
|
||||
mForumSectionAdapter?.submitList(it)
|
||||
} else {
|
||||
mShowSections = false
|
||||
mBinding.sectionContainer.visibility = View.GONE
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun hideRefreshingLayout() {
|
||||
mBinding.refreshLayout.isRefreshing = false
|
||||
}
|
||||
@ -320,8 +384,9 @@ class ForumDetailFragment : BaseLazyTabFragment(), IScrollable {
|
||||
return when (position) {
|
||||
INDEX_ALL -> "全部Tab"
|
||||
INDEX_ESSENCE -> "精华Tab"
|
||||
INDEX_ASK -> "问答Tab"
|
||||
else -> "视频Tab"
|
||||
mAskIndex -> "问答Tab"
|
||||
mVideoIndex -> "视频Tab"
|
||||
else -> "专区Tab"
|
||||
}
|
||||
}
|
||||
|
||||
@ -331,7 +396,7 @@ class ForumDetailFragment : BaseLazyTabFragment(), IScrollable {
|
||||
mBinding.forumDefaultBackground.goneIf(background.isNotEmpty())
|
||||
mBinding.forumMaskDefaultView.goneIf(background.isNotEmpty())
|
||||
mBinding.moderatorContainer.visibleIf(moderator.isNotEmpty())
|
||||
mBinding.gameZoneTv.visibleIf(zone != null)
|
||||
mBinding.gameDetailTv.goneIf(!game.active)
|
||||
mBinding.forumNameTv.text = name
|
||||
mBinding.followTv.text = if (me.isFollower) "已关注" else "关注"
|
||||
mBinding.titleTv.text = name
|
||||
@ -407,11 +472,66 @@ class ForumDetailFragment : BaseLazyTabFragment(), IScrollable {
|
||||
requireContext(),
|
||||
if (me.isFollower) R.drawable.button_round_gray_light else R.drawable.download_button_normal_style
|
||||
)
|
||||
mBinding.allOrderSfv.setItemList(mDefOrderList, 0)
|
||||
mBinding.askOrderSfv.setItemList(mDefOrderList, 0)
|
||||
mBinding.videoOrderSfv.setItemList(mVideoOrderList, 0)
|
||||
|
||||
showModeratorGuide()
|
||||
|
||||
if (backgroundLayerColor.isNotEmpty()) {
|
||||
val colorRGBList =
|
||||
backgroundLayerColor.substring(4, backgroundLayerColor.length - 1).split(",").map { it.toInt() }
|
||||
val colorHSV = colorRGBList.colorRGBToHSV().apply {
|
||||
this[2] *= 0.6F
|
||||
}
|
||||
val startColor = Color.HSVToColor(colorHSV)
|
||||
val endColor = ColorUtils.setAlphaComponent(startColor, 0)
|
||||
|
||||
mBinding.forumTopMaskContainer.background = GradientDrawable().apply {
|
||||
gradientType = GradientDrawable.LINEAR_GRADIENT
|
||||
orientation = GradientDrawable.Orientation.BOTTOM_TOP
|
||||
colors = intArrayOf(startColor, endColor)
|
||||
}
|
||||
}
|
||||
|
||||
mBinding.forumHeatTv.text = "热度值:${NumberUtils.transSimpleCount(hot)}"
|
||||
mBinding.forumHeatTv.setDrawableEnd(
|
||||
if (hotRank <= 20) AppCompatResources.getDrawable(
|
||||
requireContext(),
|
||||
R.drawable.icon_heat
|
||||
) else null
|
||||
)
|
||||
mBinding.sectionMoreIv.setOnClickListener {
|
||||
showSectionsPopupWindow()
|
||||
}
|
||||
|
||||
zone?.let {
|
||||
mTabTitleList.add(INDEX_TRENDS, it.customName.ifEmpty { TAB_TRENDS })
|
||||
if (it.style == "link") {//显示web页面
|
||||
val webFragment = childFragmentManager.findFragmentByTag("${tag}$INDEX_TRENDS") ?: WebFragment()
|
||||
val webBundle = Bundle()
|
||||
webBundle.putString(EntranceConsts.KEY_ENTRANCE, "游戏专区")
|
||||
webBundle.putString(EntranceConsts.KEY_URL, it.link)
|
||||
webBundle.putBoolean(WebFragment.KEY_OPEN_NATIVE_PAGE, true)
|
||||
webBundle.putString(EntranceConsts.KEY_PATH, TAB_TRENDS)
|
||||
webFragment.arguments = webBundle
|
||||
mTrendsFragment = webFragment
|
||||
mFragmentsList.add(INDEX_TRENDS, webFragment)
|
||||
} else {
|
||||
val fuliFragment = childFragmentManager.findFragmentByTag("${tag}$INDEX_TRENDS") ?: FuLiFragment()
|
||||
fuliFragment.arguments = bundleOf(
|
||||
GameEntity.TAG to game.toGameEntity(),
|
||||
EntranceConsts.KEY_ENTRANCE to mEntrance,
|
||||
EntranceConsts.KEY_PATH to TAB_TRENDS
|
||||
)
|
||||
mTrendsFragment = fuliFragment
|
||||
mFragmentsList.add(INDEX_TRENDS, fuliFragment)
|
||||
}
|
||||
mViewPager.adapter?.notifyDataSetChanged()
|
||||
mAskIndex = INDEX_ASK + 1
|
||||
mVideoIndex = INDEX_VIDEO + 1
|
||||
|
||||
if (arguments?.getBoolean(EntranceConsts.KEY_SCROLL_TO_TRENDS, false) == true) {
|
||||
mViewPager.currentItem = INDEX_TRENDS
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -462,18 +582,6 @@ class ForumDetailFragment : BaseLazyTabFragment(), IScrollable {
|
||||
NewLogUtils.logForumDetailEnterOrClick("click_forum_detail_search")
|
||||
requireContext().startActivity(ForumOrUserSearchActivity.getIntent(requireContext(), mBbsId, "论坛详情"))
|
||||
}
|
||||
mBinding.allOrderSfv.setOnCheckedCallback { position ->
|
||||
mFilter = mDefOrderList[position]
|
||||
mAllForumArticleAskListFragment?.onRefresh(mDefOrderList[position])
|
||||
}
|
||||
mBinding.askOrderSfv.setOnCheckedCallback { position ->
|
||||
mFilter = mDefOrderList[position]
|
||||
mAskForumArticleAskListFragment?.onRefresh(mDefOrderList[position])
|
||||
}
|
||||
mBinding.videoOrderSfv.setOnCheckedCallback { position ->
|
||||
mVideoFilter = mVideoOrderList[position]
|
||||
mVideoForumArticleAskListFragment?.onRefresh(mVideoOrderList[position])
|
||||
}
|
||||
mBinding.forumTopContentArrowContainer.setOnClickListener {
|
||||
mForumDetail?.run {
|
||||
mBinding.run {
|
||||
@ -543,16 +651,17 @@ class ForumDetailFragment : BaseLazyTabFragment(), IScrollable {
|
||||
mSkeleton.show()
|
||||
mViewModel?.getForumDetail()
|
||||
mViewModel?.getModeratorsApplyStatus()
|
||||
mViewModel?.getSections()
|
||||
}
|
||||
mBinding.gameZoneTv.setOnClickListener {
|
||||
NewLogUtils.logForumDetailEnterOrClick("click_strategy_zone", mBbsId, mBbsType)
|
||||
if (mForumDetail?.zone != null) {
|
||||
MtaHelper.onEvent("论坛详情", "顶部区域", "游戏专区")
|
||||
GameDetailActivity.startGameDetailActivity(
|
||||
requireContext(), mForumDetail?.game?.id ?: "", mEntrance, GameDetailFragment.INDEX_TRENDES
|
||||
)
|
||||
}
|
||||
}
|
||||
// mBinding.gameZoneTv.setOnClickListener {
|
||||
// NewLogUtils.logForumDetailEnterOrClick("click_strategy_zone", mBbsId, mBbsType)
|
||||
// if (mForumDetail?.zone != null) {
|
||||
// MtaHelper.onEvent("论坛详情", "顶部区域", "游戏专区")
|
||||
// GameDetailActivity.startGameDetailActivity(
|
||||
// requireContext(), mForumDetail?.game?.id ?: "", mEntrance, GameDetailFragment.INDEX_TRENDES
|
||||
// )
|
||||
// }
|
||||
// }
|
||||
mBinding.forumThumbBig.setOnClickListener {
|
||||
NewLogUtils.logForumDetailEnterOrClick("click_forum_detail_forum_icon", mBbsId)
|
||||
MtaHelper.onEvent("论坛详情", "顶部区域", "游戏图标")
|
||||
@ -613,6 +722,12 @@ class ForumDetailFragment : BaseLazyTabFragment(), IScrollable {
|
||||
)
|
||||
)
|
||||
}
|
||||
mBinding.gameDetailTv.setOnClickListener {
|
||||
GameDetailActivity.startGameDetailActivity(
|
||||
requireContext(), mForumDetail?.game?.id
|
||||
?: "", "(论坛详情)"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateToolbarStyle(isToolbarWhite: Boolean) {
|
||||
@ -683,30 +798,42 @@ class ForumDetailFragment : BaseLazyTabFragment(), IScrollable {
|
||||
private fun initModeratorHeadView(datas: List<UserEntity>) {
|
||||
mBinding.moderatorContainer.removeAllViews()
|
||||
datas.forEachIndexed { index, user ->
|
||||
val headView = SimpleDraweeView(requireContext())
|
||||
val roundingParams = RoundingParams().apply {
|
||||
roundAsCircle = true
|
||||
setBorder(ContextCompat.getColor(requireContext(), R.color.white), 1f.dip2px().toFloat())
|
||||
}
|
||||
headView.hierarchy = GenericDraweeHierarchyBuilder(resources)
|
||||
.setFadeDuration(500)
|
||||
.setRoundingParams(roundingParams)
|
||||
.setPressedStateOverlay(ColorDrawable(ContextCompat.getColor(requireContext(), R.color.pressed_bg)))
|
||||
.setPlaceholderImage(R.drawable.occupy2, ScalingUtils.ScaleType.CENTER)
|
||||
.setBackground(ColorDrawable(ContextCompat.getColor(requireContext(), R.color.placeholder_bg)))
|
||||
.setActualImageScaleType(ScalingUtils.ScaleType.CENTER_CROP)
|
||||
.build()
|
||||
val params = LinearLayout.LayoutParams(20f.dip2px(), 20f.dip2px())
|
||||
headView.layoutParams = params
|
||||
if (index != 0) {
|
||||
params.leftMargin = (-8f).dip2px()
|
||||
if (index < 3) {
|
||||
val headView = SimpleDraweeView(requireContext())
|
||||
val roundingParams = RoundingParams().apply {
|
||||
roundAsCircle = true
|
||||
setBorder(ContextCompat.getColor(requireContext(), R.color.white), 1f.dip2px().toFloat())
|
||||
}
|
||||
headView.hierarchy = GenericDraweeHierarchyBuilder(resources)
|
||||
.setFadeDuration(500)
|
||||
.setRoundingParams(roundingParams)
|
||||
.setPressedStateOverlay(ColorDrawable(ContextCompat.getColor(requireContext(), R.color.pressed_bg)))
|
||||
.setPlaceholderImage(R.drawable.occupy2, ScalingUtils.ScaleType.CENTER)
|
||||
.setBackground(ColorDrawable(ContextCompat.getColor(requireContext(), R.color.placeholder_bg)))
|
||||
.setActualImageScaleType(ScalingUtils.ScaleType.CENTER_CROP)
|
||||
.build()
|
||||
headView.layoutParams = params
|
||||
if (index != 0) {
|
||||
params.leftMargin = (-8f).dip2px()
|
||||
}
|
||||
ImageUtils.display(headView, user.icon)
|
||||
headView.setOnClickListener {
|
||||
MtaHelper.onEvent("论坛详情", "顶部区域", "版主头像")
|
||||
mBinding.moderatorTv.performClick()
|
||||
}
|
||||
mBinding.moderatorContainer.addView(headView)
|
||||
} else if (index == 3) {
|
||||
params.leftMargin = (-8F).dip2px()
|
||||
mBinding.moderatorContainer.addView(ImageView(requireContext()).apply {
|
||||
layoutParams = params
|
||||
setImageResource(R.drawable.icon_moderator_more)
|
||||
setOnClickListener {
|
||||
MtaHelper.onEvent("论坛详情", "顶部区域", "版主头像")
|
||||
mBinding.moderatorTv.performClick()
|
||||
}
|
||||
})
|
||||
}
|
||||
ImageUtils.display(headView, user.icon)
|
||||
headView.setOnClickListener {
|
||||
MtaHelper.onEvent("论坛详情", "顶部区域", "版主头像")
|
||||
mBinding.moderatorTv.performClick()
|
||||
}
|
||||
mBinding.moderatorContainer.addView(headView)
|
||||
}
|
||||
|
||||
}
|
||||
@ -812,6 +939,72 @@ class ForumDetailFragment : BaseLazyTabFragment(), IScrollable {
|
||||
}
|
||||
}
|
||||
|
||||
private fun showSectionsPopupWindow() {
|
||||
val binding = PopupForumDetailSectionsBinding.inflate(LayoutInflater.from(requireContext()), null, false)
|
||||
val popupWindow = PopupWindow(
|
||||
binding.root,
|
||||
LinearLayout.LayoutParams.MATCH_PARENT,
|
||||
LinearLayout.LayoutParams.WRAP_CONTENT
|
||||
).apply { mPopupWindow = this }
|
||||
|
||||
mViewModel?.sectionListLiveData?.value?.forEachIndexed { index, section ->
|
||||
val item = getItemTextView(section.name)
|
||||
binding.flexbox.addView(item)
|
||||
item.tag = section.name
|
||||
toggleHighlightedTextView(item, mViewModel?.selectedSection?.id == section.id)
|
||||
item.setOnClickListener {
|
||||
toggleHighlightedTextView(item, true)
|
||||
mViewModel?.selectedSection = section
|
||||
mAllForumArticleAskListFragment?.setSection(
|
||||
mViewModel?.selectedSection ?: ForumDetailEntity.Section(
|
||||
"",
|
||||
"全部"
|
||||
)
|
||||
)
|
||||
mForumSectionAdapter?.run {
|
||||
notifyItemRangeChanged(0, itemCount)
|
||||
}
|
||||
mBinding.sectionRv.smoothScrollToPosition(index)
|
||||
popupWindow.dismiss()
|
||||
}
|
||||
}
|
||||
|
||||
binding.background.setOnClickListener {
|
||||
popupWindow.dismiss()
|
||||
mPopupWindow = null
|
||||
}
|
||||
binding.closeIv.setOnClickListener {
|
||||
popupWindow.dismiss()
|
||||
mPopupWindow = null
|
||||
}
|
||||
popupWindow.isTouchable = true
|
||||
popupWindow.isFocusable = true
|
||||
popupWindow.animationStyle = 0
|
||||
popupWindow.showAsDropDown(mBinding.tabContainer, 0, 0)
|
||||
}
|
||||
|
||||
private fun toggleHighlightedTextView(targetTextView: TextView, highlightIt: Boolean) {
|
||||
if (highlightIt) {
|
||||
targetTextView.background = R.drawable.button_round_primary_light.toDrawable(requireContext())
|
||||
targetTextView.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()))
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||
super.onActivityResult(requestCode, resultCode, data)
|
||||
if (resultCode == Activity.RESULT_OK) {
|
||||
@ -843,7 +1036,14 @@ class ForumDetailFragment : BaseLazyTabFragment(), IScrollable {
|
||||
|
||||
override fun onBackPressed(): Boolean {
|
||||
NewLogUtils.logForumDetailEnterOrClick("click_forum_detail_return", mBbsId, mBbsType)
|
||||
return (mFragmentsList[mBinding.fragmentViewPager.currentItem] as ForumArticleAskListFragment).onBackPressed()
|
||||
val fragment = mFragmentsList[mBinding.fragmentViewPager.currentItem]
|
||||
return if (fragment is ForumArticleAskListFragment) {
|
||||
fragment.onBackPressed()
|
||||
} else if (fragment is WebFragment && fragment.isAdded) {
|
||||
fragment.onBackPressed()
|
||||
} else {
|
||||
super.onBackPressed()
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
@ -877,30 +1077,13 @@ class ForumDetailFragment : BaseLazyTabFragment(), IScrollable {
|
||||
super.onDarkModeChanged()
|
||||
updateToolbarStyle(mIsToolbarWhite)
|
||||
if (::mBinding.isInitialized) {
|
||||
listOf(
|
||||
mBinding.allOrderSfv,
|
||||
mBinding.askOrderSfv,
|
||||
mBinding.videoOrderSfv
|
||||
).forEach {
|
||||
updateOrderView(it)
|
||||
}
|
||||
for (i in 0 until mBinding.fragmentTabLayout.tabCount) {
|
||||
val tab = mBinding.fragmentTabLayout.getTabAt(i)
|
||||
if (tab != null) {
|
||||
BaseFragment_TabLayout.updateTabStyle(tab, tab.isSelected)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateOrderView(view: SegmentedFilterView) {
|
||||
view.run {
|
||||
setContainerBackground(R.drawable.button_round_f5f5f5.toDrawable(requireContext()))
|
||||
setIndicatorBackground(R.drawable.bg_game_collection_sfv_indicator.toDrawable(requireContext()))
|
||||
setTextColor(
|
||||
R.color.text_subtitle.toColor(requireContext()),
|
||||
R.color.text_subtitleDesc.toColor(requireContext())
|
||||
)
|
||||
mForumSectionAdapter?.let { it.notifyItemRangeChanged(0, it.itemCount) }
|
||||
}
|
||||
}
|
||||
|
||||
@ -915,10 +1098,12 @@ class ForumDetailFragment : BaseLazyTabFragment(), IScrollable {
|
||||
companion object {
|
||||
const val INDEX_ALL = 0
|
||||
const val INDEX_ESSENCE = 1
|
||||
const val INDEX_TRENDS = 2
|
||||
const val INDEX_ASK = 2
|
||||
const val INDEX_VIDEO = 3
|
||||
const val TAB_TITLE_ALL = "全部"
|
||||
const val TAB_TITLE_ESSENCE = "精华"
|
||||
const val TAB_TRENDS = "专区"
|
||||
const val TAB_TITLE_ASK = "问答"
|
||||
const val TAB_TITLE_VIDEO = "视频"
|
||||
const val EB_SHOW_QUESTION_BUTTON = "EB_SHOW_QUESTION_BUTTON"
|
||||
|
||||
@ -27,15 +27,20 @@ import retrofit2.HttpException
|
||||
class ForumDetailViewModel(application: Application, val bbsId: String) : AndroidViewModel(application) {
|
||||
|
||||
private val mApi = RetrofitManager.getInstance().api
|
||||
private val mNewApi = RetrofitManager.getInstance().newApi
|
||||
private val mForumDao = AppDatabase.getInstance().forumDao()
|
||||
var forumDetail = MutableLiveData<Resource<ForumDetailEntity>>()
|
||||
val answerLiveData = MediatorLiveData<AnswerEntity>()
|
||||
val statusEntity = MutableLiveData<ApplyModeratorStatusEntity?>()
|
||||
val sectionListLiveData = MutableLiveData<List<ForumDetailEntity.Section>>()
|
||||
|
||||
var selectedSection = ForumDetailEntity.Section("", "全部")
|
||||
|
||||
init {
|
||||
postForumRead()
|
||||
getForumDetail()
|
||||
getModeratorsApplyStatus()
|
||||
getSections()
|
||||
}
|
||||
|
||||
@SuppressLint("CheckResult")
|
||||
@ -146,6 +151,20 @@ class ForumDetailViewModel(application: Application, val bbsId: String) : Androi
|
||||
})
|
||||
}
|
||||
|
||||
fun getSections() {
|
||||
mNewApi.getForumSections(bbsId)
|
||||
.compose(observableToMain())
|
||||
.subscribe(object : Response<List<ForumDetailEntity.Section>>() {
|
||||
override fun onResponse(response: List<ForumDetailEntity.Section>?) {
|
||||
response?.run {
|
||||
val sectionList = ArrayList(this)
|
||||
sectionList.add(0, ForumDetailEntity.Section("", "全部"))
|
||||
sectionListLiveData.postValue(sectionList)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fun convertArticleDetailToAnswer(articleDetailEntity: ArticleDetailEntity): AnswerEntity {
|
||||
val answerEntity = AnswerEntity()
|
||||
|
||||
|
||||
@ -0,0 +1,56 @@
|
||||
package com.gh.gamecenter.forum.detail
|
||||
|
||||
import android.content.Context
|
||||
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.databinding.ItemForumSectionBinding
|
||||
import com.gh.gamecenter.entity.ForumDetailEntity
|
||||
import com.lightgame.adapter.BaseRecyclerAdapter
|
||||
|
||||
class ForumSectionAdapter(context: Context, val viewModel: ForumDetailViewModel, val onClick: () -> Unit) :
|
||||
BaseRecyclerAdapter<ForumSectionAdapter.ForumSectionItemViewHolder>(context) {
|
||||
|
||||
private var mSectionList = listOf<ForumDetailEntity.Section>()
|
||||
|
||||
fun submitList(sectionList: List<ForumDetailEntity.Section>) {
|
||||
mSectionList = sectionList
|
||||
notifyItemRangeChanged(0, itemCount)
|
||||
}
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ForumSectionItemViewHolder =
|
||||
ForumSectionItemViewHolder(parent.toBinding())
|
||||
|
||||
override fun getItemCount(): Int = mSectionList.size
|
||||
|
||||
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()
|
||||
}
|
||||
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()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class ForumSectionItemViewHolder(val binding: ItemForumSectionBinding) : RecyclerView.ViewHolder(binding.root)
|
||||
}
|
||||
@ -2,8 +2,8 @@ package com.gh.gamecenter.forum.search
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import androidx.appcompat.content.res.AppCompatResources
|
||||
import androidx.constraintlayout.widget.ConstraintLayout
|
||||
import androidx.vectordrawable.graphics.drawable.VectorDrawableCompat
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.utils.*
|
||||
import com.gh.gamecenter.databinding.FragmentSearchDefaultBinding
|
||||
@ -75,11 +75,12 @@ class ForumOrUserSearchDefaultFragment : SearchDefaultFragment() {
|
||||
headTitle.textSize = 16F
|
||||
headActionTv.text = "清空"
|
||||
headActionTv.setTextColor(R.color.text_subtitleDesc.toColor(requireContext()))
|
||||
headActionTv.setDrawableStart(VectorDrawableCompat.create(
|
||||
resources,
|
||||
R.drawable.search_history_delete,
|
||||
null
|
||||
))
|
||||
headActionTv.setDrawableStart(
|
||||
AppCompatResources.getDrawable(
|
||||
requireContext(),
|
||||
R.drawable.search_history_delete
|
||||
)
|
||||
)
|
||||
headActionTv.setOnClickListener {
|
||||
DialogHelper.showCenterWarningDialog(requireContext(), "清空记录", "确定清空历史搜索记录?", confirmClickCallback = {
|
||||
mSearchDao.deleteAll()
|
||||
|
||||
@ -11,6 +11,7 @@ import com.gh.gamecenter.common.utils.singleToMain
|
||||
import com.gh.gamecenter.common.utils.toColor
|
||||
import com.gh.gamecenter.entity.HomeDataEntity
|
||||
import com.gh.gamecenter.entity.SubjectRecommendEntity
|
||||
import com.gh.gamecenter.pkg.PkgHelper
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager
|
||||
import com.halo.assistant.HaloApp
|
||||
|
||||
@ -64,6 +65,20 @@ class HomeSearchToolWrapperViewModel(application: Application) : AndroidViewMode
|
||||
if (homeTab.size == 0) {
|
||||
homeTab.add(SubjectRecommendEntity(type = "home"))
|
||||
}
|
||||
|
||||
// 从推广包配置信息里找是否需要默认选中一个 tab
|
||||
PkgHelper.getPkgConfig()?.let { pkgLinkEntity ->
|
||||
if (pkgLinkEntity.isHomeTopTabLink) {
|
||||
PkgHelper.markConfigUsed()
|
||||
for ((index, tab) in homeTab.withIndex()) {
|
||||
if (pkgLinkEntity.type == tab.type && pkgLinkEntity.link == tab.link) {
|
||||
defaultTabPosition = index
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!isRefresh) {
|
||||
tabs.postValue(homeTab)
|
||||
}
|
||||
|
||||
@ -29,22 +29,28 @@ import com.facebook.imagepipeline.image.ImageInfo;
|
||||
import com.gh.common.constant.Config;
|
||||
import com.gh.common.dialog.PrivacyPolicyDialogFragment;
|
||||
import com.gh.common.dialog.ReserveDialog;
|
||||
import com.gh.common.util.DirectUtils;
|
||||
import com.gh.common.util.HomeBottomBarHelper;
|
||||
import com.gh.common.util.IntegralLogHelper;
|
||||
import com.gh.common.util.LogUtils;
|
||||
import com.gh.common.util.NewLogUtils;
|
||||
import com.gh.gamecenter.R;
|
||||
import com.gh.gamecenter.ShellActivity;
|
||||
import com.gh.gamecenter.category2.CategoryV2Fragment;
|
||||
import com.gh.gamecenter.common.base.fragment.BaseFragment_ViewPager_Checkable;
|
||||
import com.gh.gamecenter.common.callback.BiCallback;
|
||||
import com.gh.gamecenter.common.callback.OnDoubleTapListener;
|
||||
import com.gh.gamecenter.common.constant.Constants;
|
||||
import com.gh.gamecenter.common.constant.EntranceConsts;
|
||||
import com.gh.gamecenter.common.entity.PkgConfigEntity;
|
||||
import com.gh.gamecenter.common.eventbus.EBReuse;
|
||||
import com.gh.gamecenter.common.syncpage.SyncPageRepository;
|
||||
import com.gh.gamecenter.common.tracker.TrackerLogger;
|
||||
import com.gh.gamecenter.common.utils.ExtensionsKt;
|
||||
import com.gh.gamecenter.common.utils.ImageUtils;
|
||||
import com.gh.gamecenter.core.utils.DisplayUtils;
|
||||
import com.gh.gamecenter.core.utils.GsonUtils;
|
||||
import com.gh.gamecenter.core.utils.SPUtils;
|
||||
import com.gh.gamecenter.databinding.FragmentMainBinding;
|
||||
import com.gh.gamecenter.entity.SubjectData;
|
||||
import com.gh.gamecenter.entity.SubjectRecommendEntity;
|
||||
@ -58,9 +64,11 @@ import com.gh.gamecenter.game.GameFragment;
|
||||
import com.gh.gamecenter.game.columncollection.detail.ColumnCollectionDetailFragment;
|
||||
import com.gh.gamecenter.game.commoncollection.detail.CommonCollectionDetailFragment;
|
||||
import com.gh.gamecenter.gamecollection.square.GameCollectionSquareFragment;
|
||||
import com.gh.gamecenter.login.entity.UserInfoEntity;
|
||||
import com.gh.gamecenter.message.MessageUnreadRepository;
|
||||
import com.gh.gamecenter.message.MessageUnreadViewModel;
|
||||
import com.gh.gamecenter.personal.HaloPersonalFragment;
|
||||
import com.gh.gamecenter.pkg.PkgHelper;
|
||||
import com.gh.gamecenter.servers.GameServersPublishFragment;
|
||||
import com.gh.gamecenter.servers.GameServersTestFragment;
|
||||
import com.gh.gamecenter.subject.SubjectFragment;
|
||||
@ -258,11 +266,47 @@ public class MainWrapperFragment extends BaseFragment_ViewPager_Checkable implem
|
||||
}
|
||||
});
|
||||
|
||||
applyPkgConfig();
|
||||
|
||||
ViewModelProviders.of(this)
|
||||
.get(MessageUnreadViewModel.class)
|
||||
.getUnreadMessageTotalLiveData().observe(this, isShow -> ExtensionsKt.goneIf(mBinding.mainIvMessageHint, !isShow));
|
||||
}
|
||||
|
||||
private void applyPkgConfig() {
|
||||
PkgConfigEntity.PkgLinkEntity pkgLinkEntity = PkgHelper.INSTANCE.getPkgConfig();
|
||||
if (pkgLinkEntity != null && !pkgLinkEntity.isHomeTopTabLink()) {
|
||||
String bottomTab = pkgLinkEntity.getHomeBottomTab();
|
||||
|
||||
PkgHelper.INSTANCE.markConfigUsed();
|
||||
if (!TextUtils.isEmpty(bottomTab)) {
|
||||
// TODO 根据具体 tab 来作为跳转的具体位置,避免硬编码
|
||||
int targetIndex = INDEX_HOME;
|
||||
|
||||
switch (bottomTab) {
|
||||
case "game_lib":
|
||||
targetIndex = INDEX_GAME;
|
||||
break;
|
||||
case "community":
|
||||
targetIndex = INDEX_BBS;
|
||||
break;
|
||||
case "video":
|
||||
targetIndex = INDEX_VIDEO;
|
||||
break;
|
||||
case "gh":
|
||||
targetIndex = INDEX_PERSONAL;
|
||||
break;
|
||||
}
|
||||
|
||||
mViewPager.setCurrentItem(targetIndex);
|
||||
onPageChanged(targetIndex);
|
||||
changeColor(targetIndex);
|
||||
} else {
|
||||
DirectUtils.directToLinkPage(requireContext(), pkgLinkEntity, "推广包配置", "首页");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void getDialog() {
|
||||
mViewModel.requestOpeningData();
|
||||
mViewModel.getPrivacyPolicyDialog().observe(this, it -> {
|
||||
@ -579,6 +623,33 @@ public class MainWrapperFragment extends BaseFragment_ViewPager_Checkable implem
|
||||
} else {
|
||||
mBinding.mainTabCommunity.setVisibility(View.VISIBLE);
|
||||
}
|
||||
} else if (Constants.EB_REALNAME_RESULT.equals(reuse.getType())) {
|
||||
updateRealNameErrorContainer();
|
||||
}
|
||||
}
|
||||
|
||||
private void updateRealNameErrorContainer() {
|
||||
String deviceCertificationInfoString =
|
||||
SPUtils.getString(Constants.SP_DEVICE_CERTIFICATION_PREFIX + HaloApp.getInstance().getGid());
|
||||
|
||||
// 未点过关闭按钮并且处于实名认证失败状态的,显示提示 view
|
||||
if (!SPUtils.getBoolean(Constants.SP_REALNAME_ERROR_HINT_IGNORED)
|
||||
&& !TextUtils.isEmpty(deviceCertificationInfoString)) {
|
||||
UserInfoEntity entity = GsonUtils.fromJson(deviceCertificationInfoString, UserInfoEntity.class);
|
||||
if (entity.getIdCard() != null
|
||||
&& entity.getIdCard().getStatus() == 2) {
|
||||
mBinding.realNameErrorContainer.setVisibility(View.VISIBLE);
|
||||
ExtensionsKt.enlargeTouchArea(mBinding.realNameErrorCloseIv, 100);
|
||||
mBinding.realNameErrorCloseIv.setOnClickListener(v -> {
|
||||
SPUtils.setBoolean(Constants.SP_REALNAME_ERROR_HINT_IGNORED, true);
|
||||
mBinding.realNameErrorContainer.setVisibility(View.GONE);
|
||||
});
|
||||
mBinding.realNameErrorContainer.setOnClickListener(v -> {
|
||||
startActivity(ShellActivity.getIntent(requireActivity(), ShellActivity.Type.REAL_NAME_INFO, null));
|
||||
});
|
||||
} else {
|
||||
mBinding.realNameErrorContainer.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -11,7 +11,6 @@ import androidx.recyclerview.widget.RecyclerView
|
||||
import com.ethanhua.skeleton.Skeleton
|
||||
import com.ethanhua.skeleton.ViewSkeletonScreen
|
||||
import com.gh.common.exposure.ExposureListener
|
||||
import com.gh.gamecenter.feature.exposure.ExposureSource
|
||||
import com.gh.common.util.DialogUtils
|
||||
import com.gh.common.xapk.XapkInstaller
|
||||
import com.gh.common.xapk.XapkUnzipStatus
|
||||
@ -32,8 +31,10 @@ import com.gh.gamecenter.eventbus.EBDiscoverChanged
|
||||
import com.gh.gamecenter.eventbus.EBDownloadStatus
|
||||
import com.gh.gamecenter.eventbus.EBPackage
|
||||
import com.gh.gamecenter.eventbus.EBUISwitch
|
||||
import com.gh.gamecenter.feature.exposure.ExposureSource
|
||||
import com.gh.gamecenter.fragment.MainWrapperFragment
|
||||
import com.gh.gamecenter.game.data.GameItemData
|
||||
import com.gh.gamecenter.home.test_v2.HomeGameTestV2ViewModel
|
||||
import com.gh.gamecenter.home.video.ScrollCalculatorHelper
|
||||
import com.halo.assistant.HaloApp
|
||||
import com.lightgame.download.DataWatcher
|
||||
@ -44,6 +45,7 @@ import org.greenrobot.eventbus.ThreadMode
|
||||
class GameFragment : LazyFragment() {
|
||||
|
||||
private lateinit var mViewModel: GameViewModel
|
||||
private lateinit var mHomeGameTestV2ViewModel: HomeGameTestV2ViewModel
|
||||
|
||||
private lateinit var mBinding: FragmentGameBinding
|
||||
private lateinit var mSkeleton: ViewSkeletonScreen
|
||||
@ -76,9 +78,13 @@ class GameFragment : LazyFragment() {
|
||||
)
|
||||
mViewModel = ViewModelProviders.of(this, factory).get(GameViewModel::class.java)
|
||||
mViewModel.entrance = mEntrance
|
||||
//新游开测模块
|
||||
mHomeGameTestV2ViewModel = viewModelProvider()
|
||||
mHomeGameTestV2ViewModel.location = "板块"
|
||||
mHomeGameTestV2ViewModel.blockData = mViewModel.blockData
|
||||
mViewModel.setHomeGameTestV2DownloadStateUpdateHelper(mHomeGameTestV2ViewModel)
|
||||
|
||||
super.onFragmentFirstVisible()
|
||||
mScrollCalculatorHelper = ScrollCalculatorHelper(mBinding.gameList, R.id.autoVideoView, 0)
|
||||
|
||||
mViewModel.loadStatus.observe(this) {
|
||||
if (it != null) {
|
||||
@ -120,6 +126,7 @@ class GameFragment : LazyFragment() {
|
||||
super.initRealView()
|
||||
|
||||
mBinding = FragmentGameBinding.bind(mCachedView)
|
||||
mScrollCalculatorHelper = ScrollCalculatorHelper(mBinding.gameList, R.id.autoVideoView, 0)
|
||||
mBinding.gameRefresh.setColorSchemeColors(ContextCompat.getColor(requireContext(), R.color.theme))
|
||||
mLayoutManager = FixLinearLayoutManager(context)
|
||||
val exposureSourceList = arrayListOf<ExposureSource>().apply {
|
||||
@ -133,7 +140,15 @@ class GameFragment : LazyFragment() {
|
||||
)
|
||||
)
|
||||
}
|
||||
mListAdapter = GameFragmentAdapter(requireContext(), mViewModel, exposureSourceList, mLayoutManager)
|
||||
mListAdapter = GameFragmentAdapter(
|
||||
requireContext(),
|
||||
mViewModel,
|
||||
this,
|
||||
mHomeGameTestV2ViewModel = mHomeGameTestV2ViewModel,
|
||||
exposureSourceList,
|
||||
mLayoutManager,
|
||||
mScrollCalculatorHelper
|
||||
)
|
||||
|
||||
mBinding.gameList.run {
|
||||
(itemAnimator as DefaultItemAnimator).supportsChangeAnimations = false
|
||||
@ -237,35 +252,30 @@ class GameFragment : LazyFragment() {
|
||||
}
|
||||
|
||||
private fun pauseVideo() {
|
||||
if (mScrollCalculatorHelper.currentPosition >= 0) {
|
||||
mScrollCalculatorHelper.currentPlayer?.resetDetailMask()
|
||||
mScrollCalculatorHelper.currentPlayer?.onVideoPause()
|
||||
val currentPosition = mScrollCalculatorHelper.currentPlayer?.getCurrentPosition() ?: 0L
|
||||
val topVideo =
|
||||
mViewModel.itemDataList.value?.safelyGetInRelease(mScrollCalculatorHelper.currentPosition)?.attachGame?.linkGame?.topVideo
|
||||
if (topVideo != null) {
|
||||
ScrollCalculatorHelper.savePlaySchedule(
|
||||
MD5Utils.getContentMD5(topVideo.url),
|
||||
currentPosition
|
||||
)
|
||||
val currentPlayer = mScrollCalculatorHelper.currentPlayer
|
||||
if (currentPlayer != null) {
|
||||
currentPlayer.resetDetailMask()
|
||||
currentPlayer.onVideoPause()
|
||||
val currentPosition = currentPlayer.getCurrentPosition()
|
||||
val videoUrl = currentPlayer.getUrl()
|
||||
if (videoUrl.isNotEmpty()) {
|
||||
ScrollCalculatorHelper.savePlaySchedule(MD5Utils.getContentMD5(videoUrl), currentPosition)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun resumeVideo() {
|
||||
if (mScrollCalculatorHelper.currentPlayer != null) {
|
||||
val topVideo =
|
||||
mViewModel.itemDataList.value?.safelyGetInRelease(mScrollCalculatorHelper.currentPosition)?.attachGame?.linkGame?.topVideo
|
||||
if (topVideo != null) {
|
||||
val position =
|
||||
ScrollCalculatorHelper.getPlaySchedule(MD5Utils.getContentMD5(topVideo.url))
|
||||
val currentPlayer = mScrollCalculatorHelper.currentPlayer
|
||||
if (currentPlayer != null) {
|
||||
val videoUrl = currentPlayer.getUrl()
|
||||
if (videoUrl.isNotEmpty()) {
|
||||
val position = ScrollCalculatorHelper.getPlaySchedule(MD5Utils.getContentMD5(videoUrl))
|
||||
//这里必须要延迟操作,否则会白屏
|
||||
mBaseHandler.postDelayed({
|
||||
if (position != 0L) {
|
||||
mScrollCalculatorHelper.currentPlayer?.seekTo(position)
|
||||
mScrollCalculatorHelper.currentPlayer?.onVideoResume(false)
|
||||
val topVideoVoiceStatus =
|
||||
SPUtils.getBoolean(Constants.SP_VIDEO_PLAY_MUTE, true)
|
||||
val topVideoVoiceStatus = SPUtils.getBoolean(Constants.SP_VIDEO_PLAY_MUTE, true)
|
||||
if (topVideoVoiceStatus) {
|
||||
mScrollCalculatorHelper.currentPlayer?.mute()
|
||||
} else {
|
||||
@ -283,7 +293,7 @@ class GameFragment : LazyFragment() {
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
if (::mScrollCalculatorHelper.isInitialized) {
|
||||
mScrollCalculatorHelper.currentPlayer?.release()
|
||||
mScrollCalculatorHelper.release()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -7,6 +7,7 @@ import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.ImageView
|
||||
import android.widget.LinearLayout
|
||||
import androidx.lifecycle.LifecycleOwner
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import androidx.recyclerview.widget.RecyclerView.ViewHolder
|
||||
@ -73,7 +74,14 @@ import com.gh.gamecenter.home.HomeGameItemViewHolder
|
||||
import com.gh.gamecenter.home.discovercard.DiscoverCardGameAdapter
|
||||
import com.gh.gamecenter.home.discovercard.HomeDiscoverCardViewHolder
|
||||
import com.gh.gamecenter.home.gamecollection.HomeGameCollectionViewHolder
|
||||
import com.gh.gamecenter.home.horizontalslidevideo.HomeHorizontalSlideVideoAdapter
|
||||
import com.gh.gamecenter.home.horizontalslidevideo.HomeHorizontalSlideVideoListViewHolder
|
||||
import com.gh.gamecenter.home.test_v2.HomeGameTestV2GameListRvAdapter
|
||||
import com.gh.gamecenter.home.test_v2.HomeGameTestV2ViewModel
|
||||
import com.gh.gamecenter.home.test_v2.HomeItemGameTestV2ViewHolder
|
||||
import com.gh.gamecenter.home.video.ScrollCalculatorHelper
|
||||
import com.gh.gamecenter.servers.GameServersActivity
|
||||
import com.gh.gamecenter.servers.gametest2.GameServerTestV2Activity
|
||||
import com.gh.gamecenter.subject.SubjectActivity
|
||||
import com.lightgame.adapter.BaseRecyclerAdapter
|
||||
import com.lightgame.download.DownloadEntity
|
||||
@ -81,8 +89,11 @@ import com.lightgame.download.DownloadEntity
|
||||
class GameFragmentAdapter(
|
||||
context: Context,
|
||||
model: GameViewModel,
|
||||
val mBasicExposureSource: List<ExposureSource>,
|
||||
val layoutManager: LinearLayoutManager?
|
||||
private val mLifecycleOwner: LifecycleOwner,
|
||||
private val mHomeGameTestV2ViewModel: HomeGameTestV2ViewModel,
|
||||
private val mBasicExposureSource: List<ExposureSource>,
|
||||
private val mLayoutManager: LinearLayoutManager?,
|
||||
private val mScrollCalculatorHelper: ScrollCalculatorHelper? = null
|
||||
) : BaseRecyclerAdapter<ViewHolder>(context), IExposable {
|
||||
|
||||
private val mViewModel: GameViewModel = model
|
||||
@ -135,6 +146,8 @@ class GameFragmentAdapter(
|
||||
if (itemData.attachGame != null) return ItemViewType.GAME_ITEM
|
||||
if (itemData.lineDivider != null) return ItemViewType.DIVIDER_ITEM
|
||||
if (itemData.discoverCard != null) return ItemViewType.DISCOVER_CARD
|
||||
if (itemData.gameTestV2Entity != null) return ItemViewType.COLUMN_TEST_V2
|
||||
if (itemData.horizontalSlideVideo != null) return ItemViewType.HORIZONTAL_SLIDE_VIDEO
|
||||
|
||||
return ItemViewType.LOADING
|
||||
}
|
||||
@ -173,6 +186,12 @@ class GameFragmentAdapter(
|
||||
ItemViewType.GAME_ITEM -> HomeGameItemViewHolder(parent.toBinding())
|
||||
ItemViewType.DIVIDER_ITEM -> HomeDividerViewHolder(parent.toBinding())
|
||||
ItemViewType.DISCOVER_CARD -> HomeDiscoverCardViewHolder(parent.toBinding())
|
||||
ItemViewType.COLUMN_TEST_V2 -> HomeItemGameTestV2ViewHolder(
|
||||
parent.toBinding(),
|
||||
mHomeGameTestV2ViewModel,
|
||||
mLifecycleOwner
|
||||
)
|
||||
ItemViewType.HORIZONTAL_SLIDE_VIDEO -> HomeHorizontalSlideVideoListViewHolder(parent.toBinding())
|
||||
|
||||
else -> GameItemViewHolder(GameItemBinding.bind(mLayoutInflater.inflate(R.layout.game_item, parent, false)))
|
||||
}
|
||||
@ -202,6 +221,8 @@ class GameFragmentAdapter(
|
||||
is HomeGameItemViewHolder -> bindAttachGame(holder, position)
|
||||
is HomeDividerViewHolder -> holder.bindView(mItemDataList[position].lineDivider ?: 1F)
|
||||
is HomeDiscoverCardViewHolder -> bindDiscoverCard(holder, position)
|
||||
is HomeItemGameTestV2ViewHolder -> bindGameTestV2ViewHolder(holder, position)
|
||||
is HomeHorizontalSlideVideoListViewHolder -> bindHomeHorizontalSlideVideo(holder, position)
|
||||
}
|
||||
}
|
||||
|
||||
@ -1122,6 +1143,37 @@ class GameFragmentAdapter(
|
||||
mViewModel.blockData?.name ?: ""
|
||||
)
|
||||
}
|
||||
"column_test_v2" -> {
|
||||
//跳转到新游开测页面
|
||||
val link = column.indexRightTopLink
|
||||
val text = if (column.indexRightTop == "all") {
|
||||
"全部"
|
||||
} else {
|
||||
"更多"
|
||||
}
|
||||
val location = "板块"
|
||||
//埋点上报
|
||||
if (text == "全部") {
|
||||
NewFlatLogUtils.logGameTestV2MoreClick(text, location)
|
||||
//点击进入[新游开测]详情页面
|
||||
mContext.startActivity(GameServerTestV2Activity.getIntent(mContext, "新游开测"))
|
||||
} else {
|
||||
//点击跳转通用链接
|
||||
if (link != null) {
|
||||
val blockData = mViewModel.blockData
|
||||
DirectUtils.directToLinkPage(mContext, link, "新游开测", "")
|
||||
NewFlatLogUtils.logGameTestV2MoreClick(
|
||||
text,
|
||||
location,
|
||||
blockId = blockData?.link ?: "",
|
||||
blockName = blockData?.name ?: "",
|
||||
linkType = link.type ?: "",
|
||||
linkId = link.link ?: "",
|
||||
linkText = link.text ?: ""
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
if (column.indexRightTopLink != null) {
|
||||
val link = column.indexRightTopLink!!
|
||||
@ -1239,7 +1291,7 @@ class GameFragmentAdapter(
|
||||
val listExposureEventList = arrayListOf<ExposureEvent>()
|
||||
val spanCount = 3
|
||||
|
||||
val snapHelper = holder.bindView(item.discoverCard!!, "版块", mViewModel.blockData?.name ?: "")
|
||||
val snapHelper = holder.bindView(item.discoverCard!!, "版块", position, mViewModel.blockData?.name ?: "")
|
||||
|
||||
val exposureClosure: (Int) -> Unit = {
|
||||
val gameList = discoverCard.games
|
||||
@ -1277,6 +1329,21 @@ class GameFragmentAdapter(
|
||||
|
||||
}
|
||||
|
||||
private fun bindGameTestV2ViewHolder(holder: HomeItemGameTestV2ViewHolder, position: Int) {
|
||||
val exposureItemData = mItemDataList.getOrNull(position)
|
||||
val data = exposureItemData?.gameTestV2Entity ?: return
|
||||
holder.bindData(data, exposureItemData, mBasicExposureSource, position)
|
||||
}
|
||||
|
||||
private fun bindHomeHorizontalSlideVideo(holder: HomeHorizontalSlideVideoListViewHolder, position: Int) {
|
||||
val item = mItemDataList[position]
|
||||
item.horizontalSlideVideo?.run {
|
||||
holder.bindView(this, "版块内容列表", mBasicExposureSource, mScrollCalculatorHelper) {
|
||||
item.exposureEventList?.add(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int {
|
||||
return if (mItemDataList.size > 0) mItemDataList.size + 1 else mItemDataList.size
|
||||
}
|
||||
@ -1290,13 +1357,17 @@ class GameFragmentAdapter(
|
||||
}
|
||||
if (getItemViewType(gameAndPosition.position) == ItemViewType.VERTICAL_SLIDE_ITEM
|
||||
|| getItemViewType(gameAndPosition.position) == ItemViewType.DISCOVER_CARD
|
||||
|| getItemViewType(gameAndPosition.position) == ItemViewType.COLUMN_TEST_V2
|
||||
|| getItemViewType(gameAndPosition.position) == ItemViewType.HORIZONTAL_SLIDE_VIDEO
|
||||
) {
|
||||
val view = layoutManager?.findViewByPosition(gameAndPosition.position)
|
||||
val view = mLayoutManager?.findViewByPosition(gameAndPosition.position)
|
||||
val recyclerView = view?.findViewById<RecyclerView>(R.id.recycler_view)
|
||||
when (val adapter = recyclerView?.adapter) {
|
||||
is GameVerticalAdapter -> adapter.notifyItemByDownload(download)
|
||||
is RankCollectionAdapter -> adapter.notifyItemByDownload(download)
|
||||
is DiscoverCardGameAdapter -> adapter.notifyItemByDownload(download)
|
||||
is HomeGameTestV2GameListRvAdapter -> adapter.notifyItemByDownload(download)
|
||||
is HomeHorizontalSlideVideoAdapter -> adapter.notifyItemByDownload(download)
|
||||
}
|
||||
} else {
|
||||
notifyItemChanged(gameAndPosition.position)
|
||||
@ -1319,12 +1390,16 @@ class GameFragmentAdapter(
|
||||
if (getItemViewType(position) == ItemViewType.VERTICAL_SLIDE_ITEM
|
||||
|| getItemViewType(position) == ItemViewType.RANK_COLLECTION
|
||||
|| getItemViewType(position) == ItemViewType.DISCOVER_CARD
|
||||
|| getItemViewType(position) == ItemViewType.COLUMN_TEST_V2
|
||||
|| getItemViewType(position) == ItemViewType.HORIZONTAL_SLIDE_VIDEO
|
||||
) {
|
||||
val view = layoutManager?.findViewByPosition(position)
|
||||
val view = mLayoutManager?.findViewByPosition(position)
|
||||
val recyclerView = view?.findViewById<RecyclerView>(R.id.recycler_view)
|
||||
when (val adapter = recyclerView?.adapter) {
|
||||
is RankCollectionAdapter -> adapter.notifyChildItem()
|
||||
is DiscoverCardGameAdapter -> adapter.notifyChildItem(packageName)
|
||||
is HomeGameTestV2GameListRvAdapter -> adapter.notifyChildItem(packageName)
|
||||
is HomeHorizontalSlideVideoAdapter -> adapter.notifyChildItem(packageName)
|
||||
else -> recyclerView?.adapter?.notifyDataSetChanged()
|
||||
}
|
||||
} else {
|
||||
@ -1390,6 +1465,32 @@ class GameFragmentAdapter(
|
||||
}
|
||||
continue
|
||||
}
|
||||
//新游开测相关条目
|
||||
val gameTestV2 = mItemDataList[position].gameTestV2Entity
|
||||
val gameTestV2List = mHomeGameTestV2ViewModel.getDataListLiveData().value
|
||||
gameTestV2List?.forEach { gameDataWrapper ->
|
||||
val gameEntity = gameDataWrapper.gameData
|
||||
if (gameEntity != null) {
|
||||
for (apkEntity in gameEntity.getApk()) {
|
||||
if (apkEntity.packageName == packageName) {
|
||||
positionList.add(GameAndPosition(gameEntity, position))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (gameTestV2 != null) continue
|
||||
|
||||
val horizontalSlideVideo = mItemDataList[position].horizontalSlideVideo
|
||||
if (horizontalSlideVideo != null) {
|
||||
horizontalSlideVideo.data?.forEach {
|
||||
for (apkEntity in it.getApk()) {
|
||||
if (apkEntity.packageName == packageName) {
|
||||
positionList.add(GameAndPosition(it, position))
|
||||
}
|
||||
}
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
val image = mItemDataList[position].image
|
||||
if (image != null) positionList.add(GameAndPosition(image, position))
|
||||
|
||||
@ -30,6 +30,7 @@ import com.gh.gamecenter.game.data.GameItemData
|
||||
import com.gh.gamecenter.game.rank.RankCollectionAdapter
|
||||
import com.gh.gamecenter.gamecollection.square.GameCollectionListItemData
|
||||
import com.gh.gamecenter.home.BlankDividerViewHolder
|
||||
import com.gh.gamecenter.home.test_v2.HomeGameTestV2DownloadStateUpdateHelper
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager
|
||||
import com.halo.assistant.HaloApp
|
||||
import com.lightgame.utils.Utils
|
||||
@ -43,6 +44,8 @@ import kotlin.math.roundToInt
|
||||
class GameViewModel(application: Application, var blockData: SubjectRecommendEntity?) : AndroidViewModel(application),
|
||||
IOffsetable {
|
||||
|
||||
private var mHomeGameTestV2DownloadStateUpdateHelper: HomeGameTestV2DownloadStateUpdateHelper? = null
|
||||
|
||||
private var mSlideList = ArrayList<LinkEntity>() // 轮播图
|
||||
private var mNavigationList = ArrayList<GameNavigationEntity>() // 导航栏
|
||||
private var mSubjectList: MutableList<SubjectEntity> = ArrayList() // 专题
|
||||
@ -656,6 +659,12 @@ class GameViewModel(application: Application, var blockData: SubjectRecommendEnt
|
||||
iterator.remove()
|
||||
}
|
||||
}
|
||||
//过滤掉游戏数量小于2个的视频横屏滑动专题
|
||||
if (item.type == "game_video_horizontal_slide") {
|
||||
if ((item.data?.size ?: 0) < 2) {
|
||||
iterator.remove()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 专题 "type": "image/game_vertical/game_horizontal"
|
||||
@ -730,6 +739,7 @@ class GameViewModel(application: Application, var blockData: SubjectRecommendEnt
|
||||
|
||||
if ((subjectEntity.type != "gallery"
|
||||
&& subjectEntity.type != "column_collection"
|
||||
&& subjectEntity.type != "column_test_v2"
|
||||
&& subjectEntity.type != "community_article"
|
||||
&& subjectEntity.type != "question"
|
||||
&& subjectEntity.type != "bbs_video"
|
||||
@ -923,6 +933,17 @@ class GameViewModel(application: Application, var blockData: SubjectRecommendEnt
|
||||
continue
|
||||
}
|
||||
|
||||
if (subjectEntity.type == "game_video_horizontal_slide") {
|
||||
val itemItemData = GameItemData().apply {
|
||||
horizontalSlideVideo = subjectEntity
|
||||
}
|
||||
mItemDataListCache.add(itemItemData)
|
||||
itemItemData.horizontalSlideVideo?.data?.forEach {
|
||||
addGamePositionAndPackage(it)
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
if (!data.isNullOrEmpty()) {
|
||||
for (i in 0 until data.size) {
|
||||
val game = data[i]
|
||||
@ -976,6 +997,30 @@ class GameViewModel(application: Application, var blockData: SubjectRecommendEnt
|
||||
continue
|
||||
}
|
||||
|
||||
if (subjectEntity.type == "column_test_v2") {
|
||||
//新游开测 标题和全部按钮
|
||||
val head = GameItemData()
|
||||
val rightTopLink = subjectEntity.testV2Data?.rightTop?.link
|
||||
val indexRightTop = subjectEntity.testV2Data?.rightTop?.text
|
||||
head.columnHead =
|
||||
SubjectEntity(
|
||||
type = subjectEntity.type,
|
||||
name = "新游开测",
|
||||
indexRightTop = indexRightTop,
|
||||
indexRightTopLink = LinkEntity(
|
||||
text = rightTopLink?.text,
|
||||
link = rightTopLink?.link,
|
||||
type = rightTopLink?.type
|
||||
)
|
||||
)
|
||||
mItemDataListCache.add(head)
|
||||
//新游开测 条目
|
||||
val item = GameItemData()
|
||||
item.gameTestV2Entity = subjectEntity.testV2Data
|
||||
mItemDataListCache.add(item)
|
||||
continue
|
||||
}
|
||||
|
||||
if (subjectEntity.type == "game" || subjectEntity.type == "video") {
|
||||
val itemItemData = GameItemData()
|
||||
itemItemData.attachGame = subjectEntity
|
||||
@ -1015,6 +1060,16 @@ class GameViewModel(application: Application, var blockData: SubjectRecommendEnt
|
||||
itemDataList.postValue(mItemDataListCache)
|
||||
}
|
||||
|
||||
private fun addGamePositionAndPackage(game: GameEntity, position: Int) {
|
||||
var packages = ""
|
||||
for (apkEntity in game.getApk()) {
|
||||
packages += apkEntity.packageName
|
||||
}
|
||||
positionAndPackageMap[packages + position] = position
|
||||
game.gameLocation = GameEntity.GameLocation.INDEX
|
||||
game.setEntryMap(DownloadManager.getInstance().getEntryMap(game.name))
|
||||
}
|
||||
|
||||
private fun addGamePositionAndPackage(game: GameEntity) {
|
||||
var packages = ""
|
||||
for (apkEntity in game.getApk()) {
|
||||
@ -1025,6 +1080,15 @@ class GameViewModel(application: Application, var blockData: SubjectRecommendEnt
|
||||
game.setEntryMap(DownloadManager.getInstance().getEntryMap(game.name))
|
||||
}
|
||||
|
||||
fun setHomeGameTestV2DownloadStateUpdateHelper(helper: HomeGameTestV2DownloadStateUpdateHelper) {
|
||||
mHomeGameTestV2DownloadStateUpdateHelper = helper
|
||||
mHomeGameTestV2DownloadStateUpdateHelper?.setOnGameListAddCallback { position, gameEntities ->
|
||||
gameEntities.forEach {
|
||||
addGamePositionAndPackage(it, position)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取填充间距的空白 item
|
||||
*/
|
||||
|
||||
@ -1,12 +1,13 @@
|
||||
package com.gh.gamecenter.game.data
|
||||
|
||||
import com.gh.gamecenter.feature.exposure.ExposureEvent
|
||||
import com.gh.gamecenter.common.entity.LinkEntity
|
||||
import com.gh.gamecenter.entity.*
|
||||
import com.gh.gamecenter.feature.entity.GameEntity
|
||||
import com.gh.gamecenter.feature.exposure.ExposureEvent
|
||||
import com.gh.gamecenter.gamecollection.square.GameCollectionListItemData
|
||||
import com.gh.gamecenter.home.ExposureItemData
|
||||
|
||||
class GameItemData {
|
||||
class GameItemData : ExposureItemData {
|
||||
var game: GameEntity? = null
|
||||
var columnHead: SubjectEntity? = null
|
||||
var horizontalColumn: SubjectEntity? = null
|
||||
@ -35,11 +36,15 @@ class GameItemData {
|
||||
|
||||
var discoverCard: DiscoveryCardEntity? = null // 发现页卡片
|
||||
|
||||
var gameTestV2Entity: HomeItemTestV2Entity? = null// 新游开测
|
||||
|
||||
var horizontalSlideVideo: SubjectEntity? = null //水平可自动播放的视频专题
|
||||
|
||||
var blankDivider: Float? = null // 空白的空间补全item
|
||||
|
||||
var lineDivider: Float? = null
|
||||
|
||||
var offset: Int = 0
|
||||
var exposureEvent: ExposureEvent? = null
|
||||
var exposureEventList: ArrayList<ExposureEvent>? = null
|
||||
override var offset: Int = 0
|
||||
override var exposureEvent: ExposureEvent? = null
|
||||
override var exposureEventList: ArrayList<ExposureEvent>? = null
|
||||
}
|
||||
@ -2,15 +2,15 @@ package com.gh.gamecenter.game.doublecard
|
||||
|
||||
import android.content.Context
|
||||
import android.view.ViewGroup
|
||||
import com.gh.gamecenter.feature.exposure.ExposureEvent
|
||||
import com.gh.gamecenter.GameDetailActivity
|
||||
import com.gh.gamecenter.common.base.BaseRecyclerViewHolder
|
||||
import com.gh.gamecenter.common.utils.display
|
||||
import com.gh.gamecenter.common.utils.toBinding
|
||||
import com.gh.gamecenter.core.utils.StringUtils
|
||||
import com.gh.gamecenter.databinding.GameDoubleCardItemBinding
|
||||
import com.gh.gamecenter.feature.entity.GameEntity
|
||||
import com.gh.gamecenter.entity.SubjectEntity
|
||||
import com.gh.gamecenter.feature.entity.GameEntity
|
||||
import com.gh.gamecenter.feature.exposure.ExposureEvent
|
||||
import com.gh.gamecenter.feature.game.GameItemViewHolder
|
||||
import com.lightgame.adapter.BaseRecyclerAdapter
|
||||
|
||||
@ -43,7 +43,7 @@ class DoubleCardListAdapter(
|
||||
brief.text =
|
||||
if (gameEntity.columnRecommend?.text.isNullOrBlank()) gameEntity.brief
|
||||
else gameEntity.columnRecommend!!.text
|
||||
GameItemViewHolder.initGameSubtitle(gameEntity, gameSubtitle)
|
||||
GameItemViewHolder.initGameSubtitleAndAdLabel(gameEntity, gameSubtitle)
|
||||
|
||||
root.setOnClickListener {
|
||||
GameDetailActivity.startGameDetailActivity(
|
||||
|
||||
@ -45,7 +45,7 @@ class DoubleCardViewHolder(val binding: GameDoubleCardItemAlBinding) : RecyclerV
|
||||
brief.text =
|
||||
if (gameEntity.columnRecommend?.text.isNullOrBlank()) gameEntity.brief
|
||||
else gameEntity.columnRecommend!!.text
|
||||
GameItemViewHolder.initGameSubtitle(gameEntity, gameSubtitle)
|
||||
GameItemViewHolder.initGameSubtitleAndAdLabel(gameEntity, gameSubtitle)
|
||||
|
||||
root.setOnClickListener {
|
||||
GameDetailActivity.startGameDetailActivity(
|
||||
|
||||
@ -8,11 +8,11 @@ import android.view.Gravity
|
||||
import android.view.View
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.TextView
|
||||
import androidx.appcompat.content.res.AppCompatResources
|
||||
import androidx.constraintlayout.widget.ConstraintLayout
|
||||
import androidx.core.content.ContextCompat
|
||||
import com.gh.gamecenter.feature.view.DownloadButton
|
||||
import com.gh.gamecenter.feature.view.GameIconView
|
||||
import androidx.vectordrawable.graphics.drawable.VectorDrawableCompat
|
||||
import com.airbnb.lottie.LottieAnimationView
|
||||
import com.airbnb.lottie.LottieDrawable
|
||||
import com.gh.gamecenter.R
|
||||
@ -147,11 +147,7 @@ class RankGameItemUi(override val ctx: Context) : Ui {
|
||||
gravity = Gravity.CENTER
|
||||
text = "展开"
|
||||
setTextColor(ContextCompat.getColor(context, R.color.white))
|
||||
setDrawableEnd(
|
||||
VectorDrawableCompat.create(
|
||||
resources, R.drawable.ic_jump_universal, null
|
||||
)
|
||||
)
|
||||
setDrawableEnd(AppCompatResources.getDrawable(context, R.drawable.ic_jump_universal))
|
||||
compoundDrawablePadding = dip(2)
|
||||
visibility = View.GONE
|
||||
}
|
||||
|
||||
@ -10,15 +10,14 @@ import android.view.View
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.Space
|
||||
import android.widget.TextView
|
||||
import androidx.appcompat.content.res.AppCompatResources
|
||||
import androidx.constraintlayout.widget.ConstraintLayout
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.vectordrawable.graphics.drawable.VectorDrawableCompat
|
||||
import com.airbnb.lottie.LottieAnimationView
|
||||
import com.airbnb.lottie.LottieDrawable
|
||||
import com.facebook.drawee.view.SimpleDraweeView
|
||||
import com.gh.gamecenter.feature.view.DownloadButton
|
||||
import com.gh.gamecenter.feature.view.GameIconView
|
||||
import com.gh.gamecenter.common.view.NoEllipsizeSpaceTextView
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.utils.setDrawableEnd
|
||||
import com.gh.gamecenter.common.view.GameTagContainerView
|
||||
@ -46,7 +45,8 @@ import splitties.views.startPadding
|
||||
class GameItemUi(override val ctx: Context) : Ui {
|
||||
|
||||
var iconIv: GameIconView
|
||||
var gameNameTv: NoEllipsizeSpaceTextView
|
||||
var gameNameContainer: LinearLayout
|
||||
var gameNameTv: TextView
|
||||
var gameSubtitleTv: TextView
|
||||
var adLabelTv: TextView
|
||||
var downloadTv: DownloadButton
|
||||
@ -70,6 +70,7 @@ class GameItemUi(override val ctx: Context) : Ui {
|
||||
gameNameTv = initGameNameTv()
|
||||
gameSubtitleTv = initGameSubtitleTv()
|
||||
adLabelTv = initAdLabelTv()
|
||||
gameNameContainer = initGameNameContainer()
|
||||
downloadTv = initDownloadTv()
|
||||
multiVersionDownloadTv = initMultiVersionDownloadTv()
|
||||
downloadTipsLottie = initDownloadTipsLottie()
|
||||
@ -103,30 +104,10 @@ class GameItemUi(override val ctx: Context) : Ui {
|
||||
|
||||
topMargin = dip(-8)
|
||||
})
|
||||
add(gameNameTv, lParams(wrapContent, wrapContent) {
|
||||
constrainedWidth = true
|
||||
startToStartOf(mGameDesSpace)
|
||||
topToTopOf(iconIv)
|
||||
endToStartOf(gameSubtitleTv)
|
||||
bottomToTopOf(mGameDesSpace)
|
||||
|
||||
verticalChainStyle = packed
|
||||
horizontalChainStyle = packed
|
||||
horizontalBias = 0F
|
||||
constrainedWidth = true
|
||||
})
|
||||
add(serverTypeTv, lParams(wrapContent, wrapContent) {
|
||||
startToEndOf(gameNameTv)
|
||||
topToTopOf(gameNameTv)
|
||||
bottomToBottomOf(gameNameTv)
|
||||
endToEndOf(mGameDesSpace)
|
||||
|
||||
startMargin = dip(4)
|
||||
})
|
||||
add(mGameDesSpace, lParams(0, dip(28)) {
|
||||
startToEndOf(iconIv, dip(12))
|
||||
endToStartOf(downloadTv, dip(8))
|
||||
topToBottomOf(gameNameTv)
|
||||
topToBottomOf(gameNameContainer)
|
||||
bottomToTopOf(gameTagContainer)
|
||||
})
|
||||
add(gameRatingTv, lParams(wrapContent, wrapContent) {
|
||||
@ -158,22 +139,14 @@ class GameItemUi(override val ctx: Context) : Ui {
|
||||
endToEndOf(mGameDesSpace)
|
||||
orientation = LinearLayout.HORIZONTAL
|
||||
})
|
||||
add(gameSubtitleTv, lParams(wrapContent, dip(14)) {
|
||||
startToEndOf(gameNameTv)
|
||||
topToTopOf(gameNameTv)
|
||||
bottomToBottomOf(gameNameTv)
|
||||
add(gameNameContainer, lParams(0, wrapContent) {
|
||||
startToStartOf(mGameDesSpace)
|
||||
topToTopOf(iconIv)
|
||||
endToEndOf(mGameDesSpace)
|
||||
bottomToTopOf(mGameDesSpace)
|
||||
|
||||
startMargin = dip(4)
|
||||
})
|
||||
add(adLabelTv, lParams(dip(21), dip(14)) {
|
||||
startToEndOf(gameSubtitleTv)
|
||||
topToTopOf(gameSubtitleTv)
|
||||
bottomToBottomOf(gameSubtitleTv)
|
||||
endToEndOf(mGameDesSpace)
|
||||
horizontalBias = 0F
|
||||
|
||||
startMargin = dip(4)
|
||||
orientation = LinearLayout.HORIZONTAL
|
||||
verticalChainStyle = packed
|
||||
})
|
||||
}
|
||||
|
||||
@ -183,7 +156,21 @@ class GameItemUi(override val ctx: Context) : Ui {
|
||||
}
|
||||
}
|
||||
|
||||
private fun initGameNameTv() = NoEllipsizeSpaceTextView(ctx).apply {
|
||||
private fun initGameNameContainer() = LinearLayout(ctx).apply {
|
||||
gravity = Gravity.CENTER_VERTICAL
|
||||
add(gameNameTv, lParams(wrapContent, wrapContent) {})
|
||||
add(gameSubtitleTv, lParams(wrapContent, dip(14)) {
|
||||
startMargin = dip(4)
|
||||
})
|
||||
add(serverTypeTv, lParams(wrapContent, wrapContent) {
|
||||
startMargin = dip(4)
|
||||
})
|
||||
add(adLabelTv, lParams(dip(21), dip(14)) {
|
||||
startMargin = dip(4)
|
||||
})
|
||||
}
|
||||
|
||||
private fun initGameNameTv() = textView {
|
||||
id = R.id.game_name
|
||||
setSingleLine()
|
||||
includeFontPadding = false
|
||||
@ -299,11 +286,7 @@ class GameItemUi(override val ctx: Context) : Ui {
|
||||
gravity = Gravity.CENTER
|
||||
text = "展开"
|
||||
setTextColor(ContextCompat.getColor(context, R.color.white))
|
||||
setDrawableEnd(
|
||||
VectorDrawableCompat.create(
|
||||
resources, R.drawable.ic_jump_universal, null
|
||||
)
|
||||
)
|
||||
setDrawableEnd(AppCompatResources.getDrawable(context, R.drawable.ic_jump_universal))
|
||||
compoundDrawablePadding = dip(2)
|
||||
visibility = View.GONE
|
||||
}
|
||||
|
||||
@ -3,7 +3,6 @@ package com.gh.gamecenter.game.vertical
|
||||
import android.content.Context
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.view.ViewGroup
|
||||
import androidx.constraintlayout.widget.ConstraintSet
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.gh.common.databind.BindingAdapters
|
||||
import com.gh.common.util.DownloadItemUtils
|
||||
@ -26,6 +25,7 @@ class GameVerticalAdapter(
|
||||
|
||||
private val mMaxWidth = mContext.resources.displayMetrics.widthPixels
|
||||
private var countAndKey: Pair<Int, String>? = null
|
||||
private var mDarkMode = DarkModeUtils.isDarkModeOn(context)
|
||||
|
||||
init {
|
||||
var dataIds = ""
|
||||
@ -90,23 +90,14 @@ class GameVerticalAdapter(
|
||||
BindingAdapters.setGameTags(gameTagContainer, gameEntity)
|
||||
GameItemViewHolder.initServerType(gameNameTv, serverTypeTv, gameEntity)
|
||||
gameDesTv.text = gameEntity.decoratedDes
|
||||
adLabelTv.goneIf(!gameEntity.adIconActive)
|
||||
GameItemViewHolder.initGameSubtitle(gameEntity, gameSubtitleTv, mGameDesSpace)
|
||||
ConstraintSet().apply {
|
||||
clone(root)
|
||||
connect(
|
||||
R.id.game_name,
|
||||
ConstraintSet.END,
|
||||
if (gameEntity.serverLabel != null && !gameEntity.advanceDownload) R.id.game_server_type else R.id.gameSubtitleTv,
|
||||
ConstraintSet.START
|
||||
)
|
||||
connect(
|
||||
R.id.adLabelTv,
|
||||
ConstraintSet.START,
|
||||
if (gameEntity.adIconActive && gameEntity.serverLabel != null && !gameEntity.advanceDownload) R.id.game_server_type else R.id.gameSubtitleTv,
|
||||
ConstraintSet.END
|
||||
)
|
||||
}.applyTo(root)
|
||||
GameItemViewHolder.initGameSubtitleAndAdLabel(
|
||||
gameEntity,
|
||||
gameSubtitleTv,
|
||||
gameNameContainer,
|
||||
gameNameTv,
|
||||
gameEntity.adIconActive,
|
||||
adLabelTv
|
||||
)
|
||||
|
||||
var gameRatingPaddingEnd = 0
|
||||
var gameRatingDrawableStart: Drawable? = null
|
||||
@ -172,8 +163,12 @@ class GameVerticalAdapter(
|
||||
}
|
||||
|
||||
mSubjectEntity = updateData
|
||||
if (countAndKey?.first == updateData.data?.size && countAndKey?.second != dataIds) { // 数量不变,内容发生改变
|
||||
if ((countAndKey?.first == updateData.data?.size && countAndKey?.second != dataIds) || mDarkMode != DarkModeUtils.isDarkModeOn(
|
||||
mContext
|
||||
)
|
||||
) { // 数量不变,内容发生改变
|
||||
notifyItemRangeChanged(0, itemCount)
|
||||
mDarkMode = DarkModeUtils.isDarkModeOn(mContext)
|
||||
} else if (countAndKey?.first != updateData.data?.size) { // 数量发生改变
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
|
||||
@ -563,7 +563,6 @@ open class GameCollectionDetailAdapter(
|
||||
|
||||
inner class GameCollectionGameItemViewHolder(val binding: GameCollectionGameItemBinding) :
|
||||
RecyclerView.ViewHolder(binding.root) {
|
||||
|
||||
fun bindView(gameEntity: GameEntity, position: Int, isLast: Boolean) {
|
||||
binding.run {
|
||||
container.background = R.drawable.reuse_listview_item_style.toDrawable(mContext)
|
||||
@ -594,7 +593,7 @@ open class GameCollectionDetailAdapter(
|
||||
)
|
||||
gameDes.text = gameEntity.decoratedDes
|
||||
recommendStar.rating = gameEntity.recommendStar.toFloat()
|
||||
GameItemViewHolder.initGameSubtitle(gameEntity, gameSubtitleTv, gameDesSpace, root)
|
||||
GameItemViewHolder.initGameSubtitleAndAdLabel(gameEntity, gameSubtitleTv)
|
||||
}
|
||||
root.setPadding(
|
||||
16F.dip2px(),
|
||||
|
||||
@ -63,6 +63,7 @@ import com.gh.gamecenter.feature.entity.TagStyleEntity
|
||||
import com.gh.gamecenter.feature.exposure.ExposureEvent
|
||||
import com.gh.gamecenter.feature.exposure.ExposureSource
|
||||
import com.gh.gamecenter.feature.utils.ApkActiveUtils
|
||||
import com.gh.gamecenter.forum.detail.ForumDetailActivity
|
||||
import com.gh.gamecenter.gamedetail.cloudarchive.CloudArchiveFragment
|
||||
import com.gh.gamecenter.gamedetail.desc.DescFragment
|
||||
import com.gh.gamecenter.gamedetail.dialog.GameBigEventDialog
|
||||
@ -131,6 +132,7 @@ class GameDetailFragment : ToolbarFragment(), IScrollable {
|
||||
private var mRecommendPopupEntity: RecommendPopupEntity? = null
|
||||
private var mTabClickEvent: Pair<Long, String> = Pair(0L, "")
|
||||
private var mContentCardServerVp: ViewPager2? = null
|
||||
private var mIsPlayingWhenPause = false // 判断执行onPause时视频是否在播放中
|
||||
|
||||
private lateinit var mBinding: FragmentGamedetailBinding
|
||||
private lateinit var mVideoBinding: PieceGameDetailVideoBinding
|
||||
@ -408,7 +410,7 @@ class GameDetailFragment : ToolbarFragment(), IScrollable {
|
||||
savedInstanceState?.let { mDestinationTab = it.getInt(LAST_SELECTED_POSITION) }
|
||||
mBinding.reuseNoneData.reuseNoneDataTv.text = "页面不见了"
|
||||
mBodyBinding.gamedetailVp.setScrollable(true)
|
||||
mBodyBinding.gamedetailVp.offscreenPageLimit = 3
|
||||
mBodyBinding.gamedetailVp.offscreenPageLimit = 5
|
||||
|
||||
mMaxWidth = resources.displayMetrics.widthPixels - DisplayUtils.dip2px(40f)
|
||||
|
||||
@ -441,27 +443,13 @@ class GameDetailFragment : ToolbarFragment(), IScrollable {
|
||||
mBodyBinding.gamedetailVp.doOnPageSelected { position ->
|
||||
mBinding.gamedetailKaifuHint.visibleIf(mIsShowKaifuHint && position == INDEX_TRENDES)
|
||||
|
||||
if (mFirstTimeSelected) {
|
||||
when (position) {
|
||||
INDEX_DESC -> MtaHelper.onEvent("游戏详情_新", "默认[详情]", mGameEntity!!.name)
|
||||
// INDEX_TRENDES -> MtaHelper.onEvent("游戏详情_新", "默认[专区]", mGameEntity!!.name)
|
||||
// else -> MtaHelper.onEvent("游戏详情_新", "默认[评论]", mGameEntity!!.name)
|
||||
}
|
||||
mFirstTimeSelected = false
|
||||
} else {
|
||||
// 这个统计有歧义,当前统计包含左右滑动的选择
|
||||
when (position) {
|
||||
INDEX_DESC -> MtaHelper.onEvent("游戏详情_新", "点击[详情]", mGameEntity!!.name)
|
||||
INDEX_TRENDES -> MtaHelper.onEvent("游戏详情_新", "点击[专区]", mGameEntity!!.name)
|
||||
INDEX_RATING -> MtaHelper.onEvent("游戏详情_新", "点击[评论]", mGameEntity!!.name)
|
||||
INDEX_BBS -> MtaHelper.onEvent("游戏详情_新", "点击[论坛]", mGameEntity!!.name)
|
||||
}
|
||||
}
|
||||
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
|
||||
?: ""
|
||||
)
|
||||
|
||||
if (mNewGameDetailEntity?.bbsTab != null
|
||||
&& position == mTabTitleList.size - 1
|
||||
&& mTabTitleList.contains(getString(R.string.game_detail_bbs))
|
||||
) {
|
||||
if (mNewGameDetailEntity?.bbsTab != null && position == bbsPosition) {
|
||||
DirectUtils.directToLinkPage(
|
||||
requireContext(),
|
||||
mNewGameDetailEntity?.bbsTab!!,
|
||||
@ -474,6 +462,22 @@ class GameDetailFragment : ToolbarFragment(), IScrollable {
|
||||
mBodyBinding.gamedetailVp.currentItem = mCurVpPosition
|
||||
}
|
||||
}, 200)
|
||||
} else if (mNewGameDetailEntity?.zone != null && position == trendsPosition && mNewGameDetailEntity?.bbsTab != null) {
|
||||
// 跳转论坛-专区
|
||||
mNewGameDetailEntity?.bbsTab?.link?.let {
|
||||
startActivity(
|
||||
ForumDetailActivity.getTrendsIntent(
|
||||
requireContext(),
|
||||
it,
|
||||
"游戏详情"
|
||||
)
|
||||
)
|
||||
}
|
||||
mBodyBinding.gamedetailVp.postDelayed({
|
||||
if (mBodyBinding.gamedetailVp.currentItem == trendsPosition) {
|
||||
mBodyBinding.gamedetailVp.currentItem = mCurVpPosition
|
||||
}
|
||||
}, 200)
|
||||
} else {
|
||||
mCurVpPosition = position
|
||||
}
|
||||
@ -552,8 +556,8 @@ class GameDetailFragment : ToolbarFragment(), IScrollable {
|
||||
lastPosX = layout.getSecondaryHorizontal(text.length)
|
||||
}
|
||||
var remainWidth = (width - lastPosX).toInt()
|
||||
val tagMaxWidth =
|
||||
if (lineCount == 2 && layout.getEllipsisCount(1) == 0) remainWidth - 4F.dip2px() else width
|
||||
val isFullGameName = (lineCount == 2 && layout.getEllipsisCount(1) == 0)
|
||||
val tagMaxWidth = if (isFullGameName) remainWidth - 4F.dip2px() else width
|
||||
val tagLayout = FrameLayout(context)
|
||||
val tagView = TextView(context).apply {
|
||||
layoutParams = FrameLayout.LayoutParams(FrameLayout.LayoutParams.WRAP_CONTENT, 14F.dip2px())
|
||||
@ -581,7 +585,7 @@ class GameDetailFragment : ToolbarFragment(), IScrollable {
|
||||
}
|
||||
}
|
||||
tagView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED)
|
||||
if (tagView.layout.getEllipsisCount(0) > 0 && tagView.maxWidth != width) {
|
||||
if (tagView.layout.getEllipsisCount(0) > 0 && !isFullGameName) {
|
||||
tagView.maxWidth = width
|
||||
tagView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED)
|
||||
}
|
||||
@ -720,7 +724,7 @@ class GameDetailFragment : ToolbarFragment(), IScrollable {
|
||||
|
||||
initViewPage(data)
|
||||
|
||||
if (data.contentCard.size > 1 && mGameEntity?.shouldUseMirrorInfo() == false) {
|
||||
if (data.isShowContentCard(mGameEntity)) {
|
||||
initGameContentCard(data.contentCard)
|
||||
}
|
||||
|
||||
@ -830,7 +834,18 @@ class GameDetailFragment : ToolbarFragment(), IScrollable {
|
||||
@SuppressLint("ClickableViewAccessibility")
|
||||
private fun initViewPage(data: NewGameDetailEntity) {
|
||||
val scrollToLibao = arguments?.getBoolean(EntranceConsts.KEY_SCROLL_TO_LIBAO) ?: false
|
||||
val scrollToServer = arguments?.getBoolean(EntranceConsts.KEY_SCROLL_TO_SERVER) ?: false
|
||||
var scrollToServer = arguments?.getBoolean(EntranceConsts.KEY_SCROLL_TO_SERVER) ?: false
|
||||
|
||||
// 内容卡片包含开服表时不跳转详情开服表
|
||||
if (scrollToServer) {
|
||||
data.contentCard.forEach {
|
||||
if (it.type == "func_server" && data.isShowContentCard(mGameEntity)) {
|
||||
scrollToServer = false
|
||||
contentCardClick.invoke(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (scrollToLibao || scrollToServer) {
|
||||
mBodyBinding.gamedetailAppbar.setExpanded(false, true)
|
||||
}
|
||||
@ -857,11 +872,23 @@ class GameDetailFragment : ToolbarFragment(), IScrollable {
|
||||
mFragmentsList.add(descFragment)
|
||||
mTabTitleList.add(getString(R.string.game_detail_desc))
|
||||
|
||||
if (data.showComment) {
|
||||
val ratingFragment = childFragmentManager.findFragmentByTag("${tag}${INDEX_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))
|
||||
}
|
||||
|
||||
data.zone?.let {
|
||||
data.contentCard.forEach { contentCard ->
|
||||
if (data.contentCard.size > 1 && contentCard.type == "func_zone" && mGameEntity?.shouldUseMirrorInfo() == false) return@let
|
||||
if (contentCard.type == "func_zone" && data.isShowContentCard(mGameEntity)) return@let
|
||||
}
|
||||
if (it.style == "link") {//显示web页面
|
||||
if (data.bbsTab != null && mGameEntity?.shouldUseMirrorInfo() == false) {
|
||||
mFragmentsList.add(Fragment())
|
||||
} else if (it.style == "link") {
|
||||
//显示web页面
|
||||
val webFragment = childFragmentManager.findFragmentByTag("${tag}${INDEX_TRENDES}") ?: WebFragment()
|
||||
val webBundle = Bundle()
|
||||
webBundle.putString(EntranceConsts.KEY_ENTRANCE, "游戏专区")
|
||||
@ -874,7 +901,6 @@ class GameDetailFragment : ToolbarFragment(), IScrollable {
|
||||
fuliFragment.arguments = bundle
|
||||
mFragmentsList.add(fuliFragment)
|
||||
}
|
||||
|
||||
if (!TextUtils.isEmpty(it.customName)) {
|
||||
mTabTitleList.add(it.customName)
|
||||
} else {
|
||||
@ -898,15 +924,6 @@ class GameDetailFragment : ToolbarFragment(), IScrollable {
|
||||
)
|
||||
}
|
||||
|
||||
if (data.showComment) {
|
||||
val ratingFragment = childFragmentManager.findFragmentByTag("${tag}${INDEX_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))
|
||||
}
|
||||
|
||||
var isShowBbs = true
|
||||
if (data.bbsTab != null) {
|
||||
data.contentCard.forEach { contentCard ->
|
||||
@ -939,7 +956,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 == INDEX_ARCHIVE) {
|
||||
if (data.showArchive && i == getTabPositionFromTabName(getString(R.string.game_detail_cloud_archive))) {
|
||||
tab.customView = getArchiveTabView(tabTitle)
|
||||
tab.view.run {
|
||||
clipChildren = false
|
||||
@ -1064,7 +1081,13 @@ class GameDetailFragment : ToolbarFragment(), IScrollable {
|
||||
}
|
||||
|
||||
override fun onItemClickListener(tag: TagStyleEntity) {
|
||||
NewLogUtils.logGameDetailTagClick(mGameEntity?.id ?: "", mGameEntity?.name ?: "", tag.id, tag.name)
|
||||
NewLogUtils.logGameDetailTagClick(
|
||||
mGameEntity?.id ?: "",
|
||||
mGameEntity?.name ?: "",
|
||||
tag.id,
|
||||
tag.name,
|
||||
tag.isTop
|
||||
)
|
||||
MtaHelper.onEvent("游戏详情_新", "点击标签", mViewModel.game?.name ?: "")
|
||||
requireContext().startActivity(
|
||||
TagsActivity.getIntent(requireContext(), tag.name, tag.name, mEntrance, "游戏介绍")
|
||||
@ -1373,6 +1396,7 @@ class GameDetailFragment : ToolbarFragment(), IScrollable {
|
||||
.setSeekRatio(1f)
|
||||
.setUrl(topVideo.url)
|
||||
.setCacheWithPlay(true)
|
||||
.setShowPauseCover(true)
|
||||
.setReleaseWhenLossAudio(false)
|
||||
.setVideoAllCallBack(object : GSYSampleCallBack() {
|
||||
override fun onQuitFullscreen(url: String?, vararg objects: Any) {
|
||||
@ -1751,39 +1775,18 @@ class GameDetailFragment : ToolbarFragment(), IScrollable {
|
||||
) {
|
||||
performJumpContentCard("func_zone")
|
||||
} else {
|
||||
mBodyBinding.gamedetailVp.currentItem = position
|
||||
}
|
||||
}
|
||||
INDEX_RATING -> {
|
||||
//跳转评论Tab需要判断是否有专区Tab和云存档Tab
|
||||
val zoneEntity = mNewGameDetailEntity?.zone
|
||||
val hasZone = mTabTitleList.contains(getString(R.string.game_detail_dongtai))
|
||||
|| mTabTitleList.contains(zoneEntity?.customName)
|
||||
val hasArchive = mTabTitleList.contains(getString(R.string.game_detail_cloud_archive))
|
||||
val skipPosition = when {
|
||||
hasZone && hasArchive -> INDEX_RATING
|
||||
hasZone || hasArchive -> INDEX_RATING - 1
|
||||
else -> INDEX_RATING - 2
|
||||
}
|
||||
if (mTabTitleList.contains(getString(R.string.game_detail_comment))) {
|
||||
mBodyBinding.gamedetailVp.currentItem = skipPosition
|
||||
mBodyBinding.gamedetailVp.currentItem = getTabPositionFromTabName(
|
||||
if (mNewGameDetailEntity?.zone?.customName.isNullOrEmpty()) getString(R.string.game_detail_dongtai) else mNewGameDetailEntity?.zone?.customName
|
||||
?: ""
|
||||
)
|
||||
}
|
||||
}
|
||||
INDEX_BBS -> {
|
||||
if (!mTabTitleList.contains(getString(R.string.game_detail_bbs))) {
|
||||
performJumpContentCard("func_bbs")
|
||||
} else {
|
||||
//跳转论坛tab需要判断是否有评论Tab、云存档Tab专区Tab
|
||||
val zoneEntity = mNewGameDetailEntity?.zone
|
||||
val hasZone = mTabTitleList.contains(getString(R.string.game_detail_dongtai))
|
||||
|| mTabTitleList.contains(zoneEntity?.customName)
|
||||
val hasArchive = mTabTitleList.contains(getString(R.string.game_detail_cloud_archive))
|
||||
val hasRatting = mTabTitleList.contains(getString(R.string.game_detail_comment))
|
||||
var skipPosition = INDEX_BBS
|
||||
if (!hasZone) skipPosition--
|
||||
if (!hasArchive) skipPosition--
|
||||
if (!hasRatting) skipPosition--
|
||||
mBodyBinding.gamedetailVp.currentItem = skipPosition
|
||||
mBodyBinding.gamedetailVp.currentItem =
|
||||
getTabPositionFromTabName(getString(R.string.game_detail_bbs))
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
@ -1794,8 +1797,7 @@ class GameDetailFragment : ToolbarFragment(), IScrollable {
|
||||
|
||||
private fun performJumpContentCard(type: String) {
|
||||
val entity = mNewGameDetailEntity?.contentCard?.find { it.type == type }
|
||||
if ((mNewGameDetailEntity?.contentCard?.size ?: 0) > 1
|
||||
&& mGameEntity?.shouldUseMirrorInfo() == false
|
||||
if (mNewGameDetailEntity?.isShowContentCard(mGameEntity) == true
|
||||
&& entity != null
|
||||
) {
|
||||
contentCardClick(entity)
|
||||
@ -1803,6 +1805,9 @@ class GameDetailFragment : ToolbarFragment(), IScrollable {
|
||||
}
|
||||
|
||||
private fun logTabClick(position: Int) {
|
||||
// 特殊处理延时选中 tab 时可能 fragment 已被移除的情况
|
||||
if (!isAdded) return
|
||||
|
||||
val entrance = if (mEntrance.contains("论坛详情")) "论坛" else "游戏"
|
||||
mGameEntity?.run {
|
||||
when (getTabContentForReal(position)) {
|
||||
@ -1840,7 +1845,7 @@ class GameDetailFragment : ToolbarFragment(), IScrollable {
|
||||
/**
|
||||
* 获取真实的 tab 内容类型
|
||||
* @param position tab 的位置
|
||||
* @return 真实的
|
||||
* @return 真实的 tab 类型
|
||||
*/
|
||||
private fun getTabContentForReal(position: Int): String {
|
||||
return when (mTabTitleList[position]) {
|
||||
@ -1859,6 +1864,15 @@ class GameDetailFragment : ToolbarFragment(), IScrollable {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 tab 的位置
|
||||
* @param tabName tab 名字
|
||||
* @return tab 的真实位置
|
||||
*/
|
||||
private fun getTabPositionFromTabName(tabName: String): Int {
|
||||
return mTabTitleList.indexOf(tabName)
|
||||
}
|
||||
|
||||
private fun handleTabTouchEvent(title: String) {
|
||||
if (title == mTabClickEvent.second && System.currentTimeMillis() - mTabClickEvent.first < 300) {
|
||||
val fragment = mFragmentsList[mBodyBinding.gamedetailVp.currentItem]
|
||||
@ -2092,7 +2106,8 @@ class GameDetailFragment : ToolbarFragment(), IScrollable {
|
||||
|
||||
private fun updateArchiveTabUI() {
|
||||
mBodyBinding.tabLayout.run {
|
||||
getTabAt(INDEX_ARCHIVE)?.customView?.findViewById<ImageView>(R.id.newIv)?.visibility = View.VISIBLE
|
||||
val archivePosition = getTabPositionFromTabName(getString(R.string.game_detail_cloud_archive))
|
||||
getTabAt(archivePosition)?.customView?.findViewById<ImageView>(R.id.newIv)?.visibility = View.VISIBLE
|
||||
}
|
||||
}
|
||||
|
||||
@ -2124,7 +2139,7 @@ class GameDetailFragment : ToolbarFragment(), IScrollable {
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
if (!mIsPauseTopVideo) {
|
||||
if (!mIsPauseTopVideo && mIsPlayingWhenPause) {
|
||||
resumeVideo()
|
||||
}
|
||||
if (mGameEntity != null && (mGameEntity!!.getApk().size == 1 || mGameEntity!!.isReservable)) {
|
||||
@ -2139,8 +2154,12 @@ class GameDetailFragment : ToolbarFragment(), IScrollable {
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
pauseVideo()
|
||||
if (mViewModel.displayTopVideo) {
|
||||
mVideoBinding.player.postDelayed({
|
||||
mVideoBinding.player.showFullPauseBitmap()
|
||||
}, 50)
|
||||
mIsPlayingWhenPause = CustomManager.getCustomManager(mVideoBinding.player.getKey()).isPlaying
|
||||
pauseVideo()
|
||||
val currentPosition = mVideoBinding.player.getCurrentPosition()
|
||||
val topVideo = mNewGameDetailEntity?.topVideo
|
||||
if (topVideo != null) {
|
||||
@ -2270,7 +2289,7 @@ class GameDetailFragment : ToolbarFragment(), IScrollable {
|
||||
mBinding.detailLlBottom.detailLlBottom.setBackgroundColor(R.color.background.toColor(requireContext()))
|
||||
updateToolbarStyle(!mViewModel.displayTopVideo || mBodyBinding.gamedetailThumbSmall.visibility == View.VISIBLE)
|
||||
mViewModel.gameDetailLiveData.value?.data?.let {
|
||||
if (it.contentCard.size > 1 && mGameEntity?.shouldUseMirrorInfo() == false) {
|
||||
if (it.isShowContentCard(mGameEntity)) {
|
||||
initGameContentCard(it.contentCard)
|
||||
}
|
||||
}
|
||||
@ -2286,9 +2305,9 @@ class GameDetailFragment : ToolbarFragment(), IScrollable {
|
||||
|
||||
companion object {
|
||||
const val INDEX_DESC = 0
|
||||
const val INDEX_TRENDES = 1
|
||||
const val INDEX_RATING = 1
|
||||
const val INDEX_ARCHIVE = 2
|
||||
const val INDEX_RATING = 3
|
||||
const val INDEX_TRENDES = 3
|
||||
const val INDEX_BBS = 4
|
||||
|
||||
const val TAB_DESC = "详情"
|
||||
|
||||
@ -25,6 +25,7 @@ import com.gh.gamecenter.core.utils.SPUtils
|
||||
import com.gh.gamecenter.core.utils.UrlFilterUtils
|
||||
import com.gh.gamecenter.entity.*
|
||||
import com.gh.gamecenter.feature.entity.GameEntity
|
||||
import com.gh.gamecenter.feature.entity.SimpleGame
|
||||
import com.gh.gamecenter.feature.utils.ApkActiveUtils
|
||||
import com.gh.gamecenter.gamedetail.entity.BigEvent
|
||||
import com.gh.gamecenter.gamedetail.entity.CustomColumn
|
||||
@ -149,7 +150,7 @@ class GameDetailViewModel(
|
||||
|
||||
data.contentCard.forEach {
|
||||
// 显示开服内容卡片时,游戏详情-详情tab不显示“最新开服”
|
||||
if (data.contentCard.size > 1 && it.type == "func_server" && game?.shouldUseMirrorInfo() == false) {
|
||||
if (it.type == "func_server" && data.isShowContentCard(game)) {
|
||||
removeLatestServerIfNeeded(data)
|
||||
return@forEach
|
||||
}
|
||||
@ -162,8 +163,12 @@ class GameDetailViewModel(
|
||||
// 初始化礼包按钮状态
|
||||
for (entity in data.detailEntity) {
|
||||
if (entity.type == "libao") {
|
||||
val simpleGame = SimpleGame(gameId, mName = game?.name)
|
||||
if (entity.libao != null) {
|
||||
loadLiBaoStatus(data, entity.libao!!)
|
||||
for (libaoEntity in entity.libao!!) {
|
||||
libaoEntity.game = simpleGame
|
||||
}
|
||||
}
|
||||
break
|
||||
}
|
||||
@ -247,6 +252,12 @@ class GameDetailViewModel(
|
||||
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
|
||||
}
|
||||
@ -301,6 +312,8 @@ class GameDetailViewModel(
|
||||
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 ?: ""
|
||||
}
|
||||
|
||||
@ -25,13 +25,12 @@ import com.gh.gamecenter.core.iinterface.IScrollable
|
||||
import com.gh.gamecenter.core.utils.MtaHelper
|
||||
import com.gh.gamecenter.core.utils.SPUtils
|
||||
import com.gh.gamecenter.databinding.FragmentDescBinding
|
||||
import com.gh.gamecenter.feature.entity.GameEntity
|
||||
import com.gh.gamecenter.entity.LibaoEntity
|
||||
import com.gh.gamecenter.entity.RatingComment
|
||||
import com.gh.gamecenter.eventbus.EBScroll
|
||||
import com.gh.gamecenter.eventbus.EBTypeChange
|
||||
import com.gh.gamecenter.feature.entity.GameEntity
|
||||
import com.gh.gamecenter.gamedetail.GameDetailFragment
|
||||
import com.gh.gamecenter.gamedetail.GameDetailFragment.Companion.OPEN_APPBAR
|
||||
import com.gh.gamecenter.gamedetail.GameDetailFragment.Companion.SKIP_DESC
|
||||
import com.gh.gamecenter.gamedetail.GameDetailViewModel
|
||||
import com.gh.gamecenter.gamedetail.entity.DetailEntity
|
||||
@ -43,7 +42,6 @@ import io.reactivex.disposables.Disposable
|
||||
import org.greenrobot.eventbus.EventBus
|
||||
import org.greenrobot.eventbus.Subscribe
|
||||
import org.greenrobot.eventbus.ThreadMode
|
||||
import kotlin.math.abs
|
||||
|
||||
class DescFragment : BaseFragment<Any>(), IScrollable {
|
||||
|
||||
@ -190,9 +188,6 @@ class DescFragment : BaseFragment<Any>(), IScrollable {
|
||||
super.onScrolled(recyclerView, dx, dy)
|
||||
val firstCompletelyVisibleItemPosition = mLayoutManager!!.findFirstCompletelyVisibleItemPosition()
|
||||
val lastCompletelyVisibleItemPosition = mLayoutManager!!.findLastCompletelyVisibleItemPosition()
|
||||
if (firstCompletelyVisibleItemPosition == 0 && abs(dy) > 10) {
|
||||
EventBus.getDefault().post(EBReuse(OPEN_APPBAR))
|
||||
}
|
||||
|
||||
for (i in firstCompletelyVisibleItemPosition..lastCompletelyVisibleItemPosition) {
|
||||
if (i < 0) continue
|
||||
|
||||
@ -59,11 +59,30 @@ class GameLibaoAdapter(
|
||||
when (holder) {
|
||||
is LibaoViewHolder -> {
|
||||
val libaoEntity = libaos[position]
|
||||
val isTypeCopy = libaoEntity.receiveMethod == "copy"
|
||||
|
||||
holder.binding.libaoNameTv.text = libaoEntity.name
|
||||
holder.binding.contentTv.text = libaoEntity.content?.fromHtml()
|
||||
|
||||
//通用码礼包/或者还未添加礼包码时,不显示进度条,显示礼包码
|
||||
if (libaoEntity.universal || libaoEntity.status == "check") {
|
||||
if (isTypeCopy) {
|
||||
// 类型为复制,不需要登录也能直接领取
|
||||
holder.binding.libaoSchedulePb.visibility = View.GONE
|
||||
holder.binding.remainingTv.visibility = View.GONE
|
||||
holder.binding.libaoCodeTv.visibility = View.VISIBLE
|
||||
|
||||
val text = "兑换码:${libaoEntity.code}"
|
||||
holder.binding.libaoCodeTv.text = SpanBuilder(text).color(
|
||||
holder.binding.root.context,
|
||||
4,
|
||||
text.length,
|
||||
R.color.theme_font
|
||||
).build()
|
||||
holder.binding.copyLibaoCodeIv.visibility = View.VISIBLE
|
||||
holder.binding.copyLibaoCodeIv.setOnClickListener {
|
||||
holder.binding.receiveTv.performClick()
|
||||
}
|
||||
} else if (libaoEntity.universal || libaoEntity.status == "check") {
|
||||
//通用码礼包/或者还未添加礼包码时,不显示进度条,显示礼包码
|
||||
holder.binding.libaoSchedulePb.visibility = View.GONE
|
||||
holder.binding.remainingTv.visibility = View.GONE
|
||||
holder.binding.libaoCodeTv.visibility = View.VISIBLE
|
||||
@ -76,7 +95,7 @@ class GameLibaoAdapter(
|
||||
"ling" -> {
|
||||
holder.binding.libaoCodeTv.text = "礼包码:-"
|
||||
}
|
||||
"linged" -> {
|
||||
"linged", "repeatLing", "repeatLinged" -> {
|
||||
val size = libaoEntity.me?.userDataLibaoList?.size ?: 0
|
||||
val code = libaoEntity.me?.userDataLibaoList?.get(size - 1)?.code ?: ""
|
||||
val text = "礼包码:$code"
|
||||
@ -112,7 +131,7 @@ class GameLibaoAdapter(
|
||||
|
||||
initProgressUI(libaoEntity, holder)
|
||||
}
|
||||
"linged" -> {
|
||||
"linged", "repeatLing", "repeatLinged" -> {
|
||||
holder.binding.libaoSchedulePb.visibility = View.GONE
|
||||
holder.binding.remainingTv.visibility = View.GONE
|
||||
holder.binding.libaoCodeTv.visibility = View.VISIBLE
|
||||
@ -152,8 +171,12 @@ class GameLibaoAdapter(
|
||||
}
|
||||
}
|
||||
holder.itemView.setOnClickListener {
|
||||
listListener?.onListClick(it, position, libaoEntity)
|
||||
NewLogUtils.logGameDetailGiftClick(gameName, gameId, "礼包详情")
|
||||
if (isTypeCopy) {
|
||||
// do nothing
|
||||
} else {
|
||||
listListener?.onListClick(it, position, libaoEntity)
|
||||
NewLogUtils.logGameDetailGiftClick(gameName, gameId, "礼包详情")
|
||||
}
|
||||
}
|
||||
}
|
||||
is MoreViewHolder -> {
|
||||
|
||||
@ -6,10 +6,7 @@ import androidx.recyclerview.widget.RecyclerView
|
||||
import com.gh.common.databind.BindingAdapters
|
||||
import com.gh.gamecenter.GameDetailActivity
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.utils.dip2px
|
||||
import com.gh.gamecenter.common.utils.safelyGetInRelease
|
||||
import com.gh.gamecenter.common.utils.toBinding
|
||||
import com.gh.gamecenter.common.utils.toColor
|
||||
import com.gh.gamecenter.common.utils.*
|
||||
import com.gh.gamecenter.core.utils.MtaHelper
|
||||
import com.gh.gamecenter.core.utils.StringUtils
|
||||
import com.gh.gamecenter.databinding.ItemGameDetailRelatedVersionBinding
|
||||
@ -75,7 +72,7 @@ class GameRelatedVersionAdapter(
|
||||
exposureEventList.safelyGetInRelease(position)
|
||||
)
|
||||
}
|
||||
GameItemViewHolder.initGameSubtitle(gameEntity, holder.binding.gameSubtitleTv)
|
||||
GameItemViewHolder.initGameSubtitleAndAdLabel(gameEntity, holder.binding.gameSubtitleTv)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -10,14 +10,14 @@ import androidx.core.content.ContextCompat
|
||||
import androidx.core.os.bundleOf
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import com.gh.gamecenter.core.utils.DisplayUtils
|
||||
import com.gh.gamecenter.common.constant.EntranceConsts
|
||||
import com.gh.gamecenter.core.utils.MtaHelper
|
||||
import com.gh.common.util.NewLogUtils
|
||||
import com.gh.gamecenter.common.view.divider.HorizontalDividerItemDecoration
|
||||
import com.gh.download.dialog.DownloadDialog
|
||||
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.view.divider.HorizontalDividerItemDecoration
|
||||
import com.gh.gamecenter.core.utils.DisplayUtils
|
||||
import com.gh.gamecenter.core.utils.MtaHelper
|
||||
import com.gh.gamecenter.databinding.DialogGameTagsBinding
|
||||
import com.gh.gamecenter.feature.entity.TagStyleEntity
|
||||
import com.gh.gamecenter.tag.TagsActivity
|
||||
@ -77,7 +77,7 @@ class GameTagsDialog : BaseDialogFragment() {
|
||||
it.name, it.name, "", "游戏介绍"
|
||||
)
|
||||
)
|
||||
NewLogUtils.logGameDetailTagClick(mGameId, mGameName, it.id, it.name)
|
||||
NewLogUtils.logGameDetailTagClick(mGameId, mGameName, it.id, it.name, it.isTop)
|
||||
MtaHelper.onEvent("游戏标签弹窗", "进入标签", "${mGameName}+${it.name}")
|
||||
}
|
||||
}
|
||||
|
||||
@ -69,6 +69,27 @@ class DetailEntity(
|
||||
// 仅用于镜像
|
||||
@SerializedName("privacy_policy_url")
|
||||
var privacyPolicyUrl: String? = null,
|
||||
// 仅用于镜像
|
||||
@SerializedName("manufacturer_type")
|
||||
var manufacturerType: String = "",
|
||||
// 仅用于镜像
|
||||
var publisher: String = "",
|
||||
// 仅用于镜像
|
||||
var developer: String = "",
|
||||
// 仅用于镜像
|
||||
var supplier: String = "",
|
||||
// 仅用于镜像
|
||||
@SerializedName("credit_code")
|
||||
var creditCode: String = "",
|
||||
// 仅用于镜像
|
||||
@SerializedName("update_des")
|
||||
var updateDes: String = "",
|
||||
// 仅用于镜像
|
||||
@SerializedName("update_time")
|
||||
var updateTime: Long = 0,
|
||||
// 仅用于镜像
|
||||
@SerializedName("content_card_status")
|
||||
var contentCardStatus: String = "off", //on(生效)/off(不生效)
|
||||
|
||||
@SerializedName("detail_dialogs")
|
||||
var detailDialogs: ArrayList<GameEntity.Dialog> = arrayListOf(),
|
||||
@ -160,7 +181,7 @@ class UpdateContent(
|
||||
@SerializedName("history_apk_status")
|
||||
var historyApkStatus: String = "",
|
||||
@SerializedName("update_des")
|
||||
val updateDes: String = ""
|
||||
var updateDes: String = ""
|
||||
)
|
||||
|
||||
@Keep
|
||||
|
||||
@ -23,7 +23,7 @@ class NewGameDetailEntity(
|
||||
var event: BigEvent? = null,//游戏大事件
|
||||
@SerializedName("detail_dialogs")
|
||||
var detailDialogs: ArrayList<GameEntity.Dialog> = arrayListOf(),
|
||||
@SerializedName("tag_style")
|
||||
@SerializedName("new_tag_style")
|
||||
var tagStyle: ArrayList<TagStyleEntity> = ArrayList(),
|
||||
@SerializedName("detail_tab")
|
||||
var detailEntity: ArrayList<DetailEntity> = ArrayList(),
|
||||
@ -54,7 +54,11 @@ class NewGameDetailEntity(
|
||||
var showArchive: Boolean = false, //云存档开关
|
||||
@SerializedName("archive_tab")
|
||||
var archiveTab: ArchiveTab = ArchiveTab()
|
||||
)
|
||||
) {
|
||||
fun isShowContentCard(gameEntity: GameEntity?): Boolean {
|
||||
return contentCard.size > 1 && (gameEntity?.shouldUseMirrorInfo() == false || (gameEntity?.shouldUseMirrorInfo() == true && mirrorData?.contentCardStatus == "on"))
|
||||
}
|
||||
}
|
||||
|
||||
@Keep
|
||||
class Ranking(
|
||||
|
||||
@ -8,19 +8,19 @@ import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.ethanhua.skeleton.Skeleton
|
||||
import com.ethanhua.skeleton.ViewSkeletonScreen
|
||||
import com.gh.gamecenter.common.base.fragment.LazyFragment
|
||||
import com.gh.gamecenter.core.iinterface.IScrollable
|
||||
import com.gh.common.util.NewLogUtils
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.base.fragment.LazyFragment
|
||||
import com.gh.gamecenter.common.constant.EntranceConsts
|
||||
import com.gh.gamecenter.common.utils.*
|
||||
import com.gh.gamecenter.databinding.FragmentFuliBinding
|
||||
import com.gh.gamecenter.feature.entity.GameEntity
|
||||
import com.gh.gamecenter.common.eventbus.EBReuse
|
||||
import com.gh.gamecenter.common.mvvm.Status
|
||||
import com.gh.gamecenter.common.utils.*
|
||||
import com.gh.gamecenter.core.iinterface.IScrollable
|
||||
import com.gh.gamecenter.databinding.FragmentFuliBinding
|
||||
import com.gh.gamecenter.eventbus.EBTypeChange
|
||||
import com.gh.gamecenter.feature.entity.GameEntity
|
||||
import com.gh.gamecenter.gamedetail.GameDetailFragment
|
||||
import com.gh.gamecenter.gamedetail.GameDetailViewModel
|
||||
import com.gh.gamecenter.common.mvvm.Status
|
||||
import com.halo.assistant.HaloApp
|
||||
import org.greenrobot.eventbus.EventBus
|
||||
import org.greenrobot.eventbus.Subscribe
|
||||
@ -135,14 +135,6 @@ class FuLiFragment : LazyFragment(), IScrollable {
|
||||
}
|
||||
mBinding?.fmFuliRv?.layoutManager = layoutManager
|
||||
mBinding?.fmFuliRv?.addOnScrollListener(object : RecyclerView.OnScrollListener() {
|
||||
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
|
||||
super.onScrolled(recyclerView, dx, dy)
|
||||
val position = layoutManager!!.findFirstCompletelyVisibleItemPosition()
|
||||
if (position == 0 && Math.abs(dy) > 10) {
|
||||
EventBus.getDefault().post(EBReuse(GameDetailFragment.OPEN_APPBAR))
|
||||
}
|
||||
}
|
||||
|
||||
override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
|
||||
super.onScrollStateChanged(recyclerView, newState)
|
||||
if (newState == RecyclerView.SCROLL_STATE_DRAGGING) {
|
||||
|
||||
@ -438,6 +438,11 @@ class TopVideoView @JvmOverloads constructor(context: Context, attrs: AttributeS
|
||||
findViewById<LinearLayout>(R.id.errorContainer)?.visibility = View.GONE
|
||||
}
|
||||
|
||||
fun showFullPauseBitmap() {
|
||||
mThumbImageViewLayout.visibility = View.VISIBLE
|
||||
findViewById<ImageView>(R.id.thumbImage).setImageBitmap(mFullPauseBitmap)
|
||||
}
|
||||
|
||||
override fun changeUiToCompleteShow() {
|
||||
super.changeUiToCompleteShow()
|
||||
findViewById<LinearLayout>(R.id.errorContainer)?.visibility = View.GONE
|
||||
|
||||
14
app/src/main/java/com/gh/gamecenter/home/ExposureItemData.kt
Normal file
14
app/src/main/java/com/gh/gamecenter/home/ExposureItemData.kt
Normal file
@ -0,0 +1,14 @@
|
||||
package com.gh.gamecenter.home
|
||||
|
||||
import com.gh.gamecenter.feature.exposure.ExposureEvent
|
||||
|
||||
/**
|
||||
* @author : liujiarui
|
||||
* date : 2023/3/13
|
||||
* description : 曝光条目公共属性
|
||||
*/
|
||||
interface ExposureItemData {
|
||||
var exposureEvent: ExposureEvent?
|
||||
var exposureEventList: ArrayList<ExposureEvent>?
|
||||
var offset: Int // 偏移,供下面的实体用
|
||||
}
|
||||
@ -1,6 +1,7 @@
|
||||
package com.gh.gamecenter.home
|
||||
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.recyclerview.widget.DefaultItemAnimator
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
@ -17,7 +18,10 @@ import com.gh.gamecenter.common.baselist.LoadStatus
|
||||
import com.gh.gamecenter.common.constant.Constants
|
||||
import com.gh.gamecenter.common.constant.EntranceConsts
|
||||
import com.gh.gamecenter.common.eventbus.EBReuse
|
||||
import com.gh.gamecenter.common.utils.*
|
||||
import com.gh.gamecenter.common.utils.goneIf
|
||||
import com.gh.gamecenter.common.utils.observeNonNull
|
||||
import com.gh.gamecenter.common.utils.viewModelProvider
|
||||
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.utils.MD5Utils
|
||||
@ -33,6 +37,10 @@ import com.gh.gamecenter.fragment.HomeSearchToolWrapperViewModel
|
||||
import com.gh.gamecenter.fragment.MainWrapperFragment
|
||||
import com.gh.gamecenter.game.gallery.GameGallerySlideViewHolder
|
||||
import com.gh.gamecenter.home.slide.HomeSlideListAdapter
|
||||
import com.gh.gamecenter.home.test_v2.HomeGameTestV2ViewModel
|
||||
import com.gh.gamecenter.home.test_v2.HomeItemGameTestV2ViewHolder
|
||||
import com.gh.gamecenter.home.test_v2.HomeItemGameTestV2ViewHolderWatcher
|
||||
import com.gh.gamecenter.home.test_v2.addViewHolderWatcher
|
||||
import com.gh.gamecenter.home.video.ScrollCalculatorHelper
|
||||
import com.lightgame.download.DataWatcher
|
||||
import com.lightgame.download.DownloadEntity
|
||||
@ -42,6 +50,7 @@ import org.greenrobot.eventbus.ThreadMode
|
||||
class HomeFragment : LazyFragment() {
|
||||
|
||||
private lateinit var mViewModel: HomeViewModel
|
||||
private lateinit var mHomeGameTestV2ViewModel: HomeGameTestV2ViewModel
|
||||
private lateinit var mHomeSearchViewModel: HomeSearchToolWrapperViewModel
|
||||
private lateinit var mBinding: FragmentMainHomeBinding
|
||||
private lateinit var mLayoutManager: LinearLayoutManager
|
||||
@ -69,6 +78,8 @@ class HomeFragment : LazyFragment() {
|
||||
|
||||
override fun onFragmentFirstVisible() {
|
||||
mViewModel = viewModelProvider()
|
||||
mHomeGameTestV2ViewModel = viewModelProvider()
|
||||
mViewModel.setHomeGameTestV2DownloadStateUpdateHelper(mHomeGameTestV2ViewModel)
|
||||
mHomeSearchViewModel = viewModelProviderFromParent()
|
||||
mViewModel.homeOnlyWithoutOtherTab = arguments?.getInt(EntranceConsts.KEY_TAB_COUNT) == 1
|
||||
super.onFragmentFirstVisible()
|
||||
@ -86,7 +97,8 @@ class HomeFragment : LazyFragment() {
|
||||
reuseLoading.root.goneIf(loadStatus != LoadStatus.INIT_LOADING)
|
||||
}
|
||||
mListAdapter.setLoadStatus(it)
|
||||
if (it == LoadStatus.INIT_LOADED) {
|
||||
val startAdContainerView = requireActivity().findViewById<View>(R.id.startAdContainer)
|
||||
if (it == LoadStatus.INIT_LOADED && startAdContainerView == null) {
|
||||
AppExecutor.uiExecutor.executeWithDelay({
|
||||
scroll()
|
||||
mScrollCalculatorHelper.onScrollStateChanged(RecyclerView.SCROLL_STATE_IDLE)
|
||||
@ -96,14 +108,14 @@ class HomeFragment : LazyFragment() {
|
||||
mHomeSearchViewModel.homeDataLiveData.observe(this) {
|
||||
mViewModel.initData(it)
|
||||
}
|
||||
|
||||
mScrollCalculatorHelper = ScrollCalculatorHelper(mBinding.gameList, R.id.autoVideoView, 0)
|
||||
listenStartAdViewRemoved()
|
||||
}
|
||||
|
||||
override fun onRealLayoutInflated(inflatedView: View) {
|
||||
super.onRealLayoutInflated(inflatedView)
|
||||
|
||||
mBinding = FragmentMainHomeBinding.bind(inflatedView)
|
||||
mScrollCalculatorHelper = ScrollCalculatorHelper(mBinding.gameList, R.id.autoVideoView, 0)
|
||||
mBinding.gameRefresh.setColorSchemeColors(
|
||||
ContextCompat.getColor(
|
||||
requireContext(),
|
||||
@ -115,7 +127,14 @@ class HomeFragment : LazyFragment() {
|
||||
}
|
||||
mAutomaticLayoutManager = OffsetLinearLayoutManager(requireContext())
|
||||
mLayoutManager = mAutomaticLayoutManager
|
||||
mListAdapter = HomeFragmentAdapter(requireContext(), mViewModel, mLayoutManager) {
|
||||
mListAdapter = HomeFragmentAdapter(
|
||||
requireContext(),
|
||||
this,
|
||||
mViewModel,
|
||||
mHomeGameTestV2ViewModel,
|
||||
mLayoutManager,
|
||||
mScrollCalculatorHelper
|
||||
) {
|
||||
if (parentFragment is HomeSearchToolWrapperFragment) {
|
||||
(parentFragment as HomeSearchToolWrapperFragment).changeAppBarColor(it)
|
||||
}
|
||||
@ -124,7 +143,11 @@ class HomeFragment : LazyFragment() {
|
||||
(mBinding.gameList.itemAnimator as DefaultItemAnimator).supportsChangeAnimations = false
|
||||
mBinding.gameList.layoutManager = mLayoutManager
|
||||
mBinding.gameList.adapter = mListAdapter
|
||||
|
||||
//监听新游开测条目可见性变化
|
||||
mBinding.gameList.addViewHolderWatcher(
|
||||
HomeItemGameTestV2ViewHolder::class.java,
|
||||
HomeItemGameTestV2ViewHolderWatcher()
|
||||
)
|
||||
mBinding.gameList.addOnScrollListener(object : RecyclerView.OnScrollListener() {
|
||||
override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
|
||||
super.onScrollStateChanged(recyclerView, newState)
|
||||
@ -164,6 +187,30 @@ class HomeFragment : LazyFragment() {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 监听广告view被remove时再播放视频,否则会出现首页还未显示视频就开始播放了
|
||||
*/
|
||||
private fun listenStartAdViewRemoved() {
|
||||
val startAdContainerView = requireActivity().findViewById<View>(R.id.startAdContainer)
|
||||
val parentView = startAdContainerView?.parent as? ViewGroup
|
||||
|
||||
parentView?.setOnHierarchyChangeListener(object : ViewGroup.OnHierarchyChangeListener {
|
||||
override fun onChildViewRemoved(parent: View?, child: View?) {
|
||||
if (mViewModel.loadStatus.value == LoadStatus.INIT_LOADED && child == startAdContainerView) {
|
||||
AppExecutor.uiExecutor.executeWithDelay({
|
||||
scroll()
|
||||
mScrollCalculatorHelper.onScrollStateChanged(RecyclerView.SCROLL_STATE_IDLE)
|
||||
}, 100)
|
||||
parentView.setOnHierarchyChangeListener(null)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onChildViewAdded(parent: View?, child: View?) {
|
||||
//Do nothing
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private fun scroll() {
|
||||
val firstVisibleItem = mAutomaticLayoutManager.findFirstVisibleItemPosition()
|
||||
val lastVisibleItem = mAutomaticLayoutManager.findLastVisibleItemPosition()
|
||||
@ -187,35 +234,30 @@ class HomeFragment : LazyFragment() {
|
||||
}
|
||||
|
||||
private fun pauseVideo() {
|
||||
if (mScrollCalculatorHelper.currentPosition >= 0) {
|
||||
mScrollCalculatorHelper.currentPlayer?.resetDetailMask()
|
||||
mScrollCalculatorHelper.currentPlayer?.onVideoPause()
|
||||
val currentPosition = mScrollCalculatorHelper.currentPlayer?.getCurrentPosition() ?: 0L
|
||||
val topVideo =
|
||||
mViewModel.itemDataList.value?.safelyGetInRelease(mScrollCalculatorHelper.currentPosition)?.attachGame?.linkGame?.topVideo
|
||||
if (topVideo != null) {
|
||||
ScrollCalculatorHelper.savePlaySchedule(
|
||||
MD5Utils.getContentMD5(topVideo.url),
|
||||
currentPosition
|
||||
)
|
||||
val currentPlayer = mScrollCalculatorHelper.currentPlayer
|
||||
if (currentPlayer != null) {
|
||||
currentPlayer.resetDetailMask()
|
||||
currentPlayer.onVideoPause()
|
||||
val currentPosition = currentPlayer.getCurrentPosition()
|
||||
val videoUrl = currentPlayer.getUrl()
|
||||
if (videoUrl.isNotEmpty()) {
|
||||
ScrollCalculatorHelper.savePlaySchedule(MD5Utils.getContentMD5(videoUrl), currentPosition)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun resumeVideo() {
|
||||
if (mScrollCalculatorHelper.currentPlayer != null) {
|
||||
val topVideo =
|
||||
mViewModel.itemDataList.value?.safelyGetInRelease(mScrollCalculatorHelper.currentPosition)?.attachGame?.linkGame?.topVideo
|
||||
if (topVideo != null) {
|
||||
val position =
|
||||
ScrollCalculatorHelper.getPlaySchedule(MD5Utils.getContentMD5(topVideo.url))
|
||||
val currentPlayer = mScrollCalculatorHelper.currentPlayer
|
||||
if (currentPlayer != null) {
|
||||
val videoUrl = currentPlayer.getUrl()
|
||||
if (videoUrl.isNotEmpty()) {
|
||||
val position = ScrollCalculatorHelper.getPlaySchedule(MD5Utils.getContentMD5(videoUrl))
|
||||
//这里必须要延迟操作,否则会白屏
|
||||
mBaseHandler.postDelayed({
|
||||
if (position != 0L) {
|
||||
mScrollCalculatorHelper.currentPlayer?.seekTo(position)
|
||||
mScrollCalculatorHelper.currentPlayer?.onVideoResume(false)
|
||||
val topVideoVoiceStatus =
|
||||
SPUtils.getBoolean(Constants.SP_VIDEO_PLAY_MUTE, true)
|
||||
val topVideoVoiceStatus = SPUtils.getBoolean(Constants.SP_VIDEO_PLAY_MUTE, true)
|
||||
if (topVideoVoiceStatus) {
|
||||
mScrollCalculatorHelper.currentPlayer?.mute()
|
||||
} else {
|
||||
@ -233,7 +275,7 @@ class HomeFragment : LazyFragment() {
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
if (::mScrollCalculatorHelper.isInitialized) {
|
||||
mScrollCalculatorHelper.currentPlayer?.release()
|
||||
mScrollCalculatorHelper.release()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -4,6 +4,7 @@ import android.content.Context
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.constraintlayout.widget.ConstraintLayout
|
||||
import androidx.lifecycle.LifecycleOwner
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.gh.common.exposure.IExposable
|
||||
@ -36,8 +37,13 @@ import com.gh.gamecenter.home.amway.HomeAmwayListViewHolder
|
||||
import com.gh.gamecenter.home.discovercard.DiscoverCardGameAdapter
|
||||
import com.gh.gamecenter.home.discovercard.HomeDiscoverCardViewHolder
|
||||
import com.gh.gamecenter.home.gamecollection.HomeGameCollectionViewHolder
|
||||
import com.gh.gamecenter.home.horizontalslidevideo.HomeHorizontalSlideVideoAdapter
|
||||
import com.gh.gamecenter.home.slide.HomeSlideListAdapter
|
||||
import com.gh.gamecenter.home.slide.HomeSlideListViewHolder
|
||||
import com.gh.gamecenter.home.test_v2.HomeGameTestV2GameListRvAdapter
|
||||
import com.gh.gamecenter.home.test_v2.HomeGameTestV2ViewModel
|
||||
import com.gh.gamecenter.home.test_v2.HomeItemGameTestV2ViewHolder
|
||||
import com.gh.gamecenter.home.video.ScrollCalculatorHelper
|
||||
import com.gh.gamecenter.setting.SettingBridge
|
||||
import com.gh.vspace.HomeRecentVGameAdapter
|
||||
import com.gh.vspace.HomeRecentVGameViewHolder
|
||||
@ -47,8 +53,11 @@ import com.lightgame.download.DownloadEntity
|
||||
|
||||
class HomeFragmentAdapter(
|
||||
context: Context,
|
||||
private val lifecycleOwner: LifecycleOwner,
|
||||
val viewModel: HomeViewModel,
|
||||
private val mHomeGameTestV2ViewModel: HomeGameTestV2ViewModel,
|
||||
private val mLayoutManager: LinearLayoutManager,
|
||||
private val mScrollCalculatorHelper: ScrollCalculatorHelper,
|
||||
private val mCallback: (colorStr: Int) -> Unit
|
||||
) : DiffUtilAdapter<HomeItemData>(context), IExposable {
|
||||
|
||||
@ -150,6 +159,14 @@ class HomeFragmentAdapter(
|
||||
return oldItem.discoverCard == newItem.discoverCard
|
||||
}
|
||||
|
||||
if (oldItem?.gameTestV2Entity != null && newItem?.gameTestV2Entity != null) {
|
||||
return oldItem.gameTestV2Entity?.pageId == newItem.gameTestV2Entity?.pageId
|
||||
}
|
||||
|
||||
if (oldItem?.horizontalSlideVideo != null && newItem?.horizontalSlideVideo != null) {
|
||||
return oldItem.horizontalSlideVideo?.id == newItem.horizontalSlideVideo?.id
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
@ -175,6 +192,7 @@ class HomeFragmentAdapter(
|
||||
if (itemData.recentVGame != null) return RECENT_V_GAME
|
||||
if (itemData.discoverCard != null) return DISCOVER_CARD
|
||||
if (itemData.lineDivider != null) return DIVIDER_ITEM
|
||||
if (itemData.gameTestV2Entity != null) return COLUMN_TEST_V2
|
||||
if (itemData.unknownData != null) return UNKNOWN_ITEM
|
||||
|
||||
return mLegacyHomeFragmentAdapterAssistant.getLegacyItemType(itemData)
|
||||
@ -190,6 +208,7 @@ class HomeFragmentAdapter(
|
||||
DIVIDER_ITEM -> HomeDividerViewHolder(parent.toBinding())
|
||||
RECENT_V_GAME -> HomeRecentVGameViewHolder(parent.toBinding())
|
||||
DISCOVER_CARD -> HomeDiscoverCardViewHolder(parent.toBinding())
|
||||
COLUMN_TEST_V2 -> HomeItemGameTestV2ViewHolder(parent.toBinding(), mHomeGameTestV2ViewModel, lifecycleOwner)
|
||||
|
||||
FOOTER_ITEM -> FooterViewHolder(mLayoutInflater.inflate(R.layout.refresh_footerview, parent, false))
|
||||
UNKNOWN_ITEM -> ReuseViewHolder(mLayoutInflater.inflate(R.layout.home_unknown_item, parent, false))
|
||||
@ -221,8 +240,14 @@ class HomeFragmentAdapter(
|
||||
is HomeGameCollectionViewHolder -> bindGameCollection(holder, position)
|
||||
is HomeRecentVGameViewHolder -> bindRecentVGame(holder, position)
|
||||
is HomeDiscoverCardViewHolder -> bindDiscoverCard(holder, position)
|
||||
is HomeItemGameTestV2ViewHolder -> bindGameTestV2ViewHolder(holder, position)
|
||||
|
||||
else -> mLegacyHomeFragmentAdapterAssistant.bindLegacyViewHolder(holder, mDataList[position], position)
|
||||
else -> mLegacyHomeFragmentAdapterAssistant.bindLegacyViewHolder(
|
||||
holder,
|
||||
mDataList[position],
|
||||
position,
|
||||
mScrollCalculatorHelper
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@ -344,7 +369,7 @@ class HomeFragmentAdapter(
|
||||
val listExposureEventList = arrayListOf<ExposureEvent>()
|
||||
val spanCount = 3
|
||||
|
||||
val snapHelper = holder.bindView(discoverCard, "首页")
|
||||
val snapHelper = holder.bindView(discoverCard, "首页", position)
|
||||
|
||||
val exposureClosure: (Int) -> Unit = {
|
||||
val gameList = discoverCard.games
|
||||
@ -398,6 +423,12 @@ class HomeFragmentAdapter(
|
||||
}
|
||||
}
|
||||
|
||||
private fun bindGameTestV2ViewHolder(holder: HomeItemGameTestV2ViewHolder, position: Int) {
|
||||
val exposureItemData = mDataList.getOrNull(position)
|
||||
val data = exposureItemData?.gameTestV2Entity ?: return
|
||||
holder.bindData(data, exposureItemData, mBasicExposureSource, position)
|
||||
}
|
||||
|
||||
private fun bindFooterView(holder: FooterViewHolder) {
|
||||
holder.initFooterViewHolder(
|
||||
mLoadStatus == LoadStatus.LIST_LOADING,
|
||||
@ -429,6 +460,8 @@ class HomeFragmentAdapter(
|
||||
|| getItemViewType(gameAndPosition.position) == ItemViewType.GAME_SUBJECT
|
||||
|| getItemViewType(gameAndPosition.position) == ItemViewType.GAME_SUBJECT_SLIDE
|
||||
|| getItemViewType(gameAndPosition.position) == DISCOVER_CARD
|
||||
|| getItemViewType(gameAndPosition.position) == ItemViewType.HORIZONTAL_SLIDE_VIDEO
|
||||
|| getItemViewType(gameAndPosition.position) == COLUMN_TEST_V2
|
||||
) {
|
||||
val view = mLayoutManager.findViewByPosition(gameAndPosition.position)
|
||||
val recyclerView = view?.findViewById<RecyclerView>(R.id.recycler_view)
|
||||
@ -441,6 +474,8 @@ class HomeFragmentAdapter(
|
||||
is GameHorizontalSlideAdapter -> adapter.notifyItemByDownload(download)
|
||||
is HomeRecentVGameAdapter -> adapter.notifyItemByDownload(download)
|
||||
is DiscoverCardGameAdapter -> adapter.notifyItemByDownload(download)
|
||||
is HomeGameTestV2GameListRvAdapter -> adapter.notifyItemByDownload(download)
|
||||
is HomeHorizontalSlideVideoAdapter -> adapter.notifyItemByDownload(download)
|
||||
}
|
||||
} else {
|
||||
notifyItemChanged(gameAndPosition.position)
|
||||
@ -466,6 +501,8 @@ class HomeFragmentAdapter(
|
||||
|| getItemViewType(position) == ItemViewType.GAME_SUBJECT
|
||||
|| getItemViewType(position) == ItemViewType.GAME_SUBJECT_SLIDE
|
||||
|| getItemViewType(position) == DISCOVER_CARD
|
||||
|| getItemViewType(position) == COLUMN_TEST_V2
|
||||
|| getItemViewType(position) == ItemViewType.HORIZONTAL_SLIDE_VIDEO
|
||||
) {
|
||||
val view = mLayoutManager.findViewByPosition(position)
|
||||
val recyclerView = view?.findViewById<RecyclerView>(R.id.recycler_view)
|
||||
@ -475,6 +512,8 @@ class HomeFragmentAdapter(
|
||||
is GameHorizontalAdapter -> adapter.notifyChildItem(packageName)
|
||||
is GameHorizontalSlideAdapter -> adapter.notifyChildItem(packageName)
|
||||
is DiscoverCardGameAdapter -> adapter.notifyChildItem(packageName)
|
||||
is HomeGameTestV2GameListRvAdapter -> adapter.notifyChildItem(packageName)
|
||||
is HomeHorizontalSlideVideoAdapter -> adapter.notifyChildItem(packageName)
|
||||
else -> recyclerView?.adapter?.notifyDataSetChanged()
|
||||
}
|
||||
} else {
|
||||
@ -527,6 +566,20 @@ class HomeFragmentAdapter(
|
||||
}
|
||||
continue
|
||||
}
|
||||
//新游开测相关条目
|
||||
val gameTestV2 = itemData.gameTestV2Entity
|
||||
val gameTestV2List = mHomeGameTestV2ViewModel.getDataListLiveData().value
|
||||
gameTestV2List?.forEach { gameDataWrapper ->
|
||||
val gameEntity = gameDataWrapper.gameData
|
||||
if (gameEntity != null) {
|
||||
for (apkEntity in gameEntity.getApk()) {
|
||||
if (apkEntity.packageName == packageName) {
|
||||
positionList.add(GameAndPosition(gameEntity, position))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (gameTestV2 != null) continue
|
||||
|
||||
// 原游戏板块样式
|
||||
mLegacyHomeFragmentAdapterAssistant.getLegacyGameEntityByPackage(
|
||||
@ -559,5 +612,6 @@ class HomeFragmentAdapter(
|
||||
const val GAME_COLLECTION_ITEM: Int = 116
|
||||
const val RECENT_V_GAME: Int = 117
|
||||
const val DISCOVER_CARD: Int = 118
|
||||
const val COLUMN_TEST_V2: Int = 119 //新游开测
|
||||
}
|
||||
}
|
||||
@ -12,7 +12,6 @@ import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.adapter.viewholder.GameViewHolder
|
||||
import com.gh.gamecenter.common.base.BaseRecyclerViewHolder
|
||||
import com.gh.gamecenter.common.utils.*
|
||||
import com.gh.gamecenter.core.utils.DisplayUtils
|
||||
import com.gh.gamecenter.core.utils.RandomUtils
|
||||
import com.gh.gamecenter.databinding.HomeGameItemBinding
|
||||
import com.gh.gamecenter.entity.SubjectEntity
|
||||
@ -124,9 +123,9 @@ class HomeGameItemViewHolder(val binding: HomeGameItemBinding) : BaseRecyclerVie
|
||||
) {
|
||||
val game = subjectEntity.linkGame!!
|
||||
binding.gameIcon.displayGameIcon(game)
|
||||
binding.gameName.text = game.name
|
||||
binding.gameName.setTextColor(R.color.text_title.toColor(binding.root.context))
|
||||
binding.gameBrief.setTextColor(R.color.text_title.toColor(binding.root.context))
|
||||
binding.gameName.text = game.name
|
||||
binding.gameRating.text = game.star.toString()
|
||||
binding.gameRating2.text = game.star.toString()
|
||||
binding.gameRating.setDrawableStart(R.drawable.home_game_rating, 12F.dip2px(), 12F.dip2px())
|
||||
@ -137,11 +136,14 @@ class HomeGameItemViewHolder(val binding: HomeGameItemBinding) : BaseRecyclerVie
|
||||
View.VISIBLE
|
||||
} else View.GONE
|
||||
}, 5)
|
||||
binding.adLabelTv.goneIf(!subjectEntity.adIconActive)
|
||||
GameItemViewHolder.initGameSubtitle(game, binding.gameSubtitleTv, null, binding.root, false) {
|
||||
binding.gameSubtitleTv.maxWidth =
|
||||
DisplayUtils.getScreenWidth() - (if (game.adIconActive) 131F.dip2px() else 156F.dip2px())
|
||||
}
|
||||
GameItemViewHolder.initGameSubtitleAndAdLabel(
|
||||
game,
|
||||
binding.gameSubtitleTv,
|
||||
binding.gameNameContainer,
|
||||
binding.gameName,
|
||||
subjectEntity.adIconActive,
|
||||
binding.adLabelTv
|
||||
)
|
||||
val hierarchy = binding.gameImage.hierarchy
|
||||
try {
|
||||
hierarchy.setPlaceholderImage(ColorDrawable(game.homeSetting.placeholderColor.hexStringToIntColor()))
|
||||
@ -173,17 +175,17 @@ class HomeGameItemViewHolder(val binding: HomeGameItemBinding) : BaseRecyclerVie
|
||||
binding.gameRating.goneIf(!(game.showComment && game.commentCount >= 3 && game.star >= 7 && game.homeSetting.downloadBtnSwitch == "on"))
|
||||
binding.gameRating2.goneIf(!(game.showComment && game.commentCount >= 3 && game.star >= 7 && game.homeSetting.downloadBtnSwitch != "on"))
|
||||
ConstraintSet().apply {
|
||||
clone(binding.gameSubtitleTv.parent as ConstraintLayout)
|
||||
clear(binding.gameSubtitleTv.id, ConstraintSet.END)
|
||||
clone(binding.gameNameContainer.parent as ConstraintLayout)
|
||||
clear(binding.gameNameContainer.id, ConstraintSet.END)
|
||||
if (binding.downloadBtn.visibility == View.VISIBLE) {
|
||||
connect(binding.gameSubtitleTv.id, ConstraintSet.END, binding.downloadBtn.id, ConstraintSet.START)
|
||||
connect(binding.gameNameContainer.id, ConstraintSet.END, binding.downloadBtn.id, ConstraintSet.START)
|
||||
} else if (binding.gameRating2.visibility == View.VISIBLE) {
|
||||
connect(binding.gameSubtitleTv.id, ConstraintSet.END, binding.gameRating2.id, ConstraintSet.START)
|
||||
connect(binding.gameNameContainer.id, ConstraintSet.END, binding.gameRating2.id, ConstraintSet.START)
|
||||
} else {
|
||||
connect(binding.gameSubtitleTv.id, ConstraintSet.END, ConstraintSet.PARENT_ID, ConstraintSet.END)
|
||||
connect(binding.gameNameContainer.id, ConstraintSet.END, ConstraintSet.PARENT_ID, ConstraintSet.END)
|
||||
}
|
||||
setMargin(binding.gameSubtitleTv.id, ConstraintSet.END, 8F.dip2px())
|
||||
applyTo(binding.gameSubtitleTv.parent as ConstraintLayout)
|
||||
setMargin(binding.gameNameContainer.id, ConstraintSet.END, 8F.dip2px())
|
||||
applyTo(binding.gameNameContainer.parent as ConstraintLayout)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -12,6 +12,7 @@ data class HomeItemData(
|
||||
var attachGame: HomeContent? = null,
|
||||
var recentVGame: ArrayList<VGameItemData>? = null,
|
||||
var discoverCard: DiscoveryCardEntity? = null,
|
||||
var gameTestV2Entity: HomeItemTestV2Entity? = null, // 新游开测
|
||||
var lineDivider: Float? = null,
|
||||
var unknownData: Any? = null
|
||||
) : LegacyHomeItemData()
|
||||
@ -13,6 +13,7 @@ import com.gh.download.DownloadManager
|
||||
import com.gh.gamecenter.BuildConfig
|
||||
import com.gh.gamecenter.common.baselist.LoadStatus
|
||||
import com.gh.gamecenter.common.constant.Constants
|
||||
import com.gh.gamecenter.common.entity.LinkEntity
|
||||
import com.gh.gamecenter.common.retrofit.BiResponse
|
||||
import com.gh.gamecenter.common.retrofit.Response
|
||||
import com.gh.gamecenter.common.utils.observableToMain
|
||||
@ -25,6 +26,7 @@ import com.gh.gamecenter.feature.entity.PluginLocation
|
||||
import com.gh.gamecenter.feature.utils.ApkActiveUtils
|
||||
import com.gh.gamecenter.game.rank.RankCollectionAdapter
|
||||
import com.gh.gamecenter.gamecollection.square.GameCollectionListItemData
|
||||
import com.gh.gamecenter.home.test_v2.HomeGameTestV2DownloadStateUpdateHelper
|
||||
import com.gh.gamecenter.packagehelper.PackageRepository
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager
|
||||
import com.gh.vspace.VGameItemData
|
||||
@ -41,6 +43,8 @@ import kotlin.math.roundToInt
|
||||
|
||||
class HomeViewModel(application: Application) : AndroidViewModel(application) {
|
||||
|
||||
private var mHomeGameTestV2DownloadStateUpdateHelper: HomeGameTestV2DownloadStateUpdateHelper? = null
|
||||
|
||||
private val mApi = RetrofitManager.getInstance().api
|
||||
|
||||
private var mSnapshotItemList = ArrayList<HomeItemData>()
|
||||
@ -530,6 +534,13 @@ class HomeViewModel(application: Application) : AndroidViewModel(application) {
|
||||
iterator.remove()
|
||||
}
|
||||
}
|
||||
|
||||
//过滤掉游戏数量小于2个的视频横屏滑动专题
|
||||
if (item.linkType == "column" && item.linkColumn?.type == "game_video_horizontal_slide") {
|
||||
if ((item.linkColumn.data?.size ?: 0) < 2) {
|
||||
iterator.remove()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mSmartSubject != null && homeContents.size > mSmartSubject!!.sort) {
|
||||
@ -777,6 +788,28 @@ class HomeViewModel(application: Application) : AndroidViewModel(application) {
|
||||
}
|
||||
mSnapshotItemList.add(LegacyHomeSubjectTransformer.getBlankSpacingItem(HomeItemData()) as HomeItemData)
|
||||
}
|
||||
} else if (linkType == "column_test_v2") {
|
||||
//新游开测 标题和全部按钮
|
||||
val head = HomeItemData()
|
||||
val rightTopLink = homeContent.testV2Data?.rightTop?.link
|
||||
val indexRightTop = homeContent.testV2Data?.rightTop?.text
|
||||
head.columnHead =
|
||||
SubjectEntity(
|
||||
type = linkType,
|
||||
name = "新游开测",
|
||||
indexRightTop = indexRightTop,
|
||||
indexRightTopLink = LinkEntity(
|
||||
text = rightTopLink?.text,
|
||||
link = rightTopLink?.link,
|
||||
type = rightTopLink?.type
|
||||
)
|
||||
)
|
||||
mSnapshotItemList.add(LegacyHomeSubjectTransformer.getBlankSpacingItem(HomeItemData()) as HomeItemData)
|
||||
mSnapshotItemList.add(head)
|
||||
//新游开测 条目
|
||||
val item = HomeItemData()
|
||||
item.gameTestV2Entity = homeContent.testV2Data
|
||||
mSnapshotItemList.add(item)
|
||||
} else {
|
||||
val unknown = HomeItemData()
|
||||
unknown.blockPosition = i + 1
|
||||
@ -799,6 +832,26 @@ class HomeViewModel(application: Application) : AndroidViewModel(application) {
|
||||
}
|
||||
}
|
||||
|
||||
fun setHomeGameTestV2DownloadStateUpdateHelper(helper: HomeGameTestV2DownloadStateUpdateHelper) {
|
||||
mHomeGameTestV2DownloadStateUpdateHelper = helper
|
||||
mHomeGameTestV2DownloadStateUpdateHelper?.setOnGameListAddCallback { position, gameEntities ->
|
||||
gameEntities.forEach {
|
||||
addGamePositionAndPackage(it, position)
|
||||
}
|
||||
positionAndPackageMap.value = HashMap(mPositionAndPackageMap)
|
||||
}
|
||||
}
|
||||
|
||||
private fun addGamePositionAndPackage(game: GameEntity, position: Int) {
|
||||
var packages = ""
|
||||
for (apkEntity in game.getApk()) {
|
||||
packages += apkEntity.packageName
|
||||
}
|
||||
mPositionAndPackageMap[packages + position] = position
|
||||
game.gameLocation = GameEntity.GameLocation.INDEX
|
||||
game.setEntryMap(DownloadManager.getInstance().getEntryMap(game.name))
|
||||
}
|
||||
|
||||
private fun addGamePositionAndPackage(game: GameEntity) {
|
||||
var packages = ""
|
||||
for (apkEntity in game.getApk()) {
|
||||
|
||||
@ -47,6 +47,9 @@ import com.gh.gamecenter.game.rank.RankCollectionViewHolder
|
||||
import com.gh.gamecenter.game.vertical.GameVerticalAdapter
|
||||
import com.gh.gamecenter.game.vertical.GameVerticalSlideViewHolder
|
||||
import com.gh.gamecenter.game.vertical.OnPagerSnapScrollListener
|
||||
import com.gh.gamecenter.servers.gametest2.GameServerTestV2Activity
|
||||
import com.gh.gamecenter.home.horizontalslidevideo.HomeHorizontalSlideVideoListViewHolder
|
||||
import com.gh.gamecenter.home.video.ScrollCalculatorHelper
|
||||
import com.gh.gamecenter.subject.SubjectActivity
|
||||
import com.halo.assistant.fragment.game.GamePluginAdapter
|
||||
import com.halo.assistant.fragment.game.GamePluginViewHolder
|
||||
@ -85,6 +88,7 @@ class LegacyHomeFragmentAdapterAssistant(
|
||||
if (itemData.rankCollection != null) return ItemViewType.RANK_COLLECTION
|
||||
if (itemData.doubleCardColumn != null) return ItemViewType.DOUBLE_CARD_COLUMN
|
||||
if (itemData.bigImageRecommend != null) return ItemViewType.BIG_IMAGE_RECOMMEND
|
||||
if (itemData.horizontalSlideVideo != null) return ItemViewType.HORIZONTAL_SLIDE_VIDEO
|
||||
|
||||
return 0
|
||||
}
|
||||
@ -112,6 +116,7 @@ class LegacyHomeFragmentAdapterAssistant(
|
||||
ItemViewType.RANK_COLLECTION -> RankCollectionViewHolder(parent.toBinding())
|
||||
ItemViewType.DOUBLE_CARD_COLUMN -> DoubleCardViewHolder(parent.toBinding())
|
||||
ItemViewType.BIG_IMAGE_RECOMMEND -> BigImageRecommendViewHolder(parent.toBinding())
|
||||
ItemViewType.HORIZONTAL_SLIDE_VIDEO -> HomeHorizontalSlideVideoListViewHolder(parent.toBinding())
|
||||
|
||||
else -> throw NullPointerException()
|
||||
}
|
||||
@ -120,7 +125,8 @@ class LegacyHomeFragmentAdapterAssistant(
|
||||
fun bindLegacyViewHolder(
|
||||
holder: ViewHolder,
|
||||
item: LegacyHomeItemData,
|
||||
position: Int
|
||||
position: Int,
|
||||
scrollCalculatorHelper: ScrollCalculatorHelper? = null,
|
||||
) {
|
||||
when (holder) {
|
||||
is GameHeadViewHolder -> bindHeadView(holder, item)
|
||||
@ -147,6 +153,11 @@ class LegacyHomeFragmentAdapterAssistant(
|
||||
is RankCollectionViewHolder -> bindRankCollection(holder, item)
|
||||
is DoubleCardViewHolder -> bindGameDoubleCard(holder, item)
|
||||
is BigImageRecommendViewHolder -> bindBigImageRecommend(holder, item)
|
||||
is HomeHorizontalSlideVideoListViewHolder -> bindHomeHorizontalSlideVideo(
|
||||
holder,
|
||||
item,
|
||||
scrollCalculatorHelper
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@ -228,6 +239,18 @@ class LegacyHomeFragmentAdapterAssistant(
|
||||
return
|
||||
}
|
||||
|
||||
val horizontalSlideVideo = itemData.horizontalSlideVideo
|
||||
if (horizontalSlideVideo != null) {
|
||||
horizontalSlideVideo.data?.forEach {
|
||||
for (apkEntity in it.getApk()) {
|
||||
if (apkEntity.packageName == packageName) {
|
||||
positionList.add(GameAndPosition(it, position))
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
val image = itemData.image
|
||||
if (image != null) {
|
||||
positionList.add(GameAndPosition(image, position))
|
||||
@ -628,6 +651,34 @@ class LegacyHomeFragmentAdapterAssistant(
|
||||
NewLogUtils.logCommonCategoryHomeButtonClick(buttonType, column.name ?: "", column.id ?: "", "新首页")
|
||||
} else if (column.type == "game_list_collection") {
|
||||
DirectUtils.directToGameCollectionSquare(mContext, "首页内容列表", column.name ?: "")
|
||||
} else if (column.type == "column_test_v2") {
|
||||
//跳转到新游开测页面
|
||||
val link = column.indexRightTopLink
|
||||
val text = if (column.indexRightTop == "all") {
|
||||
"全部"
|
||||
} else {
|
||||
"更多"
|
||||
}
|
||||
val location = "首页"
|
||||
//埋点上报
|
||||
if (text == "全部") {
|
||||
NewFlatLogUtils.logGameTestV2MoreClick(text, location)
|
||||
//点击进入[新游开测]详情页面
|
||||
mContext.startActivity(GameServerTestV2Activity.getIntent(mContext, "新游开测"))
|
||||
} else {
|
||||
//点击跳转通用链接
|
||||
if (link != null) {
|
||||
DirectUtils.directToLinkPage(mContext, link, "新游开测", "")
|
||||
NewFlatLogUtils.logGameTestV2MoreClick(
|
||||
text,
|
||||
location,
|
||||
linkType = link.type ?: "",
|
||||
linkId = link.link ?: "",
|
||||
linkText = link.text ?: ""
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
if (column.indexRightTopLink != null) {
|
||||
val link = column.indexRightTopLink!!
|
||||
@ -914,6 +965,18 @@ class LegacyHomeFragmentAdapterAssistant(
|
||||
}
|
||||
}
|
||||
|
||||
private fun bindHomeHorizontalSlideVideo(
|
||||
holder: HomeHorizontalSlideVideoListViewHolder,
|
||||
item: LegacyHomeItemData,
|
||||
scrollCalculatorHelper: ScrollCalculatorHelper? = null
|
||||
) {
|
||||
item.horizontalSlideVideo?.run {
|
||||
holder.bindView(this, "新首页", mBasicExposureSources, scrollCalculatorHelper) {
|
||||
item.exposureEventList?.add(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun setPageSwitchData() {
|
||||
PageSwitchDataHelper.pushCurrentPageData(hashMapOf(Pair(PageSwitchDataHelper.PAGE_BUSINESS_TYPE, "首页-内容列表")))
|
||||
}
|
||||
|
||||
@ -1,17 +1,17 @@
|
||||
package com.gh.gamecenter.home
|
||||
|
||||
import com.gh.gamecenter.feature.exposure.ExposureEvent
|
||||
import com.gh.gamecenter.feature.entity.GameEntity
|
||||
import com.gh.gamecenter.entity.SubjectEntity
|
||||
import com.gh.gamecenter.feature.entity.GameEntity
|
||||
import com.gh.gamecenter.feature.exposure.ExposureEvent
|
||||
|
||||
// 原游戏板块样式
|
||||
open class LegacyHomeItemData(
|
||||
// 非实体 (统计数据时用)
|
||||
var blockPosition: Int = -1, // 统计会用到块的位置(相当于一个专题就是1)
|
||||
|
||||
var exposureEvent: ExposureEvent? = null,
|
||||
var exposureEventList: ArrayList<ExposureEvent>? = arrayListOf(),
|
||||
var offset: Int = -1, // 偏移,供下面的实体用
|
||||
override var exposureEvent: ExposureEvent? = null,
|
||||
override var exposureEventList: ArrayList<ExposureEvent>? = arrayListOf(),
|
||||
override var offset: Int = -1, // 偏移,供下面的实体用
|
||||
|
||||
// 实体
|
||||
var game: GameEntity? = null,
|
||||
@ -30,5 +30,6 @@ open class LegacyHomeItemData(
|
||||
var rankCollection: SubjectEntity? = null, // 排行榜样式专题合集
|
||||
var doubleCardColumn: SubjectEntity? = null, // 双列卡片专题
|
||||
var bigImageRecommend: SubjectEntity? = null, //提问、帖子、视频帖、文章
|
||||
var horizontalSlideVideo: SubjectEntity? = null, //水平可自动播放的视频专题
|
||||
var blankDivider: Float? = null // 空白填充内容
|
||||
)
|
||||
):ExposureItemData
|
||||
@ -1,8 +1,8 @@
|
||||
package com.gh.gamecenter.home
|
||||
|
||||
import com.gh.gamecenter.common.entity.LinkEntity
|
||||
import com.gh.gamecenter.feature.entity.GameEntity
|
||||
import com.gh.gamecenter.entity.SubjectEntity
|
||||
import com.gh.gamecenter.feature.entity.GameEntity
|
||||
import com.gh.gamecenter.feature.entity.GameSubjectData
|
||||
|
||||
object LegacyHomeSubjectTransformer {
|
||||
@ -236,6 +236,30 @@ object LegacyHomeSubjectTransformer {
|
||||
return
|
||||
}
|
||||
|
||||
if (subjectEntity.type == "game_video_horizontal_slide") {
|
||||
val itemItemData = newItemInstance()
|
||||
itemItemData.horizontalSlideVideo = subjectEntity
|
||||
appendAdditionalInfoToSubjectGame(subjectEntity, blockPosition)
|
||||
itemList.add(itemItemData)
|
||||
for (i in 0 until data.size) {
|
||||
val game = data[i]
|
||||
game.subjectData = GameSubjectData(
|
||||
id = subjectEntity.id,
|
||||
name = subjectEntity.name,
|
||||
tag = subjectEntity.tag,
|
||||
position = i + if (data[0].image.isNullOrEmpty()) 1 else 0,
|
||||
isOrder = subjectEntity.isOrder,
|
||||
briefStyle = subjectEntity.briefStyle,
|
||||
isShowSuffix = subjectEntity.showSuffix
|
||||
)
|
||||
game.outerSequence = blockPosition
|
||||
game.sequence = i
|
||||
game.isAdData = subjectEntity.adIconActive
|
||||
addGamePositionAndPackage(game)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
for (i in 0 until data.size) {
|
||||
val game = data[i]
|
||||
game.sequence = i
|
||||
|
||||
@ -5,10 +5,7 @@ import android.view.View
|
||||
import com.gh.common.databind.BindingAdapters
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.base.BaseRecyclerViewHolder
|
||||
import com.gh.gamecenter.common.utils.ImageUtils
|
||||
import com.gh.gamecenter.common.utils.TextHelper
|
||||
import com.gh.gamecenter.common.utils.toColor
|
||||
import com.gh.gamecenter.common.utils.toDrawable
|
||||
import com.gh.gamecenter.common.utils.*
|
||||
import com.gh.gamecenter.common.view.AsyncCell
|
||||
import com.gh.gamecenter.databinding.HomeAmwayItemBinding
|
||||
import com.gh.gamecenter.entity.AmwayCommentEntity
|
||||
@ -54,7 +51,7 @@ class HomeAmwayItemViewHolder(val binding: HomeAmwayItemBinding) : BaseRecyclerV
|
||||
ratingName.setTextColor(R.color.text_subtitleDesc.toColor(root.context))
|
||||
all.setTextColor(R.color.text_title.toColor(root.context))
|
||||
}
|
||||
GameItemViewHolder.initGameSubtitle(gameEntity, binding.gameSubtitleTv)
|
||||
GameItemViewHolder.initGameSubtitleAndAdLabel(gameEntity, binding.gameSubtitleTv)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -25,7 +25,9 @@ class HomeDiscoverCardViewHolder(val binding: HomeDiscoverCardItemBinding) : Bas
|
||||
|
||||
fun bindView(
|
||||
entity: DiscoveryCardEntity,
|
||||
entrance: String, blockName: String = ""
|
||||
entrance: String,
|
||||
position: Int,
|
||||
blockName: String = ""
|
||||
): SpanCountPagerSnapHelper {
|
||||
val spanCount = 3
|
||||
val snapHelper = SpanCountPagerSnapHelper(spanCount, false)
|
||||
@ -67,10 +69,26 @@ class HomeDiscoverCardViewHolder(val binding: HomeDiscoverCardItemBinding) : Bas
|
||||
entity.label.forEachIndexed { index, label ->
|
||||
if (index < childCount) {
|
||||
val labelView = labelContainer.getChildAt(index) as TextView
|
||||
updateLabelView(context, labelView, label, index == entity.label.size - 1)
|
||||
updateLabelView(
|
||||
context,
|
||||
labelView,
|
||||
label,
|
||||
index == entity.label.size - 1,
|
||||
entrance,
|
||||
blockName,
|
||||
position
|
||||
)
|
||||
} else {
|
||||
val newLabelView = TextView(context)
|
||||
updateLabelView(context, newLabelView, label, index == entity.label.size - 1)
|
||||
updateLabelView(
|
||||
context,
|
||||
newLabelView,
|
||||
label,
|
||||
index == entity.label.size - 1,
|
||||
entrance,
|
||||
blockName,
|
||||
position
|
||||
)
|
||||
labelContainer.addView(newLabelView)
|
||||
}
|
||||
}
|
||||
@ -82,7 +100,10 @@ class HomeDiscoverCardViewHolder(val binding: HomeDiscoverCardItemBinding) : Bas
|
||||
context: Context,
|
||||
textView: TextView,
|
||||
label: DiscoveryGameCardLabel,
|
||||
isLast: Boolean
|
||||
isLast: Boolean,
|
||||
entrance: String,
|
||||
blockName: String,
|
||||
position: Int
|
||||
) {
|
||||
textView.background = R.drawable.bg_shape_space_radius_4.toDrawable(context)
|
||||
textView.setTextColor(R.color.text_subtitle.toColor(context))
|
||||
@ -102,6 +123,14 @@ class HomeDiscoverCardViewHolder(val binding: HomeDiscoverCardItemBinding) : Bas
|
||||
text = label.title
|
||||
label.text = label.linkText
|
||||
setOnClickListener {
|
||||
NewFlatLogUtils.logDiscoverPageRecommendedInterestCardClick(
|
||||
position,
|
||||
label.text ?: "",
|
||||
label.type ?: "",
|
||||
label.link ?: "",
|
||||
entrance,
|
||||
blockName
|
||||
)
|
||||
DirectUtils.directToLinkPage(context, label, "发现页卡片", "")
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,109 @@
|
||||
package com.gh.gamecenter.home.horizontalslidevideo
|
||||
|
||||
import android.content.Context
|
||||
import android.view.ViewGroup
|
||||
import com.gh.gamecenter.common.utils.dip2px
|
||||
import com.gh.gamecenter.common.utils.toBinding
|
||||
import com.gh.gamecenter.feature.entity.GameEntity
|
||||
import com.gh.gamecenter.feature.exposure.ExposureEvent
|
||||
import com.gh.gamecenter.feature.exposure.ExposureSource
|
||||
import com.lightgame.adapter.BaseRecyclerAdapter
|
||||
import com.lightgame.download.DownloadEntity
|
||||
import splitties.views.bottomPadding
|
||||
import splitties.views.leftPadding
|
||||
import splitties.views.rightPadding
|
||||
import splitties.views.topPadding
|
||||
|
||||
class HomeHorizontalSlideVideoAdapter(
|
||||
mContext: Context,
|
||||
private var mGames: MutableList<GameEntity>,
|
||||
private val mSubjectName: String,
|
||||
private val mEntrance: String,
|
||||
private val mBasicExposureSources: List<ExposureSource>,
|
||||
private val mExposureClosure: (ExposureEvent) -> Unit
|
||||
) :
|
||||
BaseRecyclerAdapter<HomeHorizontalSlideVideoItemViewHolder>(mContext) {
|
||||
|
||||
private var mCountAndKey: Pair<Int, String>? = null
|
||||
|
||||
init {
|
||||
var dataIds = ""
|
||||
mGames.forEach {
|
||||
dataIds += it.id
|
||||
}
|
||||
if (dataIds.isNotEmpty()) mCountAndKey = Pair(mGames.size, dataIds)
|
||||
}
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): HomeHorizontalSlideVideoItemViewHolder {
|
||||
return HomeHorizontalSlideVideoItemViewHolder(parent.toBinding())
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int = mGames.size
|
||||
|
||||
override fun onBindViewHolder(holder: HomeHorizontalSlideVideoItemViewHolder, position: Int) {
|
||||
val gameEntity = mGames[position]
|
||||
val event = ExposureEvent.createEventWithSourceConcat(
|
||||
gameEntity = gameEntity,
|
||||
basicSource = mBasicExposureSources,
|
||||
source = listOf(ExposureSource("专题", mSubjectName))
|
||||
)
|
||||
gameEntity.exposureEvent = event
|
||||
mExposureClosure.invoke(event)
|
||||
|
||||
holder.binding.root.setPadding(
|
||||
16F.dip2px(),
|
||||
holder.binding.root.topPadding,
|
||||
holder.binding.root.rightPadding,
|
||||
holder.binding.root.bottomPadding
|
||||
)
|
||||
|
||||
if (position == itemCount - 1) {
|
||||
holder.binding.root.setPadding(
|
||||
holder.binding.root.leftPadding,
|
||||
holder.binding.root.topPadding,
|
||||
16F.dip2px(),
|
||||
holder.binding.root.bottomPadding
|
||||
)
|
||||
}
|
||||
holder.bindAttachGame(gameEntity, this, mEntrance, event)
|
||||
}
|
||||
|
||||
|
||||
fun checkResetData(update: MutableList<GameEntity>) {
|
||||
var dataIds = ""
|
||||
update.forEach { dataIds += it.id }
|
||||
|
||||
mGames = update
|
||||
if (mCountAndKey?.first == update.size && mCountAndKey?.second != dataIds) { // 数量不变,内容发生改变
|
||||
notifyItemRangeChanged(0, itemCount)
|
||||
} else if (mCountAndKey?.first != update.size) { // 数量发生改变
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
|
||||
// 重新刷新数据标识
|
||||
mCountAndKey = Pair(update.size, dataIds)
|
||||
}
|
||||
|
||||
fun notifyItemByDownload(downloadEntity: DownloadEntity?) {
|
||||
if (downloadEntity == null) {
|
||||
notifyDataSetChanged()
|
||||
} else {
|
||||
mGames.forEachIndexed { position, gameEntity ->
|
||||
if (downloadEntity.gameId == gameEntity.id) {
|
||||
notifyItemChanged(position)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun notifyChildItem(packageName: String) {
|
||||
mGames.forEachIndexed { position, gameEntity ->
|
||||
gameEntity.getApk().forEach { apkEntity ->
|
||||
if (apkEntity.packageName == packageName) {
|
||||
notifyItemChanged(position)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,115 @@
|
||||
package com.gh.gamecenter.home.horizontalslidevideo
|
||||
|
||||
import android.graphics.drawable.ColorDrawable
|
||||
import android.view.View
|
||||
import androidx.constraintlayout.widget.ConstraintLayout
|
||||
import androidx.constraintlayout.widget.ConstraintSet
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.gh.common.databind.BindingAdapters
|
||||
import com.gh.common.util.DownloadItemUtils
|
||||
import com.gh.gamecenter.GameDetailActivity
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.adapter.viewholder.GameViewHolder
|
||||
import com.gh.gamecenter.common.base.BaseRecyclerViewHolder
|
||||
import com.gh.gamecenter.common.utils.*
|
||||
import com.gh.gamecenter.core.utils.RandomUtils
|
||||
import com.gh.gamecenter.databinding.ItemHomeHorizontalSlideVideoBinding
|
||||
import com.gh.gamecenter.feature.entity.GameEntity
|
||||
import com.gh.gamecenter.feature.exposure.ExposureEvent
|
||||
import com.gh.gamecenter.feature.game.GameItemViewHolder
|
||||
import com.shuyu.gsyvideoplayer.builder.GSYVideoOptionBuilder
|
||||
|
||||
class HomeHorizontalSlideVideoItemViewHolder(val binding: ItemHomeHorizontalSlideVideoBinding) :
|
||||
BaseRecyclerViewHolder<Any>(binding.root) {
|
||||
|
||||
fun bindAttachGame(
|
||||
gameEntity: GameEntity,
|
||||
adapter: RecyclerView.Adapter<out RecyclerView.ViewHolder>,
|
||||
entrance: String,
|
||||
exposureEvent: ExposureEvent
|
||||
) {
|
||||
bindGameInfo(gameEntity, adapter, exposureEvent, entrance)
|
||||
binding.gameImage.goneIf(gameEntity.topVideo != null || gameEntity.homeSetting.image.isEmpty()) {
|
||||
ImageUtils.display(binding.gameImage, gameEntity.homeSetting.image)
|
||||
val hierarchy = binding.gameImage.hierarchy
|
||||
try {
|
||||
hierarchy.setPlaceholderImage(ColorDrawable(gameEntity.homeSetting.placeholderColor.hexStringToIntColor()))
|
||||
} catch (ignore: Throwable) {
|
||||
hierarchy.setPlaceholderImage(RandomUtils.getRandomPlaceholderColor())
|
||||
}
|
||||
}
|
||||
binding.autoVideoView.goneIf(gameEntity.topVideo == null) {
|
||||
if (!binding.autoVideoView.isInPlayingState) {
|
||||
GSYVideoOptionBuilder()
|
||||
.setIsTouchWiget(false)
|
||||
.setUrl(gameEntity.topVideo?.url ?: "")
|
||||
.setRotateViewAuto(false)
|
||||
.setCacheWithPlay(true)
|
||||
.setRotateWithSystem(false)
|
||||
.setReleaseWhenLossAudio(true)
|
||||
.setLooping(false)
|
||||
.setShowFullAnimation(false)
|
||||
.build(binding.autoVideoView)
|
||||
binding.autoVideoView.updateThumb(gameEntity.topVideo?.poster ?: "")
|
||||
binding.autoVideoView.setParamsData(gameEntity, gameEntity.homeSetting.placeholderColor)
|
||||
binding.autoVideoView.setOnVideoClickListener { itemView.performClick() }
|
||||
}
|
||||
}
|
||||
|
||||
itemView.setOnClickListener {
|
||||
GameDetailActivity.startGameDetailActivity(
|
||||
binding.root.context,
|
||||
gameEntity.id,
|
||||
"(${entrance}-游戏[" + gameEntity.name + "])",
|
||||
exposureEvent
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun bindGameInfo(
|
||||
gameEntity: GameEntity,
|
||||
adapter: RecyclerView.Adapter<out RecyclerView.ViewHolder>,
|
||||
exposureEvent: ExposureEvent?,
|
||||
entrance: String
|
||||
) {
|
||||
binding.gameIcon.displayGameIcon(gameEntity)
|
||||
binding.gameName.text = gameEntity.name
|
||||
binding.gameName.setTextColor(R.color.text_title.toColor(binding.root.context))
|
||||
BindingAdapters.setGameTags(binding.gameTags, gameEntity)
|
||||
GameItemViewHolder.initGameSubtitleAndAdLabel(gameEntity, binding.gameSubtitleTv)
|
||||
|
||||
DownloadItemUtils.setOnClickListener(
|
||||
binding.root.context,
|
||||
binding.downloadBtn,
|
||||
gameEntity,
|
||||
position,
|
||||
adapter,
|
||||
entrance,
|
||||
"",
|
||||
exposureEvent
|
||||
)
|
||||
DownloadItemUtils.updateItem(
|
||||
binding.root.context,
|
||||
gameEntity,
|
||||
GameViewHolder(binding.root).apply {
|
||||
gameDownloadBtn = binding.downloadBtn
|
||||
multiVersionDownloadTv = binding.multiVersionDownloadTv
|
||||
gameDownloadTips = binding.downloadTipsLottie
|
||||
},
|
||||
true
|
||||
)
|
||||
|
||||
ConstraintSet().apply {
|
||||
clone(binding.gameNameContainer.parent as ConstraintLayout)
|
||||
clear(binding.gameNameContainer.id, ConstraintSet.END)
|
||||
if (binding.downloadBtn.visibility == View.VISIBLE) {
|
||||
connect(binding.gameNameContainer.id, ConstraintSet.END, binding.downloadBtn.id, ConstraintSet.START)
|
||||
} else {
|
||||
connect(binding.gameNameContainer.id, ConstraintSet.END, ConstraintSet.PARENT_ID, ConstraintSet.END)
|
||||
}
|
||||
setMargin(binding.gameNameContainer.id, ConstraintSet.END, 16F.dip2px())
|
||||
applyTo(binding.gameNameContainer.parent as ConstraintLayout)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,53 @@
|
||||
package com.gh.gamecenter.home.horizontalslidevideo
|
||||
|
||||
import androidx.recyclerview.widget.DefaultItemAnimator
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.gh.gamecenter.common.base.BaseRecyclerViewHolder
|
||||
import com.gh.gamecenter.common.view.FixLinearLayoutManager
|
||||
import com.gh.gamecenter.databinding.HomeHorizontalSlideVideoListBinding
|
||||
import com.gh.gamecenter.entity.SubjectEntity
|
||||
import com.gh.gamecenter.feature.exposure.ExposureEvent
|
||||
import com.gh.gamecenter.feature.exposure.ExposureSource
|
||||
import com.gh.gamecenter.home.amway.LeftPagerSnapHelper
|
||||
import com.gh.gamecenter.home.video.ScrollCalculatorHelper
|
||||
|
||||
class HomeHorizontalSlideVideoListViewHolder(val binding: HomeHorizontalSlideVideoListBinding) :
|
||||
BaseRecyclerViewHolder<Any>(binding.root) {
|
||||
|
||||
fun bindView(
|
||||
subject: SubjectEntity,
|
||||
entrance: String,
|
||||
basicExposureSource: List<ExposureSource>,
|
||||
scrollCalculatorHelper: ScrollCalculatorHelper? = null,
|
||||
exposureClosure: (ExposureEvent) -> Unit
|
||||
) {
|
||||
val context = binding.recyclerView.context
|
||||
var adapter = binding.recyclerView.adapter
|
||||
val games = subject.data ?: return
|
||||
if (adapter is HomeHorizontalSlideVideoAdapter) {
|
||||
adapter.checkResetData(games)
|
||||
return
|
||||
}
|
||||
adapter = HomeHorizontalSlideVideoAdapter(context, games, subject.name ?: "", entrance, basicExposureSource) {
|
||||
exposureClosure.invoke(it)
|
||||
}
|
||||
|
||||
binding.recyclerView.layoutManager =
|
||||
FixLinearLayoutManager(context, RecyclerView.HORIZONTAL, false)
|
||||
binding.recyclerView.adapter = adapter
|
||||
(binding.recyclerView.itemAnimator as DefaultItemAnimator).supportsChangeAnimations = false
|
||||
val snapHelper = LeftPagerSnapHelper()
|
||||
snapHelper.attachToRecyclerView(binding.recyclerView)
|
||||
binding.recyclerView.addOnScrollListener(object : RecyclerView.OnScrollListener() {
|
||||
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
|
||||
super.onScrolled(recyclerView, dx, dy)
|
||||
scrollCalculatorHelper?.onScroll()
|
||||
}
|
||||
|
||||
override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
|
||||
super.onScrollStateChanged(recyclerView, newState)
|
||||
scrollCalculatorHelper?.onScrollStateChanged(newState)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -6,10 +6,7 @@ import android.view.View
|
||||
import com.facebook.imagepipeline.image.ImageInfo
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.base.BaseRecyclerViewHolder
|
||||
import com.gh.gamecenter.common.utils.ImageUtils
|
||||
import com.gh.gamecenter.common.utils.dip2px
|
||||
import com.gh.gamecenter.common.utils.goneIf
|
||||
import com.gh.gamecenter.common.utils.toColor
|
||||
import com.gh.gamecenter.common.utils.*
|
||||
import com.gh.gamecenter.core.utils.RandomUtils
|
||||
import com.gh.gamecenter.databinding.HomeSlideListItemBinding
|
||||
import com.gh.gamecenter.entity.HomeSlide
|
||||
@ -42,7 +39,7 @@ class HomeSlideListItemViewHolder(val binding: HomeSlideListItemBinding) : BaseR
|
||||
binding.includeGame.gameName.setTextColor(R.color.white.toColor())
|
||||
|
||||
homeSlide.linkGame?.let {
|
||||
GameItemViewHolder.initGameSubtitle(it, binding.includeGame.gameSubtitleTv, null, binding.includeGame.root)
|
||||
GameItemViewHolder.initGameSubtitleAndAdLabel(it, binding.includeGame.gameSubtitleTv)
|
||||
}
|
||||
|
||||
binding.bottomGradient.visibility = View.GONE
|
||||
|
||||
@ -0,0 +1,42 @@
|
||||
package com.gh.gamecenter.home.test_v2
|
||||
|
||||
import com.gh.gamecenter.feature.entity.GameEntity
|
||||
|
||||
/**
|
||||
* @author : liujiarui
|
||||
* date : 2023/3/10
|
||||
* description : 首页-新游开测-游戏下载进度更新辅助
|
||||
*/
|
||||
interface HomeGameTestV2DownloadStateUpdateHelper {
|
||||
/**
|
||||
* 模块所处的父列表索引
|
||||
*/
|
||||
var mParentPosition: Int
|
||||
|
||||
/**
|
||||
* 游戏列表新增回调
|
||||
*/
|
||||
var mOnGameListAddCallback: (Int, List<GameEntity>) -> Unit
|
||||
|
||||
/**
|
||||
* 设置模块在父列表的索引
|
||||
*/
|
||||
fun setParentPosition(parentPosition: Int) {
|
||||
mParentPosition = parentPosition
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置游戏列表新增回调
|
||||
*/
|
||||
fun setOnGameListAddCallback(callback: (Int, List<GameEntity>) -> Unit) {
|
||||
mOnGameListAddCallback = callback
|
||||
}
|
||||
|
||||
/**
|
||||
* 通知外部有游戏列表添加
|
||||
*/
|
||||
fun notifyParentAddGameList(gameList: List<GameEntity>) {
|
||||
mOnGameListAddCallback(mParentPosition, gameList)
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,46 @@
|
||||
package com.gh.gamecenter.home.test_v2
|
||||
|
||||
import android.view.View
|
||||
import androidx.core.view.updateLayoutParams
|
||||
import com.gh.gamecenter.common.base.BaseRecyclerViewHolder
|
||||
import com.gh.gamecenter.common.utils.dip2px
|
||||
import com.gh.gamecenter.databinding.ItemSkeletonHomeGameTestV2PlaceHolderBinding
|
||||
|
||||
/**
|
||||
* @author : liujiarui
|
||||
* date : 2023/3/6
|
||||
* description : 新游开测,游戏列表 item space holder
|
||||
*/
|
||||
class HomeGameTestV2GameListPlaceHolderViewHolder(
|
||||
private val mBinding: ItemSkeletonHomeGameTestV2PlaceHolderBinding
|
||||
) : BaseRecyclerViewHolder<Any>(mBinding.root) {
|
||||
|
||||
fun bind(isLastRow: Boolean) {
|
||||
mBinding.root.post {
|
||||
mBinding.resetItemWidth(isLastRow)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 右侧条目露出一小部分
|
||||
*/
|
||||
private fun ItemSkeletonHomeGameTestV2PlaceHolderBinding.resetItemWidth(isLastRow: Boolean) {
|
||||
root.parent?.let {
|
||||
if (it is View) {
|
||||
root.updateLayoutParams {
|
||||
width = it.width - if (isLastRow) {
|
||||
8F.dip2px()
|
||||
} else {
|
||||
24F.dip2px()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
val padding = 16F.dip2px()
|
||||
if (isLastRow) {
|
||||
root.setPadding(padding, 0, padding, 12F.dip2px())
|
||||
} else {
|
||||
root.setPadding(padding, 0, 0, 12F.dip2px())
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,208 @@
|
||||
package com.gh.gamecenter.home.test_v2
|
||||
|
||||
import android.content.Context
|
||||
import android.view.ViewGroup
|
||||
import androidx.recyclerview.widget.DiffUtil
|
||||
import androidx.recyclerview.widget.RecyclerView.ViewHolder
|
||||
import com.gh.common.exposure.IExposable
|
||||
import com.gh.common.util.DownloadItemUtils
|
||||
import com.gh.gamecenter.GameDetailActivity
|
||||
import com.gh.gamecenter.common.utils.toBinding
|
||||
import com.gh.gamecenter.core.utils.StringUtils
|
||||
import com.gh.gamecenter.entity.GameDataWrapper
|
||||
import com.gh.gamecenter.feature.entity.GameEntity
|
||||
import com.gh.gamecenter.feature.exposure.ExposureEvent
|
||||
import com.gh.gamecenter.feature.exposure.ExposureSource
|
||||
import com.gh.gamecenter.home.ExposureItemData
|
||||
import com.lightgame.adapter.BaseRecyclerAdapter
|
||||
import com.lightgame.download.DownloadEntity
|
||||
|
||||
/**
|
||||
* @author : liujiarui
|
||||
* date : 2023/3/6
|
||||
* description : 新游开测,游戏列表 adapter
|
||||
*/
|
||||
class HomeGameTestV2GameListRvAdapter(
|
||||
context: Context,
|
||||
private val mViewModel: HomeGameTestV2ViewModel,
|
||||
private val mBasicExposureSource: List<ExposureSource>,
|
||||
private val mOuterSequence: Int,
|
||||
var exposureItemData: ExposureItemData
|
||||
) : BaseRecyclerAdapter<ViewHolder>(context), IExposable {
|
||||
|
||||
private val mEntrance: String = "新游开测"
|
||||
|
||||
private val mExposureEventMap = mutableMapOf<Int, ExposureEvent>()
|
||||
|
||||
var mDataList = listOf<GameDataWrapper>()
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
||||
return when (viewType) {
|
||||
0 -> HomeGameTestV2GameListSpaceViewHolder(parent.toBinding())
|
||||
1 -> HomeGameTestV2GameListPlaceHolderViewHolder(parent.toBinding())
|
||||
else -> HomeGameTestV2GameListViewHolder(parent.toBinding())
|
||||
}
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int {
|
||||
return mDataList.size
|
||||
}
|
||||
|
||||
override fun getItemViewType(position: Int): Int {
|
||||
val data = mDataList[position]
|
||||
return when {
|
||||
data.isSpace -> 0
|
||||
data.isPlaceHolder -> 1
|
||||
else -> 2
|
||||
}
|
||||
}
|
||||
|
||||
fun submitData(data: List<GameDataWrapper>) {
|
||||
val oldList = mDataList
|
||||
mDataList = data
|
||||
DiffUtil.calculateDiff(object : DiffUtil.Callback() {
|
||||
override fun getOldListSize(): Int {
|
||||
return oldList.size
|
||||
}
|
||||
|
||||
override fun getNewListSize(): Int {
|
||||
return data.size
|
||||
}
|
||||
|
||||
override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
|
||||
val oldItem = oldList[oldItemPosition]
|
||||
val newItem = data[newItemPosition]
|
||||
return oldItem.index == newItem.index
|
||||
}
|
||||
|
||||
override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
|
||||
val oldItem = oldList[oldItemPosition]
|
||||
val newItem = data[newItemPosition]
|
||||
return oldItem.isSpace == newItem.isSpace
|
||||
&& oldItem.isPlaceHolder == newItem.isPlaceHolder
|
||||
&& oldItem.gameData?.id == newItem.gameData?.id
|
||||
&& oldItem.gameData?.name == newItem.gameData?.name
|
||||
}
|
||||
|
||||
}, false).dispatchUpdatesTo(this)
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
||||
val data = mDataList.getOrNull(position) ?: return
|
||||
var lastModPosition = itemCount % 3
|
||||
if (lastModPosition == 0) lastModPosition = 3
|
||||
val isLastRow = (itemCount - position) <= lastModPosition
|
||||
if (holder is HomeGameTestV2GameListViewHolder) {
|
||||
val gameData = data.gameData ?: return
|
||||
holder.bindGameItem(gameData, isLastRow)
|
||||
initGameHolder(holder, gameData, position)
|
||||
} else if (holder is HomeGameTestV2GameListPlaceHolderViewHolder) {
|
||||
holder.bind(isLastRow)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化上报事件,下载按钮点击事件,游戏详情点击事件,
|
||||
* 更新下载状态等
|
||||
*/
|
||||
private fun initGameHolder(
|
||||
viewHolder: HomeGameTestV2GameListViewHolder,
|
||||
gameEntity: GameEntity,
|
||||
position: Int
|
||||
) {
|
||||
val exposureEvent = putExposureEvent(gameEntity, position)
|
||||
//游戏下载事件上报
|
||||
DownloadItemUtils.setOnClickListener(
|
||||
mContext,
|
||||
viewHolder.gameDownloadBtn, gameEntity, viewHolder.bindingAdapterPosition, this,
|
||||
StringUtils.buildString(mEntrance, "+(新游开测[", position.toString(), "])"),
|
||||
StringUtils.buildString("新游开测:", gameEntity.name),
|
||||
exposureEvent
|
||||
)
|
||||
|
||||
DownloadItemUtils.updateItem(mContext, gameEntity, viewHolder, true)
|
||||
|
||||
//游戏详情点击事件上报
|
||||
viewHolder.itemView.setOnClickListener {
|
||||
GameDetailActivity.startGameDetailActivity(
|
||||
mContext,
|
||||
gameEntity,
|
||||
StringUtils.buildString(mEntrance, "+(新游开测[", viewHolder.adapterPosition.toString(), "])"),
|
||||
traceEvent = exposureEvent
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun notifyItemByDownload(downloadEntity: DownloadEntity?) {
|
||||
if (downloadEntity == null) {
|
||||
notifyDataSetChanged()
|
||||
} else {
|
||||
mDataList.forEachIndexed { position, gameEntity ->
|
||||
if (downloadEntity.gameId == gameEntity.gameData?.id) {
|
||||
notifyItemChanged(position)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun notifyChildItem(packageName: String) {
|
||||
mDataList.forEachIndexed { position, gameEntity ->
|
||||
gameEntity.gameData?.getApk()?.forEach { apkEntity ->
|
||||
if (apkEntity.packageName == packageName) {
|
||||
notifyItemChanged(position)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun putExposureEvent(
|
||||
gameEntity: GameEntity,
|
||||
position: Int
|
||||
): ExposureEvent {
|
||||
val exposureSources = ArrayList<ExposureSource>()
|
||||
var timeType = mViewModel.getTimePointLiveData().value ?: ""
|
||||
if (timeType == "recommend") {
|
||||
timeType = "推荐"
|
||||
}
|
||||
exposureSources.add(
|
||||
ExposureSource(
|
||||
"新游开测",
|
||||
timeType
|
||||
)
|
||||
)
|
||||
val exposureEvent = ExposureEvent.createEventWithSourceConcat(
|
||||
gameEntity = gameEntity.apply {
|
||||
outerSequence = mOuterSequence
|
||||
sequence = position
|
||||
},
|
||||
basicSource = mBasicExposureSource,
|
||||
source = exposureSources
|
||||
)
|
||||
mExposureEventMap.put(position, exposureEvent)
|
||||
//游戏曝光事件交给外层的adapter处理
|
||||
val list = mExposureEventMap.values.toList()
|
||||
val arrayList = arrayListOf(*list.toTypedArray())
|
||||
exposureItemData.exposureEventList = arrayList
|
||||
return exposureEvent
|
||||
}
|
||||
|
||||
/**
|
||||
* 左右滑动曝光条目
|
||||
*/
|
||||
fun exposureItem(firstItemPosition: Int) {
|
||||
val gameList = mDataList
|
||||
for (position in firstItemPosition..firstItemPosition + 2) {
|
||||
val gameEntity = gameList.getOrNull(position)?.gameData ?: continue
|
||||
putExposureEvent(gameEntity, position)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getEventByPosition(pos: Int): ExposureEvent? {
|
||||
return mExposureEventMap[pos]
|
||||
}
|
||||
|
||||
override fun getEventListByPosition(pos: Int): List<ExposureEvent>? {
|
||||
return null
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,13 @@
|
||||
package com.gh.gamecenter.home.test_v2
|
||||
|
||||
import com.gh.gamecenter.common.base.BaseRecyclerViewHolder
|
||||
import com.gh.gamecenter.databinding.ItemHomeGameTestV2ItemSpaceBinding
|
||||
|
||||
/**
|
||||
* @author : liujiarui
|
||||
* date : 2023/3/6
|
||||
* description : 新游开测,游戏列表 item space holder
|
||||
*/
|
||||
class HomeGameTestV2GameListSpaceViewHolder(binding: ItemHomeGameTestV2ItemSpaceBinding) :
|
||||
BaseRecyclerViewHolder<Any>(binding.root) {
|
||||
}
|
||||
@ -0,0 +1,121 @@
|
||||
package com.gh.gamecenter.home.test_v2
|
||||
|
||||
import android.view.View
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.core.view.updateLayoutParams
|
||||
import com.gh.common.databind.BindingAdapters
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.adapter.viewholder.GameViewHolder
|
||||
import com.gh.gamecenter.common.utils.dip2px
|
||||
import com.gh.gamecenter.common.utils.setDrawableStart
|
||||
import com.gh.gamecenter.common.utils.toColor
|
||||
import com.gh.gamecenter.common.utils.toDrawable
|
||||
import com.gh.gamecenter.core.utils.TimeUtils
|
||||
import com.gh.gamecenter.databinding.ItemHomeGameTestV2ItemBinding
|
||||
import com.gh.gamecenter.feature.entity.GameEntity
|
||||
import com.gh.gamecenter.feature.game.GameItemViewHolder
|
||||
|
||||
/**
|
||||
* @author : liujiarui
|
||||
* date : 2023/3/6
|
||||
* description :
|
||||
*/
|
||||
class HomeGameTestV2GameListViewHolder(
|
||||
private val mBinding: ItemHomeGameTestV2ItemBinding
|
||||
) : GameViewHolder(mBinding.root) {
|
||||
|
||||
init {
|
||||
gameName = mBinding.gameName
|
||||
gameDownloadBtn = mBinding.downloadBtn
|
||||
gameDes = mBinding.gameDes
|
||||
gameRating = mBinding.gameRating
|
||||
recommendContainer = mBinding.recommendContainer
|
||||
recommendIv = mBinding.recommendIv
|
||||
multiVersionDownloadTv = mBinding.multiVersionDownloadTv
|
||||
gameDownloadTips = mBinding.downloadTipsLottie
|
||||
}
|
||||
|
||||
fun bindGameItem(gameEntity: GameEntity, isLastRow: Boolean) {
|
||||
mBinding.run {
|
||||
gameIconView.displayGameIcon(gameEntity)
|
||||
BindingAdapters.setGameName(gameName, gameEntity, false, null)
|
||||
BindingAdapters.setTextSize(gameRating, if (gameEntity.commentCount > 3) 12 else 10)
|
||||
BindingAdapters.setGameTags(labelList, gameEntity)
|
||||
gameRating.setDrawableStart(if (gameEntity.commentCount > 3) R.drawable.game_horizontal_rating.toDrawable() else null)
|
||||
gameRating.text = if (gameEntity.commentCount > 3) {
|
||||
if (gameEntity.star == 10.0F) "10" else gameEntity.star.toString()
|
||||
} else ""
|
||||
gameRating.setPadding(0, 0, if (gameEntity.commentCount > 3) 8F.dip2px() else 0, 0)
|
||||
gameRating.setTextColor(
|
||||
if (gameEntity.commentCount > 3) {
|
||||
R.color.theme_font.toColor(gameRating.context)
|
||||
} else {
|
||||
R.color.theme.toColor(gameRating.context)
|
||||
}
|
||||
)
|
||||
|
||||
//开服日期
|
||||
val gameTimeText = getGameTimeText(gameEntity)
|
||||
gameDes.text = gameTimeText
|
||||
gameDes.isVisible = gameTimeText.isNotEmpty()
|
||||
|
||||
GameItemViewHolder.initGameSubtitleAndAdLabel(gameEntity, gameSubtitleTv)
|
||||
|
||||
fixViewHolderTheme(gameEntity)
|
||||
|
||||
root.post { resetItemWidth(isLastRow) }
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 修复切换深色模式后,条目复用颜色没有变化的问题
|
||||
*/
|
||||
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_subtitleDesc.toColor(context))
|
||||
var gameRatingTextColor = R.color.theme.toColor(context)
|
||||
if (gameEntity.commentCount > 3) {
|
||||
gameRatingTextColor = R.color.theme_font.toColor(context)
|
||||
}
|
||||
gameRating?.setTextColor(gameRatingTextColor)
|
||||
}
|
||||
|
||||
private fun getGameTimeText(gameEntity: GameEntity): String {
|
||||
val time = gameEntity.time?.time ?: return ""
|
||||
val timeText = TimeUtils.getFormatDate(time)
|
||||
val typeText = when (gameEntity.eventType) {
|
||||
"first" -> "首发上线"
|
||||
"test" -> "开启测试"
|
||||
"update" -> "更新"
|
||||
else -> ""
|
||||
}
|
||||
return "$timeText $typeText"
|
||||
}
|
||||
|
||||
/**
|
||||
* 右侧条目露出一小部分
|
||||
*/
|
||||
private fun ItemHomeGameTestV2ItemBinding.resetItemWidth(isLastRow: Boolean) {
|
||||
root.parent?.let {
|
||||
if (it is View) {
|
||||
root.updateLayoutParams {
|
||||
width = it.width - if (isLastRow) {
|
||||
8F.dip2px()
|
||||
} else {
|
||||
24F.dip2px()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
val padding = 16F.dip2px()
|
||||
if (isLastRow) {
|
||||
root.setPadding(padding, 0, padding, 12F.dip2px())
|
||||
} else {
|
||||
root.setPadding(padding, 0, 0, 12F.dip2px())
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,34 @@
|
||||
package com.gh.gamecenter.home.test_v2
|
||||
|
||||
import android.content.Context
|
||||
import android.view.ViewGroup
|
||||
import com.gh.gamecenter.common.utils.toBinding
|
||||
import com.gh.gamecenter.entity.RecommendLabel
|
||||
import com.gh.gamecenter.entity.SubjectRecommendEntity
|
||||
import com.lightgame.adapter.BaseRecyclerAdapter
|
||||
|
||||
/**
|
||||
* @author : liujiarui
|
||||
* date : 2023/3/6
|
||||
* description : 新游开测,推荐标签
|
||||
*/
|
||||
class HomeGameTestV2RecommendRvAdapter(
|
||||
context: Context,
|
||||
var data: List<RecommendLabel>,
|
||||
private val mLocation: String,
|
||||
private val mBlockData: SubjectRecommendEntity? = null
|
||||
) : BaseRecyclerAdapter<HomeGameTestV2RecommendViewHolder>(context) {
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): HomeGameTestV2RecommendViewHolder {
|
||||
return HomeGameTestV2RecommendViewHolder(parent.toBinding(), mLocation, mBlockData)
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int {
|
||||
return data.size
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: HomeGameTestV2RecommendViewHolder, position: Int) {
|
||||
val label = data.getOrElse(position) { RecommendLabel() }
|
||||
holder.bind(label)
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,54 @@
|
||||
package com.gh.gamecenter.home.test_v2
|
||||
|
||||
import androidx.core.content.ContextCompat
|
||||
import com.gh.common.util.DirectUtils
|
||||
import com.gh.common.util.NewFlatLogUtils
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.base.BaseRecyclerViewHolder
|
||||
import com.gh.gamecenter.common.utils.setDebouncedClickListener
|
||||
import com.gh.gamecenter.common.utils.toColor
|
||||
import com.gh.gamecenter.databinding.ItemHomeGameTestV2RecommendLabelBinding
|
||||
import com.gh.gamecenter.entity.RecommendLabel
|
||||
import com.gh.gamecenter.entity.SubjectRecommendEntity
|
||||
|
||||
/**
|
||||
* @author : liujiarui
|
||||
* date : 2023/3/3
|
||||
* description : 新游开测 推荐标签 holder
|
||||
*/
|
||||
class HomeGameTestV2RecommendViewHolder(
|
||||
private val mBinding: ItemHomeGameTestV2RecommendLabelBinding,
|
||||
private val mLocation: String,
|
||||
private val mBlockData: SubjectRecommendEntity? = null
|
||||
) : BaseRecyclerViewHolder<Any>(mBinding.root) {
|
||||
fun bind(data: RecommendLabel) {
|
||||
val context = mBinding.tvLabel.context
|
||||
mBinding.tvLabel.text = data.text
|
||||
mBinding.tvLabel.setTextColor(R.color.text_subtitle.toColor(context))
|
||||
mBinding.tvLabel.background =
|
||||
ContextCompat.getDrawable(
|
||||
context,
|
||||
R.drawable.bg_game_test_v2_recommend_label
|
||||
)
|
||||
mBinding.tvLabel.setDebouncedClickListener {
|
||||
DirectUtils.directToLinkPage(
|
||||
context,
|
||||
data.link,
|
||||
"新游开测",
|
||||
""
|
||||
)
|
||||
//埋点上报
|
||||
NewFlatLogUtils.logGameTestV2RecommendLabelClick(
|
||||
location = mLocation,
|
||||
blockId = mBlockData?.link ?: "",
|
||||
blockName = mBlockData?.name ?: "",
|
||||
tagId = data.id,
|
||||
text = data.text,
|
||||
sequence = this.bindingAdapterPosition,
|
||||
linkType = data.link.type ?: "",
|
||||
linkId = data.link.link ?: "",
|
||||
linkText = data.link.text ?: ""
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,127 @@
|
||||
package com.gh.gamecenter.home.test_v2
|
||||
|
||||
import android.content.Context
|
||||
import android.view.ViewGroup
|
||||
import com.gh.common.util.NewFlatLogUtils
|
||||
import com.gh.gamecenter.common.utils.toBinding
|
||||
import com.gh.gamecenter.core.utils.TimeUtils
|
||||
import com.lightgame.adapter.BaseRecyclerAdapter
|
||||
import java.text.DateFormat
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
* @author : liujiarui
|
||||
* date : 2023/3/3
|
||||
* description :
|
||||
*/
|
||||
class HomeGameTestV2TimePointRvAdapter(
|
||||
context: Context,
|
||||
private val mViewModel: HomeGameTestV2ViewModel,
|
||||
var data: List<String>
|
||||
) : BaseRecyclerAdapter<HomeGameTestV2TimePointViewHolder>(context) {
|
||||
|
||||
private var mSelectedPosition: Int = 0
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): HomeGameTestV2TimePointViewHolder {
|
||||
return HomeGameTestV2TimePointViewHolder(parent.toBinding())
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int {
|
||||
return data.size
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: HomeGameTestV2TimePointViewHolder, position: Int) {
|
||||
val text = data.getOrElse(position) { "" }
|
||||
holder.binding.root.setOnClickListener {
|
||||
val bindingAdapterPosition = holder.bindingAdapterPosition
|
||||
if (bindingAdapterPosition == mSelectedPosition) return@setOnClickListener
|
||||
selectPoint(bindingAdapterPosition, true)
|
||||
mViewModel.onTimePointClick(text)
|
||||
}
|
||||
val isSelected = position == mSelectedPosition
|
||||
val todayAndWeekText = if (isSelected) {
|
||||
getShortDate(text)
|
||||
} else {
|
||||
getTodayAndWeekText(text)
|
||||
}
|
||||
holder.bind(
|
||||
todayAndWeekText,
|
||||
position == 0,
|
||||
position == itemCount - 1,
|
||||
isSelected
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* 把日期文本 yyyy-MM-dd 转换成 今天,周几,下周几格式
|
||||
*/
|
||||
private fun getTodayAndWeekText(date: String): String {
|
||||
val today = TimeUtils.getToday()
|
||||
if (today == date) return "今天"
|
||||
val list = TimeUtils.getCurrentAndNextWeek(pattern = "yyyy-MM-dd")
|
||||
list.find { it.first == date }?.let {
|
||||
return it.second
|
||||
} ?: return getShortDate(date)
|
||||
}
|
||||
|
||||
/**
|
||||
* 把日期文本 yyyy-MM-dd 转换成 MM.dd
|
||||
*/
|
||||
private fun getShortDate(date: String): String {
|
||||
if (date == "recommend") return "推荐"
|
||||
val format: DateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA)
|
||||
return try {
|
||||
val d = format.parse(date) ?: return date
|
||||
SimpleDateFormat("MM.dd", Locale.CHINA).format(d)
|
||||
} catch (e: Exception) {
|
||||
date
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 时间轴日期转时间戳
|
||||
*/
|
||||
private fun getDateTimeStamp(date: String): Long {
|
||||
if (date == "recommend") return 0
|
||||
val format: DateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA)
|
||||
return try {
|
||||
val d = format.parse(date) ?: return 0
|
||||
d.time
|
||||
} catch (e: Exception) {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 点击时间轴节点事件
|
||||
*/
|
||||
fun selectPoint(position: Int, isClick: Boolean = false) {
|
||||
val lastSelectedPosition = mSelectedPosition
|
||||
mSelectedPosition = position
|
||||
notifyItemChanged(lastSelectedPosition)
|
||||
notifyItemChanged(position)
|
||||
//埋点上报
|
||||
val action = if (isClick) "手动点击" else "自动定位"
|
||||
NewFlatLogUtils.logGameTestV2TimeLineClick(
|
||||
action = action,
|
||||
type = getType(),
|
||||
time = getStartTime(),
|
||||
sequence = getSequence()
|
||||
)
|
||||
}
|
||||
|
||||
fun getType(): String {
|
||||
val text = data.getOrElse(mSelectedPosition) { "" }
|
||||
return if (text == "recommend") "推荐" else "全部"
|
||||
}
|
||||
|
||||
fun getStartTime(): Long {
|
||||
val text = data.getOrElse(mSelectedPosition) { "" }
|
||||
return getDateTimeStamp(text)
|
||||
}
|
||||
|
||||
fun getSequence(): Int {
|
||||
return mSelectedPosition
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,62 @@
|
||||
package com.gh.gamecenter.home.test_v2
|
||||
|
||||
import android.view.ViewGroup.MarginLayoutParams
|
||||
import androidx.core.view.isInvisible
|
||||
import androidx.core.view.updateLayoutParams
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.base.BaseRecyclerViewHolder
|
||||
import com.gh.gamecenter.common.utils.dip2px
|
||||
import com.gh.gamecenter.common.utils.toColor
|
||||
import com.gh.gamecenter.databinding.ItemHomeGameTestV2TimePointBinding
|
||||
|
||||
/**
|
||||
* @author : liujiarui
|
||||
* date : 2023/3/3
|
||||
* description :
|
||||
*/
|
||||
class HomeGameTestV2TimePointViewHolder(
|
||||
val binding: ItemHomeGameTestV2TimePointBinding
|
||||
) : BaseRecyclerViewHolder<Any>(binding.root) {
|
||||
|
||||
fun bind(data: String, isStart: Boolean, isEnd: Boolean, isSelected: Boolean) {
|
||||
binding.tvTimePoint.text = data
|
||||
reset()
|
||||
if (isStart) isStartNode()
|
||||
if (isEnd) isEndNode()
|
||||
if (isSelected) isSelected()
|
||||
}
|
||||
|
||||
private fun reset() {
|
||||
val context = binding.root.context
|
||||
binding.lineLeft.isInvisible = false
|
||||
binding.lineLeft.setBackgroundColor(R.color.btn_gray_light.toColor(context))
|
||||
binding.lineRight.isInvisible = false
|
||||
binding.lineRight.setBackgroundColor(R.color.btn_gray_light.toColor(context))
|
||||
binding.point.isEnabled = false
|
||||
binding.point.setBackgroundResource(R.drawable.ic_home_game_test_v2_time_point_dot)
|
||||
binding.tvTimePoint.isChecked = false
|
||||
binding.tvTimePoint.textSize = 12f
|
||||
val color = context.resources.getColorStateList(R.color.line_axis_text_selector)
|
||||
binding.tvTimePoint.setTextColor(color)
|
||||
binding.root.updateLayoutParams {
|
||||
(this as? MarginLayoutParams)?.leftMargin = 0f.dip2px()
|
||||
}
|
||||
}
|
||||
|
||||
private fun isSelected() {
|
||||
binding.point.isEnabled = true
|
||||
binding.tvTimePoint.isChecked = true
|
||||
binding.tvTimePoint.textSize = 16f
|
||||
}
|
||||
|
||||
private fun isStartNode() {
|
||||
binding.lineLeft.isInvisible = true
|
||||
binding.root.updateLayoutParams {
|
||||
(this as? MarginLayoutParams)?.leftMargin = 16f.dip2px()
|
||||
}
|
||||
}
|
||||
|
||||
private fun isEndNode() {
|
||||
binding.lineRight.isInvisible = true
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,411 @@
|
||||
package com.gh.gamecenter.home.test_v2
|
||||
|
||||
import android.app.Application
|
||||
import androidx.lifecycle.AndroidViewModel
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import com.gh.common.filter.RegionSettingHelper
|
||||
import com.gh.gamecenter.BuildConfig
|
||||
import com.gh.gamecenter.common.baselist.LoadStatus
|
||||
import com.gh.gamecenter.common.retrofit.Response
|
||||
import com.gh.gamecenter.common.utils.observableToMain
|
||||
import com.gh.gamecenter.core.utils.UrlFilterUtils
|
||||
import com.gh.gamecenter.entity.GameData
|
||||
import com.gh.gamecenter.entity.GameDataWrapper
|
||||
import com.gh.gamecenter.entity.HomeItemTestV2Entity
|
||||
import com.gh.gamecenter.entity.SubjectRecommendEntity
|
||||
import com.gh.gamecenter.feature.entity.GameEntity
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager
|
||||
import com.halo.assistant.HaloApp
|
||||
import retrofit2.HttpException
|
||||
|
||||
/**
|
||||
* @author : liujiarui
|
||||
* date : 2023/3/3
|
||||
* description : 首页-推荐tab-新游开测 item 的分页加载 ViewModel
|
||||
*/
|
||||
|
||||
class HomeGameTestV2ViewModel(application: Application) : AndroidViewModel(application),
|
||||
HomeGameTestV2DownloadStateUpdateHelper {
|
||||
|
||||
override var mParentPosition: Int = 0
|
||||
override var mOnGameListAddCallback: (Int, List<GameEntity>) -> Unit = { _, _ -> }
|
||||
|
||||
//埋点上报的信息,别的板块使用修改这里
|
||||
var location: String = "首页"
|
||||
var blockData: SubjectRecommendEntity? = null
|
||||
|
||||
|
||||
private val mApi = RetrofitManager.getInstance().api
|
||||
|
||||
/**
|
||||
* 加载状态livedata
|
||||
*/
|
||||
private val mLoadStateLiveData = MutableLiveData<LoadStatus>()
|
||||
|
||||
/**
|
||||
* 加载数据返回livedata
|
||||
*/
|
||||
private val mDataLiveData = MutableLiveData<List<GameDataWrapper>>()
|
||||
|
||||
/**
|
||||
* 时间线节点事件通知livedata
|
||||
*/
|
||||
private val mTimePointLiveData = MutableLiveData<String>()
|
||||
|
||||
/**
|
||||
* 游戏列表滑动到指定position位置通知
|
||||
*/
|
||||
private val mGameListScrollLiveData = MutableLiveData<Int>()
|
||||
|
||||
/**
|
||||
* 时间轴数据
|
||||
*/
|
||||
private var mTimePoint: Map<String, String>? = null
|
||||
|
||||
/**
|
||||
* 时间轴节点对应游戏总数
|
||||
*/
|
||||
private var mDataCount: Map<String, Int>? = null
|
||||
|
||||
/**
|
||||
* 设置时间轴数据
|
||||
*/
|
||||
fun setTimePoint(timePoint: Map<String, String>) {
|
||||
this.mTimePoint = timePoint
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置时间轴节点游戏总数
|
||||
* 用占位和空条目填充数据列表
|
||||
*/
|
||||
fun setDataCount(dataCount: Map<String, Int>) {
|
||||
this.mDataCount = dataCount
|
||||
if (dataCount.isEmpty()) return
|
||||
val rawCount = 3
|
||||
val gameList = mutableListOf<GameDataWrapper>()
|
||||
var index = 0
|
||||
dataCount.asSequence().forEach {
|
||||
val (timeType, count) = it
|
||||
repeat(count) {
|
||||
gameList.add(GameDataWrapper(index++, timeType = timeType, isPlaceHolder = true))
|
||||
}
|
||||
val limit = rawCount - (count % rawCount)
|
||||
repeat(limit) {
|
||||
gameList.add(GameDataWrapper(index++, timeType = timeType, isSpace = true))
|
||||
}
|
||||
}
|
||||
mDataLiveData.value = gameList
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页加载方向,
|
||||
* action:
|
||||
* left(左滑加载,即手指从右往左滑,也就是下一页)、
|
||||
* right(右滑加载,即手指从左往右滑,也就是上一页)
|
||||
*/
|
||||
enum class Action(val command: String) {
|
||||
LEFT("left"),
|
||||
RIGHT("right");
|
||||
|
||||
companion object {
|
||||
fun getActionByCommand(command: String): Action {
|
||||
values().forEach {
|
||||
if (it.command == command) return it
|
||||
}
|
||||
return LEFT
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页加载
|
||||
* @param isRefresh 是否是刷新
|
||||
* @param action 分页加载方向
|
||||
* @param pageId 分页id ,加载下一页为上一页最后一个id,加载上一页为下一页第一个id
|
||||
* @param timeType 时间轴类型 time_type(recommend:推荐、xxxx-xx-xx:全部(比如:2023-01-01))
|
||||
* @param startId //时间轴id,起始点ID(与时间轴对应):
|
||||
* start_id(【数据从“时间轴起始点”接口获取】,刚进入页面,或者用户自己“点击切换时间轴”的时候必填。
|
||||
* 如果是用户在数据列表里左右滑动则自动切换下一列的时候 则不用传,要用户主动切换时间轴的才传)
|
||||
*/
|
||||
private fun loadData(
|
||||
isRefresh: Boolean = false,
|
||||
action: Action,
|
||||
pageId: String,
|
||||
timeType: String,
|
||||
loadTimeType: String,
|
||||
startId: String = "",
|
||||
limit: Int = 9
|
||||
) {
|
||||
if (isRefresh) {
|
||||
mLoadStateLiveData.postValue(LoadStatus.INIT_LOADING)
|
||||
} else {
|
||||
mLoadStateLiveData.postValue(LoadStatus.LIST_LOADING)
|
||||
}
|
||||
val filterQuery = UrlFilterUtils.getFilterQuery(
|
||||
"action", action.command,
|
||||
"page_id", pageId,
|
||||
"time_type", timeType, //时间轴类型必填:time_type(recommend:推荐、xxxx-xx-xx:全部(比如:2023-01-01))
|
||||
"load_time_type", loadTimeType, //下一个节点的 time_type,根据action 确定是左边的还是右边的
|
||||
"start_id", startId
|
||||
)
|
||||
mApi.getHomeServerTestV2(
|
||||
BuildConfig.VERSION_NAME,
|
||||
HaloApp.getInstance().channel,
|
||||
limit,
|
||||
filterQuery
|
||||
).compose(observableToMain())
|
||||
.subscribe(object : Response<HomeItemTestV2Entity>() {
|
||||
override fun onResponse(response: HomeItemTestV2Entity?) {
|
||||
mLoadStateLiveData.postValue(LoadStatus.LIST_LOADED)
|
||||
val data = response?.data ?: return
|
||||
addGameList(
|
||||
list = data,
|
||||
timeType = response.timeType,
|
||||
pageId = response.pageId,
|
||||
startId = response.startId,
|
||||
action = Action.getActionByCommand(response.action),
|
||||
isRefresh = false
|
||||
)
|
||||
}
|
||||
|
||||
override fun onFailure(e: HttpException?) {
|
||||
mLoadStateLiveData.postValue(LoadStatus.INIT_FAILED)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fun getDataListLiveData(): LiveData<List<GameDataWrapper>> {
|
||||
return mDataLiveData
|
||||
}
|
||||
|
||||
fun getLoadStateLiveData(): LiveData<LoadStatus> {
|
||||
return mLoadStateLiveData
|
||||
}
|
||||
|
||||
fun getTimePointLiveData(): LiveData<String> {
|
||||
return mTimePointLiveData
|
||||
}
|
||||
|
||||
fun getGameListScrollLiveData(): LiveData<Int> {
|
||||
return mGameListScrollLiveData
|
||||
}
|
||||
|
||||
private fun getCurrentData(): List<GameDataWrapper> {
|
||||
return mDataLiveData.value ?: emptyList()
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据当前条目索引,向前和向后查找6个条目,如果有占位条目,则加载数据
|
||||
*/
|
||||
fun parseActionWithPosition(position: Int) {
|
||||
val forwardPosition = maxOf(position - 6, 0)
|
||||
if (forwardPosition != position) {
|
||||
val list = getCurrentData().subList(forwardPosition, position + 1)
|
||||
val lastPlaceHolderItem = list.lastOrNull { it.isPlaceHolder }
|
||||
val firstHasDataItem = list.firstOrNull { it.gameData != null }
|
||||
if (firstHasDataItem != null && lastPlaceHolderItem != null &&
|
||||
firstHasDataItem.index > lastPlaceHolderItem.index
|
||||
) {
|
||||
loadData(
|
||||
action = Action.RIGHT,
|
||||
pageId = firstHasDataItem.gameData?.id ?: firstHasDataItem.pageId,
|
||||
timeType = firstHasDataItem.timeType,
|
||||
loadTimeType = lastPlaceHolderItem.timeType
|
||||
)
|
||||
}
|
||||
}
|
||||
val backwardPosition = minOf(position + 7, getCurrentData().size)
|
||||
if (backwardPosition != position) {
|
||||
val list = getCurrentData().subList(position, backwardPosition)
|
||||
val firstPlaceHolderItem = list.firstOrNull { it.isPlaceHolder }
|
||||
val lastHasDataItem = list.lastOrNull { it.gameData != null }
|
||||
if (firstPlaceHolderItem != null && lastHasDataItem != null &&
|
||||
lastHasDataItem.index < firstPlaceHolderItem.index
|
||||
) {
|
||||
loadData(
|
||||
action = Action.LEFT,
|
||||
pageId = lastHasDataItem.gameData?.id ?: lastHasDataItem.pageId,
|
||||
timeType = lastHasDataItem.timeType,
|
||||
loadTimeType = firstPlaceHolderItem.timeType
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//添加数据到列表
|
||||
@Synchronized //可能会有多请求同时修改数据问题,以防万一
|
||||
fun addGameList(
|
||||
list: List<GameData>,
|
||||
timeType: String,
|
||||
pageId: String,
|
||||
startId: String,
|
||||
action: Action,
|
||||
isRefresh: Boolean = false
|
||||
) {
|
||||
val currentData = getCurrentData().toMutableList()
|
||||
val gameList = mutableListOf<GameDataWrapper>()
|
||||
list.forEach { gameData ->
|
||||
val gameTimeType = gameData.timeType
|
||||
//过滤被屏蔽的游戏 todo 占位也要同步减少
|
||||
val filterGames = RegionSettingHelper.filterGame(gameData.games)
|
||||
//注册到外部model,用于下载按钮状态更新
|
||||
notifyParentAddGameList(filterGames)
|
||||
filterGames.forEach { gameEntity ->
|
||||
gameList.add(
|
||||
GameDataWrapper(
|
||||
-1, //还未分配位置的数据
|
||||
pageId,
|
||||
gameTimeType,
|
||||
gameEntity
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
if (currentData.size < gameList.size) {
|
||||
//出现错误,没有获取到时间轴的游戏数量, 或者数量不正确
|
||||
return
|
||||
}
|
||||
//给数据分配位置
|
||||
var index = 0
|
||||
if (isRefresh) {
|
||||
//初始化分配
|
||||
while (gameList.isNotEmpty()) {
|
||||
val gameDataWrapper = gameList.removeFirst()
|
||||
while (currentData.getOrNull(index)?.isPlaceHolder == false) {
|
||||
index++
|
||||
}
|
||||
if (index >= currentData.size) {
|
||||
//出现错误,没有获取到时间轴的游戏数量, 或者数量不正确
|
||||
return
|
||||
}
|
||||
currentData[index] = gameDataWrapper.also { it.index = index }
|
||||
}
|
||||
} else {
|
||||
//分页加载逻辑
|
||||
val findPageIdItemPosition = currentData.indexOfFirst {
|
||||
it.timeType == timeType && it.gameData?.id == pageId
|
||||
}
|
||||
|
||||
when (action) {
|
||||
Action.LEFT -> {
|
||||
val firstItemWithTimeTypePosition = currentData.indexOfFirst {
|
||||
it.timeType == timeType
|
||||
}
|
||||
//获取分页标志的条目索引
|
||||
index = if (findPageIdItemPosition != -1) {
|
||||
//找得到pageId那条item,就以此item的索引为基准
|
||||
findPageIdItemPosition
|
||||
} else {
|
||||
//找不到分页标志item,就以时间轴第一个条目作为基准
|
||||
firstItemWithTimeTypePosition
|
||||
}
|
||||
//左滑,向右加载
|
||||
if (findPageIdItemPosition != -1) index++
|
||||
while (gameList.isNotEmpty()) {
|
||||
val gameDataWrapper = gameList.removeFirst()
|
||||
while (currentData.getOrNull(index)?.isSpace == true) {
|
||||
index++
|
||||
}
|
||||
if (index >= currentData.size) {
|
||||
//出现错误,没有获取到时间轴的游戏数量, 或者数量不正确
|
||||
return
|
||||
}
|
||||
currentData[index] = gameDataWrapper.also { it.index = index }
|
||||
index++
|
||||
}
|
||||
}
|
||||
Action.RIGHT -> {
|
||||
//右滑,向左加载
|
||||
val lastItemWithTimeTypePosition = currentData.indexOfLast {
|
||||
it.timeType == timeType
|
||||
}
|
||||
//获取分页标志的条目索引
|
||||
index = if (findPageIdItemPosition != -1) {
|
||||
//找得到pageId那条item,就以此item的索引为基准
|
||||
findPageIdItemPosition
|
||||
} else {
|
||||
//找不到分页标志item,就以时间轴第一个条目作为基准
|
||||
lastItemWithTimeTypePosition
|
||||
}
|
||||
if (findPageIdItemPosition != -1) index--
|
||||
while (gameList.isNotEmpty()) {
|
||||
val gameDataWrapper = gameList.removeLast()
|
||||
while (currentData.getOrNull(index)?.isSpace == true) {
|
||||
index--
|
||||
}
|
||||
if (index < 0) {
|
||||
//出现错误,没有获取到时间轴的游戏数量, 或者数量不正确
|
||||
return
|
||||
}
|
||||
currentData[index] = gameDataWrapper.also { it.index = index }
|
||||
index--
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
mDataLiveData.value = currentData.toMutableList()
|
||||
}
|
||||
|
||||
/**
|
||||
* 选中时间轴,如果列表内有相关数据则滑动到指定位置
|
||||
* @param timeType 时间轴类型 time_type(recommend:推荐、xxxx-xx-xx:全部(比如:2023-01-01))
|
||||
* 还需要做时间轴联动,列表滑动,时间轴也要跟着选中对应的
|
||||
*/
|
||||
fun onTimePointSelected(timeType: String) {
|
||||
mTimePointLiveData.postValue(timeType)
|
||||
}
|
||||
|
||||
/**
|
||||
* 点击时间轴, 获取时间节点数据,或者移动列表到指定位置
|
||||
*/
|
||||
fun onTimePointClick(timeType: String) {
|
||||
val firstItemWithTimeType = getCurrentData().find { it.timeType == timeType } ?: return
|
||||
val index = firstItemWithTimeType.index
|
||||
if (index != -1) {
|
||||
mGameListScrollLiveData.postValue(index)
|
||||
mLoadStateLiveData.postValue(LoadStatus.INIT_LOADED)
|
||||
}
|
||||
val startId = mTimePoint?.get(timeType) ?: ""
|
||||
if (firstItemWithTimeType.isPlaceHolder) {
|
||||
//加载当前页数据 , 不足limit 则用下一页补足
|
||||
val timeTypeList = mTimePoint?.keys?.toList()
|
||||
val currentTimeTypeIndex = timeTypeList?.indexOf(timeType)
|
||||
var loadTimeType = ""
|
||||
if (currentTimeTypeIndex != null && currentTimeTypeIndex != -1) {
|
||||
val nextTimeType = timeTypeList.getOrNull(currentTimeTypeIndex + 1)
|
||||
loadTimeType = nextTimeType ?: timeType
|
||||
}
|
||||
loadData(
|
||||
isRefresh = false,
|
||||
action = Action.LEFT,
|
||||
pageId = startId,
|
||||
timeType = timeType,
|
||||
loadTimeType = loadTimeType,
|
||||
startId = startId
|
||||
)
|
||||
}
|
||||
//判断前一页是否有数据
|
||||
if (index == -1) return
|
||||
val preRow = getCurrentData().take(index).takeLast(3)
|
||||
val preRowNoData = preRow.all { it.isPlaceHolder || it.isSpace }
|
||||
//前一列没有数据,需要加载
|
||||
if (preRowNoData && preRow.isNotEmpty()) {
|
||||
//前一列如果有空条目,则需要计算空条目的数量,作为limit
|
||||
val space = preRow.count { it.isSpace }
|
||||
val limit = 9 - space
|
||||
loadData(
|
||||
isRefresh = false,
|
||||
action = Action.RIGHT,
|
||||
pageId = startId,
|
||||
timeType = timeType,
|
||||
loadTimeType = preRow.firstOrNull()?.timeType ?: timeType,
|
||||
limit = limit
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user