Compare commits
126 Commits
feat/jzcs
...
feat/sync-
| Author | SHA1 | Date | |
|---|---|---|---|
| bd02a0b4be | |||
| 7a498763bb | |||
| 8b839a5b13 | |||
| 7d2ed0eac0 | |||
| 5c70bc2237 | |||
| 03b36096b8 | |||
| 4191dbc4f0 | |||
| cc20b6e38a | |||
| 3ad5890238 | |||
| 6179d7055b | |||
| f18391adc2 | |||
| 3a2f15a436 | |||
| c0e8160955 | |||
| 9038131c96 | |||
| 4430ae1107 | |||
| d6aa2690b2 | |||
| e42fd24b71 | |||
| 452a1ede24 | |||
| ceb227f645 | |||
| 479ea5778b | |||
| 8969d6fd5d | |||
| cc43f2e0fd | |||
| ab12491f2f | |||
| ae24ab0c87 | |||
| 383712900c | |||
| cea62b55e2 | |||
| ff6cdb1ba3 | |||
| b6e531fa96 | |||
| e7a37df690 | |||
| 5308ccfabe | |||
| 2ee49b9a20 | |||
| 3af3d413c0 | |||
| 9bf24977ca | |||
| bf1dd958cd | |||
| 30c34b799b | |||
| b202b580bb | |||
| 239b056abb | |||
| 315be3797c | |||
| 6d29da5172 | |||
| 8aeb0d6f09 | |||
| bdcca58770 | |||
| 4115383b68 | |||
| 9075bfa214 | |||
| 3fa63e331b | |||
| aef19fcd49 | |||
| 15d7252974 | |||
| f6fa060f3a | |||
| 7cfe48b3c8 | |||
| 6bd3c1011d | |||
| 3447ecffd8 | |||
| 644b93ab02 | |||
| 6b44140ff3 | |||
| 78d26b4cc1 | |||
| 5565539445 | |||
| 1ee0f292ba | |||
| f609637f0b | |||
| 9d10add8eb | |||
| f5a39f982e | |||
| 1a063bb0c1 | |||
| 86340d603f | |||
| 0731cc1fde | |||
| 86dfee2ff9 | |||
| edf82952ce | |||
| 062f0149d0 | |||
| a504f00bac | |||
| 4412d159bb | |||
| e119b7fecd | |||
| 72460b88be | |||
| 3fe7c8252e | |||
| 36ebab77ee | |||
| e84db01984 | |||
| ae605d4a55 | |||
| 882bf4b551 | |||
| 968164af55 | |||
| 0119e6f123 | |||
| 30135bdb8f | |||
| f8ac85d29c | |||
| 7093552259 | |||
| 2be52d21ee | |||
| cb093cc3f0 | |||
| 3cbdd94189 | |||
| 11013319bf | |||
| aa954b3af9 | |||
| 93f279a384 | |||
| 4e54833cc9 | |||
| f95862da8b | |||
| 1515df34b5 | |||
| 8a8ef40dc1 | |||
| b6194fed26 | |||
| 02752f6c81 | |||
| b33d367dfd | |||
| d5046ab431 | |||
| a53168c9bc | |||
| 3cbc8c2f74 | |||
| 7398b83004 | |||
| 8013426ded | |||
| b86d85b15f | |||
| 5a73afbab3 | |||
| e19ee25839 | |||
| 61bf39e95f | |||
| ef82ae2378 | |||
| 2dcccc22a8 | |||
| cb0e77d204 | |||
| a6ea178609 | |||
| 6a62f08891 | |||
| ddb48481d2 | |||
| 48a55a6b31 | |||
| 50fcb0c3ea | |||
| e97722b6fb | |||
| 2163b2ff9e | |||
| b9558e2732 | |||
| 39bba71e7a | |||
| 5daddeadda | |||
| 58b1c0295c | |||
| a56082d002 | |||
| 877ab7cf39 | |||
| 428e3496d8 | |||
| b33419ea05 | |||
| e9bcd0a0d6 | |||
| 98b877671a | |||
| 6c61a62799 | |||
| e9139c66e1 | |||
| 24941a165a | |||
| d9743a89d6 | |||
| f492d2ea97 | |||
| 46955685bb |
@ -72,6 +72,7 @@ android_build:
|
||||
only:
|
||||
- dev
|
||||
- release
|
||||
- feat/GHZSCY-6578
|
||||
|
||||
# 代码检查
|
||||
sonarqube_analysis:
|
||||
@ -156,4 +157,5 @@ oss-upload&send-email:
|
||||
- /usr/local/bin/python /ci-android-mail-jira-comment.py
|
||||
only:
|
||||
- dev
|
||||
- release
|
||||
- release
|
||||
- feat/GHZSCY-6578
|
||||
@ -107,7 +107,6 @@ android {
|
||||
buildConfigField "String", "WEIBO_APPKEY", "\"${WEIBO_APPKEY}\""
|
||||
// 一体包的32位畅玩游戏助手包名
|
||||
buildConfigField "String", "EXT_PACKAGE_NAME", "\"${rootProject.ext.EXT_PACKAGE_NAME}\""
|
||||
buildConfigField "String", "VA_VERSION_NAME", "\"${rootProject.ext.VA_VERSION}\""
|
||||
}
|
||||
|
||||
// gradle 2.2以上默认同时启用v1和v2(优先用于Android N)
|
||||
@ -218,6 +217,9 @@ android {
|
||||
buildConfigField "String", "QUICK_LOGIN_APPKEY", "\"${DEV_QUICK_LOGIN_APPKEY}\""
|
||||
buildConfigField "String", "DEV_CSJ_APPID", "\"${DEV_CSJ_APPID}\""
|
||||
buildConfigField "String", "CSJ_APPID", "\"${CSJ_APPID}\""
|
||||
|
||||
buildConfigField "String", "VA_VERSION_NAME", "\"${rootProject.ext.VA_VERSION}-debug\""
|
||||
manifestPlaceholders.put("VA_VERSION_NAME", "${rootProject.ext.VA_VERSION}-debug")
|
||||
}
|
||||
|
||||
// publish, 发布时候使用的 flavor,接口仅包含正式环境
|
||||
@ -231,6 +233,9 @@ android {
|
||||
buildConfigField "String", "QUICK_LOGIN_APPKEY", "\"${QUICK_LOGIN_APPKEY}\""
|
||||
buildConfigField "String", "DEV_CSJ_APPID", "\"${CSJ_APPID}\""
|
||||
buildConfigField "String", "CSJ_APPID", "\"${CSJ_APPID}\""
|
||||
|
||||
buildConfigField "String", "VA_VERSION_NAME", "\"${rootProject.ext.VA_VERSION}\""
|
||||
manifestPlaceholders.put("VA_VERSION_NAME", "${rootProject.ext.VA_VERSION}")
|
||||
}
|
||||
|
||||
tea {
|
||||
@ -244,7 +249,10 @@ android {
|
||||
buildConfigField "String", "DEV_CSJ_APPID", "\"${CSJ_APPID}\""
|
||||
buildConfigField "String", "CSJ_APPID", "\"${CSJ_APPID}\""
|
||||
|
||||
buildConfigField "String", "VA_VERSION_NAME", "\"${rootProject.ext.VA_VERSION}\""
|
||||
|
||||
manifestPlaceholders.put("APPLOG_SCHEME", "rangersapplog.byAx6uYt".toLowerCase())
|
||||
manifestPlaceholders.put("VA_VERSION_NAME", "${rootProject.ext.VA_VERSION}")
|
||||
}
|
||||
|
||||
kuaishou {
|
||||
@ -257,6 +265,9 @@ android {
|
||||
buildConfigField "String", "QUICK_LOGIN_APPKEY", "\"${QUICK_LOGIN_APPKEY}\""
|
||||
buildConfigField "String", "DEV_CSJ_APPID", "\"${CSJ_APPID}\""
|
||||
buildConfigField "String", "CSJ_APPID", "\"${CSJ_APPID}\""
|
||||
|
||||
buildConfigField "String", "VA_VERSION_NAME", "\"${rootProject.ext.VA_VERSION}\""
|
||||
manifestPlaceholders.put("VA_VERSION_NAME", "${rootProject.ext.VA_VERSION}")
|
||||
}
|
||||
|
||||
gdt {
|
||||
@ -269,6 +280,9 @@ android {
|
||||
buildConfigField "String", "QUICK_LOGIN_APPKEY", "\"${QUICK_LOGIN_APPKEY}\""
|
||||
buildConfigField "String", "DEV_CSJ_APPID", "\"${CSJ_APPID}\""
|
||||
buildConfigField "String", "CSJ_APPID", "\"${CSJ_APPID}\""
|
||||
|
||||
buildConfigField "String", "VA_VERSION_NAME", "\"${rootProject.ext.VA_VERSION}\""
|
||||
manifestPlaceholders.put("VA_VERSION_NAME", "${rootProject.ext.VA_VERSION}")
|
||||
}
|
||||
|
||||
sm {
|
||||
@ -281,6 +295,9 @@ android {
|
||||
buildConfigField "String", "QUICK_LOGIN_APPKEY", "\"${QUICK_LOGIN_APPKEY}\""
|
||||
buildConfigField "String", "DEV_CSJ_APPID", "\"${CSJ_APPID}\""
|
||||
buildConfigField "String", "CSJ_APPID", "\"${CSJ_APPID}\""
|
||||
|
||||
buildConfigField "String", "VA_VERSION_NAME", "\"${rootProject.ext.VA_VERSION}\""
|
||||
manifestPlaceholders.put("VA_VERSION_NAME", "${rootProject.ext.VA_VERSION}")
|
||||
}
|
||||
|
||||
// 港澳台
|
||||
@ -371,7 +388,7 @@ dependencies {
|
||||
|
||||
implementation "com.lg:easyfloat:${easyFloat}"
|
||||
|
||||
implementation ("com.lg:apksig:${apksig}") {
|
||||
implementation("com.lg:apksig:${apksig}") {
|
||||
exclude group: 'com.google.protobuf'
|
||||
}
|
||||
|
||||
@ -387,7 +404,7 @@ dependencies {
|
||||
implementation project(':vspace-bridge:vspace')
|
||||
implementation(project(':feature:xapk-installer'))
|
||||
|
||||
implementation (project(':module_common')) {
|
||||
implementation(project(':module_common')) {
|
||||
exclude group: 'androidx.swiperefreshlayout'
|
||||
}
|
||||
|
||||
@ -462,9 +479,11 @@ dependencies {
|
||||
implementation(project(':feature:sentry'))
|
||||
}
|
||||
|
||||
implementation(project(':feature:media_select'))
|
||||
|
||||
implementation(project(":module_va_api"))
|
||||
implementation(project(":va-archive-common"))
|
||||
if(!gradle.ext.excludeOptionalModules || gradle.ext.enableVa) {
|
||||
if (!gradle.ext.excludeOptionalModules || gradle.ext.enableVa) {
|
||||
implementation(project(":module_va_impl"))
|
||||
}
|
||||
debugImplementation "com.bytedance.tools.codelocator:codelocator-core:2.0.3"
|
||||
|
||||
@ -32,43 +32,11 @@ class ExternalGameUsage : ITestCase {
|
||||
it.titleTv.text = context.getString(R.string.title_install_external_game)
|
||||
it.iconIv.setImageResource(R.drawable.ic_personal_my_game)
|
||||
it.root.setOnClickListener {
|
||||
VHelper.connectService {
|
||||
context.startActivity(
|
||||
InstallExternalGameActivity.getIntent(context)
|
||||
.apply { flags = flags or Intent.FLAG_ACTIVITY_NEW_TASK })
|
||||
}
|
||||
context.startActivity(
|
||||
InstallExternalGameActivity.getIntent(context)
|
||||
.apply { flags = flags or Intent.FLAG_ACTIVITY_NEW_TASK })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun addInstallPluginButton(viewParent: ViewGroup) {
|
||||
buttonTemplate(viewParent, R.id.install_plugin) {
|
||||
it.titleTv.text = "安装64位插件"
|
||||
it.root.setOnClickListener {
|
||||
val file = File("/data/local/tmp/gh-plugins/artifacts.zip")
|
||||
if (file.exists()) {
|
||||
Utils.log(VHelper.LOG_TAG, "有本地更新文件: 64位插件")
|
||||
// TODO: 补充debug插件更新
|
||||
ToastUtils.showToast("暂未实现debug功能")
|
||||
} else {
|
||||
ToastUtils.showToast("data/local/tmp没有push文件")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun addInstallPlugin32Button(viewParent: ViewGroup) {
|
||||
buttonTemplate(viewParent, R.id.install_plugin_32) {
|
||||
it.titleTv.text = "安装32位插件"
|
||||
it.root.setOnClickListener {
|
||||
val file = File("/data/local/tmp/gh-plugins/artifacts32.zip")
|
||||
if (file.exists()) {
|
||||
// TODO: 补充debug插件更新
|
||||
ToastUtils.showToast("暂未实现debug功能")
|
||||
} else {
|
||||
ToastUtils.showToast("data/local/tmp没有push文件")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,7 +1,12 @@
|
||||
package com.gh.vspace.installexternalgames
|
||||
|
||||
import android.Manifest
|
||||
import android.app.Dialog
|
||||
import android.content.ComponentName
|
||||
import android.content.pm.PackageManager
|
||||
import android.os.Bundle
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import com.gh.common.util.DialogUtils
|
||||
import com.gh.gamecenter.R
|
||||
@ -40,6 +45,19 @@ class InstallExternalGameFragment : ToolbarFragment(), OnItemClickListener {
|
||||
|
||||
private lateinit var dialog: Dialog
|
||||
|
||||
|
||||
private val requestPermissionLauncher = registerForActivityResult<String, Boolean>(
|
||||
ActivityResultContracts.RequestPermission()
|
||||
) { result ->
|
||||
if (result == true) {
|
||||
// grant
|
||||
mViewModel.scanPaths()
|
||||
} else {
|
||||
// not grant
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setNavigationTitle(getString(com.gh.gamecenter.R.string.title_install_external_game))
|
||||
@ -56,11 +74,30 @@ class InstallExternalGameFragment : ToolbarFragment(), OnItemClickListener {
|
||||
)
|
||||
adapter.notifyDataSetChanged()
|
||||
}
|
||||
mViewModel.scanPaths()
|
||||
|
||||
|
||||
requestStoragePermission()
|
||||
}
|
||||
|
||||
private fun requestStoragePermission() {
|
||||
when {
|
||||
ContextCompat.checkSelfPermission(
|
||||
requireContext(),
|
||||
Manifest.permission.READ_EXTERNAL_STORAGE
|
||||
) == PackageManager.PERMISSION_GRANTED -> {
|
||||
mViewModel.scanPaths()
|
||||
}
|
||||
|
||||
shouldShowRequestPermissionRationale(Manifest.permission.READ_EXTERNAL_STORAGE) -> {
|
||||
requestPermissionLauncher.launch(Manifest.permission.READ_EXTERNAL_STORAGE)
|
||||
}
|
||||
|
||||
else -> {
|
||||
requestPermissionLauncher.launch(Manifest.permission.READ_EXTERNAL_STORAGE)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private fun initView() {
|
||||
dialog = DialogUtils.showWaitDialog(requireContext(), "")
|
||||
mBinding.externalGamesList.let {
|
||||
@ -94,9 +131,11 @@ class InstallExternalGameFragment : ToolbarFragment(), OnItemClickListener {
|
||||
OnItemClickListener.ClickType.CLICK_INSTALL -> {
|
||||
install(externalGameUiState)
|
||||
}
|
||||
|
||||
OnItemClickListener.ClickType.CLICK_UNINSTALL -> {
|
||||
uninstall(externalGameUiState)
|
||||
}
|
||||
|
||||
OnItemClickListener.ClickType.CLICK_START -> {
|
||||
start(externalGameUiState)
|
||||
}
|
||||
@ -104,9 +143,8 @@ class InstallExternalGameFragment : ToolbarFragment(), OnItemClickListener {
|
||||
}
|
||||
|
||||
private fun install(externalGameUiState: ExternalGameUiState) {
|
||||
val bit =
|
||||
externalGameUiState.externalGameEntity.cpuAbi.let { if (it.size == 1 && it.contains("armeabi-v7a")) "32" else "64" }
|
||||
|
||||
VHelper.disableLaunchGameAfterInstallation()
|
||||
VHelper.install(requireContext(), DownloadEntity().apply {
|
||||
externalGameUiState.externalGameEntity.apply {
|
||||
packageName = apkPackageName
|
||||
@ -114,20 +152,12 @@ class InstallExternalGameFragment : ToolbarFragment(), OnItemClickListener {
|
||||
}
|
||||
}, true)
|
||||
|
||||
|
||||
if (VHelper.showDialogIfVSpaceIsNeeded(
|
||||
requireContext(),
|
||||
"",
|
||||
externalGameUiState.externalGameEntity.appName,
|
||||
"",
|
||||
bit = bit
|
||||
)
|
||||
) return
|
||||
dialog.show()
|
||||
externalGameUiState.externalGameEntity.let {
|
||||
val intent = VirtualAppManager.getInstallIntent(context, it.apkPath, it.apkPackageName)
|
||||
requireActivity().startActivity(intent)
|
||||
VHelper.newCwValidateVspaceBeforeAction(
|
||||
requireContext(),null,
|
||||
) {
|
||||
dialog.show()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private fun uninstall(externalGameUiState: ExternalGameUiState) {
|
||||
@ -158,6 +188,12 @@ class InstallExternalGameFragment : ToolbarFragment(), OnItemClickListener {
|
||||
com.gh.gamecenter.BuildConfig.VA_VERSION_NAME,
|
||||
HaloApp.getInstance().oaid
|
||||
)
|
||||
intent.setComponent(
|
||||
ComponentName(
|
||||
com.gh.gamecenter.BuildConfig.APPLICATION_ID,
|
||||
VirtualAppManager.AIDL_SERVER_REMOTE_GUIDE_ACTIVITY
|
||||
)
|
||||
)
|
||||
requireActivity().startActivity(intent)
|
||||
}
|
||||
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
<resources>
|
||||
<string name="title_install_external_game">從SD卡安裝</string>
|
||||
<string name="text_install">安裝</string>
|
||||
<string name="text_update">更新</string>
|
||||
<string name="text_uninstall">卸載</string>
|
||||
<string name="text_start">啟動</string>
|
||||
</resources>
|
||||
@ -1,6 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<item name="install_game_from_external" type="id" />
|
||||
<item name="install_plugin" type="id" />
|
||||
<item name="install_plugin_32" type="id" />
|
||||
</resources>
|
||||
@ -185,6 +185,8 @@
|
||||
android:name="io.sentry.breadcrumbs.system-events"
|
||||
android:value="false" />
|
||||
|
||||
<meta-data android:name="module_version" android:value="${VA_VERSION_NAME}" />
|
||||
|
||||
<service android:name="com.gh.ndownload.NDownloadService" />
|
||||
|
||||
<activity
|
||||
@ -333,14 +335,6 @@
|
||||
android:screenOrientation="portrait"
|
||||
android:windowSoftInputMode="stateHidden" />
|
||||
|
||||
<activity
|
||||
android:name=".category.CategoryDirectoryActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name=".category.CategoryListActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.UserInfoActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
@ -462,9 +456,6 @@
|
||||
android:name="com.gh.gamecenter.video.game.GameVideoActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.qa.editor.LocalMediaActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.servers.GameServersActivity"
|
||||
@ -562,14 +553,6 @@
|
||||
android:name=".simulatorgame.SimulatorManagementActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name=".catalog.CatalogActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name=".catalog.NewCatalogListActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name=".forum.search.ForumOrUserSearchActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
@ -590,10 +573,6 @@
|
||||
android:name=".personal.DeliveryInfoActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name=".qa.editor.PreviewVideoActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name=".qa.video.publish.VideoPublishActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
@ -227,18 +227,7 @@ object AdDelegateHelper {
|
||||
/**
|
||||
* 是否大于开屏广告展示间隔时长
|
||||
*/
|
||||
private fun isMatchStartUpAdDisplayRule(): Boolean {
|
||||
mSplashAd?.displayRule?.run {
|
||||
if (adDisplayInterval > 0) {
|
||||
val lastShowTime = SPUtils.getLong(Constants.SP_LAST_SPLASH_AD_SHOW_TIME, 0L)
|
||||
val durationInMinutes = (System.currentTimeMillis() - lastShowTime).toFloat() / 1000 / 60
|
||||
return durationInMinutes > adDisplayInterval
|
||||
} else {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
private fun isMatchStartUpAdDisplayRule(): Boolean = isMatchAdDisplayRule(mSplashAd, Constants.SP_LAST_SPLASH_AD_SHOW_TIME)
|
||||
|
||||
/**
|
||||
* 是否大于广告管理展示间隔时长
|
||||
@ -292,6 +281,7 @@ object AdDelegateHelper {
|
||||
adViewHeightInDp: Float,
|
||||
startAdContainer: ViewGroup,
|
||||
sdkStartAdContainer: ViewGroup,
|
||||
sdkJumpBtn: TextView,
|
||||
adsViewGroup: FrameLayout,
|
||||
handler: BaseActivity.BaseHandler,
|
||||
isHotLaunch: Boolean,
|
||||
@ -313,6 +303,7 @@ object AdDelegateHelper {
|
||||
adViewHeightInDp,
|
||||
startAdContainer,
|
||||
sdkStartAdContainer,
|
||||
sdkJumpBtn,
|
||||
adsViewGroup,
|
||||
handler,
|
||||
isHotLaunch,
|
||||
@ -330,6 +321,7 @@ object AdDelegateHelper {
|
||||
adViewHeightInDp,
|
||||
startAdContainer,
|
||||
sdkStartAdContainer,
|
||||
sdkJumpBtn,
|
||||
adsViewGroup,
|
||||
handler,
|
||||
isHotLaunch,
|
||||
@ -353,6 +345,7 @@ object AdDelegateHelper {
|
||||
adViewHeightInDp: Float,
|
||||
startAdContainer: ViewGroup,
|
||||
sdkStartAdContainer: ViewGroup,
|
||||
sdkJumpBtn: TextView,
|
||||
adsViewGroup: FrameLayout,
|
||||
handler: BaseActivity.BaseHandler,
|
||||
isHotLaunch: Boolean,
|
||||
@ -374,6 +367,7 @@ object AdDelegateHelper {
|
||||
adViewHeightInDp,
|
||||
startAdContainer,
|
||||
sdkStartAdContainer,
|
||||
sdkJumpBtn,
|
||||
adsViewGroup,
|
||||
handler,
|
||||
isHotLaunch,
|
||||
@ -403,13 +397,14 @@ object AdDelegateHelper {
|
||||
sdkStartAdContainer.visibility = View.VISIBLE
|
||||
requestCsjSplashAd(
|
||||
activity,
|
||||
thirdPartyAd.slotId,
|
||||
adViewWidthInPx,
|
||||
adViewHeightInPx,
|
||||
adViewWidthInDp,
|
||||
adViewHeightInDp,
|
||||
sdkStartAdContainer,
|
||||
sdkJumpBtn,
|
||||
timeout,
|
||||
isHotLaunch,
|
||||
sdkSplashCallback
|
||||
)
|
||||
}
|
||||
@ -420,27 +415,65 @@ object AdDelegateHelper {
|
||||
*/
|
||||
private fun requestCsjSplashAd(
|
||||
activity: Activity,
|
||||
slotId: String,
|
||||
adViewWidthInPx: Int,
|
||||
adViewHeightInPx: Int,
|
||||
adViewWidthInDp: Float,
|
||||
adViewHeightInDp: Float,
|
||||
startAdContainer: ViewGroup,
|
||||
sdkJumpBtn: TextView,
|
||||
timeout: Int,
|
||||
isHotLaunch: Boolean,
|
||||
callback: (isSuccess: Boolean) -> Unit,
|
||||
) {
|
||||
if (mCsjAdImpl == null) {
|
||||
val thirdPartyAd = if (isHotLaunch) mSplashAd?.hotStartThirdPartyAd else mSplashAd?.thirdPartyAd
|
||||
if (mCsjAdImpl == null || thirdPartyAd == null) {
|
||||
callback.invoke(false)
|
||||
} else {
|
||||
sdkJumpBtn.setOnClickListener {
|
||||
callback.invoke(true)
|
||||
if (activity is BaseActivity) {
|
||||
activity.baseHandler.removeMessages(MainActivity.COUNTDOWN_SDK_AD)
|
||||
}
|
||||
}
|
||||
|
||||
val onAdShowAction = {
|
||||
sdkJumpBtn.visibility = View.VISIBLE
|
||||
if (activity is BaseActivity) {
|
||||
activity.baseHandler.sendEmptyMessageDelayed(MainActivity.COUNTDOWN_SDK_AD, 1000)
|
||||
}
|
||||
SensorsBridge.trackEvent("ThirdPartyAdShow",
|
||||
"ad_source", thirdPartyAd.sourceName,
|
||||
"ad_id", thirdPartyAd.slotId,
|
||||
"ad_format", mSplashAd?.typeChinese ?: "",
|
||||
"ad_placement", "光环启动",
|
||||
"launch_type", if (isHotLaunch) "热启动" else "冷启动",
|
||||
"ad_space_id", mSplashAd?.id ?: "",
|
||||
"ad_space_name", mSplashAd?.name ?: ""
|
||||
)
|
||||
}
|
||||
val onAdClickAction = {
|
||||
callback.invoke(true)
|
||||
SensorsBridge.trackEvent("ThirdPartyAdClick",
|
||||
"ad_source", thirdPartyAd.sourceName,
|
||||
"ad_id", thirdPartyAd.slotId,
|
||||
"ad_format", mSplashAd?.typeChinese ?: "",
|
||||
"ad_placement", "光环启动",
|
||||
"launch_type", if (isHotLaunch) "热启动" else "冷启动",
|
||||
"ad_space_id", mSplashAd?.id ?: "",
|
||||
"ad_space_name", mSplashAd?.name ?: ""
|
||||
)
|
||||
}
|
||||
mCsjAdImpl?.requestSplashAd(
|
||||
activity,
|
||||
slotId,
|
||||
thirdPartyAd.slotId,
|
||||
adViewWidthInPx,
|
||||
adViewHeightInPx,
|
||||
adViewWidthInDp,
|
||||
adViewHeightInDp,
|
||||
startAdContainer,
|
||||
timeout,
|
||||
onAdShowAction,
|
||||
onAdClickAction,
|
||||
callback,
|
||||
)
|
||||
}
|
||||
@ -457,6 +490,7 @@ object AdDelegateHelper {
|
||||
adViewHeightInDp: Float,
|
||||
startAdContainer: ViewGroup,
|
||||
sdkStartAdContainer: ViewGroup,
|
||||
sdkJumpBtn: TextView,
|
||||
adsViewGroup: FrameLayout,
|
||||
handler: BaseActivity.BaseHandler,
|
||||
isHotLaunch: Boolean,
|
||||
@ -474,6 +508,7 @@ object AdDelegateHelper {
|
||||
adViewHeightInDp,
|
||||
startAdContainer,
|
||||
sdkStartAdContainer,
|
||||
sdkJumpBtn,
|
||||
adsViewGroup,
|
||||
handler,
|
||||
isHotLaunch,
|
||||
@ -543,15 +578,14 @@ object AdDelegateHelper {
|
||||
), null, null
|
||||
)
|
||||
|
||||
adImage.visibleIf(true)
|
||||
ImageUtils.display(adImage, ad.img)
|
||||
|
||||
if (ad.isImageType) {
|
||||
adImage.visibleIf(true)
|
||||
adVideo.visibleIf(false)
|
||||
ImageUtils.display(adImage, ad.img)
|
||||
} else {
|
||||
adImage.visibleIf(false)
|
||||
adVideo.visibleIf(true)
|
||||
adVideo.startPlay(ad.img, ad.video.url)
|
||||
adVideo.startPlay(ad.video.url)
|
||||
}
|
||||
startAdContainer.setOnClickListener {
|
||||
// 拦截点击事件传递
|
||||
@ -622,9 +656,11 @@ object AdDelegateHelper {
|
||||
slotId: String,
|
||||
adContainerView: ViewGroup,
|
||||
expressViewWidth: Float,
|
||||
onAdShowAction: () -> Unit,
|
||||
onAdClickAction: () -> Unit,
|
||||
callback: (isSuccess: Boolean) -> Unit,
|
||||
) {
|
||||
mCsjAdImpl?.requestFlowAd(fragment, adContainerView, slotId, expressViewWidth, callback)
|
||||
mCsjAdImpl?.requestFlowAd(fragment, adContainerView, slotId, expressViewWidth, onAdShowAction, onAdClickAction, callback)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -635,6 +671,8 @@ object AdDelegateHelper {
|
||||
containerView: ViewGroup,
|
||||
ad: AdConfig.ThirdPartyAd,
|
||||
expressViewWidthInDp: Float,
|
||||
onAdShowAction: () -> Unit,
|
||||
onAdClickAction: () -> Unit,
|
||||
callback: (isSuccess: Boolean) -> Unit
|
||||
) {
|
||||
|
||||
@ -657,6 +695,28 @@ object AdDelegateHelper {
|
||||
slotId,
|
||||
expressViewWidthInDp,
|
||||
expressViewHeightInDp,
|
||||
onAdShowAction,
|
||||
onAdClickAction,
|
||||
callback
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取第三方 全屏/插屏 广告
|
||||
*/
|
||||
fun requestFullScreenAd(
|
||||
fragment: Fragment,
|
||||
ad: AdConfig.ThirdPartyAd,
|
||||
onAdShowAction: () -> Unit,
|
||||
onAdClickAction: () -> Unit,
|
||||
callback: (isSuccess: Boolean) -> Unit
|
||||
) {
|
||||
val slotId = ad.slotId
|
||||
mCsjAdImpl?.requestFullScreenAd(
|
||||
fragment,
|
||||
slotId,
|
||||
onAdShowAction,
|
||||
onAdClickAction,
|
||||
callback
|
||||
)
|
||||
}
|
||||
|
||||
@ -3,42 +3,105 @@ package com.gh.ad
|
||||
import android.content.Context
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
|
||||
import android.view.ViewStub
|
||||
import androidx.fragment.app.Fragment
|
||||
|
||||
import com.alibaba.android.arouter.facade.annotation.Route
|
||||
import com.gh.gamecenter.common.constant.Constants
|
||||
import com.gh.gamecenter.common.constant.RouteConsts
|
||||
import com.gh.gamecenter.common.provider.ILaunchAd
|
||||
import com.gh.gamecenter.common.utils.SensorsBridge
|
||||
import com.gh.gamecenter.common.utils.goneIf
|
||||
import com.gh.gamecenter.core.utils.DisplayUtils
|
||||
import com.gh.gamecenter.core.utils.SPUtils
|
||||
import com.gh.gamecenter.entity.AdConfig
|
||||
|
||||
@Route(path = RouteConsts.provider.vaAd, name = "畅玩启动页广告")
|
||||
class LaunchAdImpl : ILaunchAd {
|
||||
override fun init(context: Context?) {
|
||||
}
|
||||
|
||||
override fun requestAd(fragment: Fragment, container: ViewGroup, maskView: View) {
|
||||
override fun requestAd(fragment: Fragment, container: ViewGroup, maskView: View, topViewStub: ViewStub, bottomViewStub: ViewStub, adClickAction: () -> Unit): View {
|
||||
if (AdDelegateHelper.shouldShowHelperLaunchAd()) {
|
||||
val launchAd = AdDelegateHelper.vGameLaunchAd
|
||||
val showThirdPartyAd = launchAd?.displayRule?.adSource == AdDelegateHelper.AD_TYPE_SDK
|
||||
val thirdPartyAd = launchAd?.thirdPartyAd
|
||||
if (showThirdPartyAd && thirdPartyAd != null) {
|
||||
AdDelegateHelper.requestThirdPartyBannerAd(
|
||||
fragment,
|
||||
container,
|
||||
thirdPartyAd,
|
||||
DisplayUtils.getScreenWidthInDp(fragment.requireActivity()),
|
||||
) { isSuccess ->
|
||||
maskView.goneIf(!isSuccess)
|
||||
if (isSuccess) {
|
||||
SPUtils.setLong(Constants.SP_LAST_HELPER_LAUNCH_AD_SHOW_TIME, System.currentTimeMillis())
|
||||
}
|
||||
val onAdShowAction = {
|
||||
SensorsBridge.trackEvent("ThirdPartyAdShow",
|
||||
"ad_source", thirdPartyAd.sourceName,
|
||||
"ad_id", thirdPartyAd.slotId,
|
||||
"ad_format", launchAd.typeChinese,
|
||||
"ad_placement", AD_PLACEMENT,
|
||||
"ad_space_id", launchAd.id,
|
||||
"ad_space_name", launchAd.name
|
||||
)
|
||||
}
|
||||
val onAdClickAction = {
|
||||
SensorsBridge.trackEvent("ThirdPartyAdClick",
|
||||
"ad_source", thirdPartyAd.sourceName,
|
||||
"ad_id", thirdPartyAd.slotId,
|
||||
"ad_format", launchAd.typeChinese,
|
||||
"ad_placement", AD_PLACEMENT,
|
||||
"ad_space_id", launchAd.id,
|
||||
"ad_space_name", launchAd.name
|
||||
)
|
||||
adClickAction.invoke()
|
||||
}
|
||||
|
||||
if (launchAd.type == AdConfig.TYPE_BANNER) {
|
||||
requestBannerAd(fragment, container, maskView, thirdPartyAd, onAdShowAction, onAdClickAction)
|
||||
return topViewStub.inflate()
|
||||
} else if (launchAd.type == AdConfig.TYPE_INTERSTITIAL) {
|
||||
requestFullScreenAd(fragment, thirdPartyAd, onAdShowAction, onAdClickAction)
|
||||
return bottomViewStub.inflate()
|
||||
}
|
||||
}
|
||||
}
|
||||
return bottomViewStub.inflate()
|
||||
}
|
||||
|
||||
private fun requestBannerAd(
|
||||
fragment: Fragment,
|
||||
container: ViewGroup,
|
||||
maskView: View,
|
||||
thirdPartyAd: AdConfig.ThirdPartyAd,
|
||||
onAdShowAction: () -> Unit,
|
||||
onAdClickAction: () -> Unit,
|
||||
) {
|
||||
AdDelegateHelper.requestThirdPartyBannerAd(
|
||||
fragment,
|
||||
container,
|
||||
thirdPartyAd,
|
||||
DisplayUtils.getScreenWidthInDp(fragment.requireActivity()),
|
||||
onAdShowAction,
|
||||
onAdClickAction
|
||||
) { isSuccess ->
|
||||
maskView.goneIf(!isSuccess)
|
||||
if (isSuccess) {
|
||||
SPUtils.setLong(Constants.SP_LAST_HELPER_LAUNCH_AD_SHOW_TIME, System.currentTimeMillis())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun requestFullScreenAd(
|
||||
fragment: Fragment,
|
||||
thirdPartyAd: AdConfig.ThirdPartyAd,
|
||||
onAdShowAction: () -> Unit,
|
||||
onAdClickAction: () -> Unit
|
||||
) {
|
||||
AdDelegateHelper.requestFullScreenAd(
|
||||
fragment,
|
||||
thirdPartyAd,
|
||||
onAdShowAction,
|
||||
onAdClickAction
|
||||
) { isSuccess ->
|
||||
if (isSuccess) {
|
||||
SPUtils.setLong(Constants.SP_LAST_HELPER_LAUNCH_AD_SHOW_TIME, System.currentTimeMillis())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val AD_PLACEMENT = "畅玩启动"
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,12 +1,11 @@
|
||||
package com.gh.ad
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.util.AttributeSet
|
||||
import com.facebook.drawee.view.SimpleDraweeView
|
||||
import android.view.WindowManager
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.utils.ImageUtils
|
||||
import com.gh.gamecenter.video.detail.CustomManager
|
||||
import com.shuyu.gsyvideoplayer.utils.Debuger
|
||||
import com.shuyu.gsyvideoplayer.utils.GSYVideoType
|
||||
import com.shuyu.gsyvideoplayer.utils.GSYVideoType.SCREEN_TYPE_FULL
|
||||
import com.shuyu.gsyvideoplayer.video.StandardGSYVideoPlayer
|
||||
@ -18,18 +17,14 @@ class SplashAdVideoView @JvmOverloads constructor(
|
||||
) :
|
||||
StandardGSYVideoPlayer(context, attrs) {
|
||||
|
||||
|
||||
fun startPlay(cover: String, url: String) {
|
||||
fun startPlay(url: String) {
|
||||
GSYVideoType.setShowType(SCREEN_TYPE_FULL)
|
||||
GSYVideoType.setRenderType(GSYVideoType.SUFRACE)
|
||||
CustomManager.getCustomManager(getKey()).isNeedMute = true
|
||||
|
||||
setUp(url, true, "")
|
||||
|
||||
val ivCover = findViewById<SimpleDraweeView>(R.id.thumbImage)
|
||||
ImageUtils.display(ivCover, cover)
|
||||
setNeedAutoAdaptation(false)
|
||||
isLooping = true
|
||||
startPlayLogic()
|
||||
}
|
||||
|
||||
@ -49,6 +44,31 @@ class SplashAdVideoView @JvmOverloads constructor(
|
||||
return R.layout.layout_splash_ad_video
|
||||
}
|
||||
|
||||
override fun onAutoCompletion() {
|
||||
setStateAndUi(CURRENT_STATE_AUTO_COMPLETE);
|
||||
|
||||
mSaveChangeViewTIme = 0
|
||||
mCurrentPosition = 0
|
||||
|
||||
if (!mIfCurrentIsFullscreen) {
|
||||
getGSYVideoManager().setLastListener(null)
|
||||
}
|
||||
mAudioManager.abandonAudioFocus(onAudioFocusChangeListener);
|
||||
if (mContext is Activity) {
|
||||
try {
|
||||
(mContext as Activity).getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
releaseNetWorkState()
|
||||
|
||||
if (mVideoAllCallBack != null && isCurrentMediaListener()) {
|
||||
mVideoAllCallBack.onAutoComplete(mOriginUrl, mTitle, this)
|
||||
}
|
||||
mHadPlay = false
|
||||
}
|
||||
|
||||
fun clearAll() {
|
||||
GSYVideoType.setShowType(GSYVideoType.SCREEN_TYPE_DEFAULT)
|
||||
GSYVideoType.setRenderType(GSYVideoType.TEXTURE)
|
||||
|
||||
@ -21,6 +21,8 @@ import com.gh.common.view.RichEditor
|
||||
import com.gh.gamecenter.CropImageActivity
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.base.activity.ToolBarActivity
|
||||
import com.gh.gamecenter.common.entity.LocalVideoEntity
|
||||
import com.gh.gamecenter.feature.selector.LocalMediaActivity
|
||||
import com.gh.gamecenter.common.utils.*
|
||||
import com.gh.gamecenter.core.AppExecutor
|
||||
import com.gh.gamecenter.core.runOnIoThread
|
||||
@ -30,6 +32,7 @@ import com.gh.gamecenter.feature.entity.GameEntity
|
||||
import com.gh.gamecenter.qa.editor.*
|
||||
import com.gh.gamecenter.feature.entity.AnswerEntity
|
||||
import com.gh.gamecenter.feature.entity.ArticleEntity
|
||||
import com.gh.gamecenter.feature.selector.ChooseType
|
||||
import com.gh.gamecenter.qa.entity.EditorInsertEntity
|
||||
import com.gh.gamecenter.video.poster.PosterEditActivity
|
||||
import com.gh.gamecenter.video.upload.UploadManager
|
||||
@ -502,7 +505,7 @@ abstract class BaseRichEditorActivity<VM : BaseRichEditorViewModel> constructor(
|
||||
startActivityForResult(
|
||||
LocalMediaActivity.getIntent(
|
||||
this@BaseRichEditorActivity,
|
||||
LocalMediaActivity.ChooseType.VIDEO,
|
||||
ChooseType.VIDEO,
|
||||
maxChooseCount,
|
||||
if (mtaEventName() == "提问帖") "发提问帖" else "发帖子"
|
||||
), INSERT_MEDIA_VIDEO_CODE
|
||||
@ -531,7 +534,7 @@ abstract class BaseRichEditorActivity<VM : BaseRichEditorViewModel> constructor(
|
||||
val maxChooseCount = if (imageCount + 10 <= MAX_IMAGE_COUNT) 10 else MAX_IMAGE_COUNT - imageCount
|
||||
val intent = LocalMediaActivity.getIntent(
|
||||
this@BaseRichEditorActivity,
|
||||
LocalMediaActivity.ChooseType.IMAGE,
|
||||
ChooseType.IMAGE,
|
||||
maxChooseCount,
|
||||
if (mtaEventName() == "提问帖") "发提问帖" else "发帖子"
|
||||
)
|
||||
|
||||
@ -20,7 +20,7 @@ import com.gh.gamecenter.core.runOnUiThread
|
||||
import com.gh.gamecenter.core.utils.MD5Utils
|
||||
import com.gh.gamecenter.core.utils.ToastUtils
|
||||
import com.gh.gamecenter.entity.ForumDetailEntity
|
||||
import com.gh.gamecenter.entity.LocalVideoEntity
|
||||
import com.gh.gamecenter.common.entity.LocalVideoEntity
|
||||
import com.gh.gamecenter.entity.QuoteCountEntity
|
||||
import com.gh.gamecenter.qa.BbsType
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager
|
||||
@ -39,8 +39,6 @@ import retrofit2.HttpException
|
||||
import java.io.File
|
||||
import java.io.FileOutputStream
|
||||
import java.util.*
|
||||
import kotlin.collections.ArrayList
|
||||
import kotlin.collections.HashMap
|
||||
import kotlin.collections.LinkedHashMap
|
||||
import kotlin.collections.set
|
||||
|
||||
|
||||
@ -268,10 +268,6 @@ object DefaultUrlHandler {
|
||||
directToGameVideo(context, id, entrance, "")
|
||||
}
|
||||
|
||||
EntranceConsts.HOST_CATEGORY -> {
|
||||
val title = uri.getQueryParameter("title")
|
||||
DirectUtils.directCategoryDirectory(context, id, title ?: "", entrance, "")
|
||||
}
|
||||
EntranceConsts.HOST_COLUMN_COLLECTION -> {
|
||||
val name = uri.getQueryParameter("name")
|
||||
DirectUtils.directToColumnCollection(context, id, -1, entrance, name ?: "")
|
||||
|
||||
@ -6,8 +6,8 @@ class DownloadChainBuilder {
|
||||
|
||||
private var processEndCallback: ((asVGame: Boolean, Any?) -> Unit)? = null
|
||||
|
||||
fun setProcessEndCallback(callback: (asVGame: Boolean, Any?) -> Unit): DownloadChainBuilder {
|
||||
processEndCallback = callback
|
||||
fun setProcessEndCallback(gameId: String, callback: (asVGame: Boolean, Any?) -> Unit): DownloadChainBuilder {
|
||||
processEndCallback = VaPluginDownloadWrapper(gameId = gameId, callback = callback) // 其他需要添加行为的装饰者可以一直包装A(B(C(callback))), 执行顺序 A->B->C->callback
|
||||
return this
|
||||
}
|
||||
|
||||
|
||||
@ -0,0 +1,12 @@
|
||||
package com.gh.common.chain
|
||||
|
||||
import com.gh.vspace.VHelper
|
||||
|
||||
class VaPluginDownloadWrapper(val gameId: String, val callback: (Boolean, Any?) -> Unit) : (Boolean, Any?) -> Unit {
|
||||
override fun invoke(asVGame: Boolean, any: Any?) {
|
||||
callback.invoke(asVGame, any)
|
||||
if (asVGame) {
|
||||
VHelper.initVaPlugin(gameId)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -7,6 +7,7 @@ import android.os.Build;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.gh.common.util.PackageHelper;
|
||||
@ -46,6 +47,7 @@ import org.json.JSONObject;
|
||||
import java.io.IOException;
|
||||
import java.util.Locale;
|
||||
|
||||
import io.reactivex.Observable;
|
||||
import io.reactivex.Single;
|
||||
import io.reactivex.SingleSource;
|
||||
import io.reactivex.functions.Function;
|
||||
@ -78,10 +80,10 @@ public class Config {
|
||||
private static NewApiSettingsEntity.NightMode mNightModeSetting;
|
||||
private static SimulatorEntity mNewSimulatorEntity;
|
||||
private static VSetting mVSetting;
|
||||
private static VNewSetting mVNewSetting;
|
||||
private volatile static VNewSetting mVNewSetting;
|
||||
|
||||
private static AppEntity mNew32UpdateEntity;
|
||||
public static BehaviorSubject<VNewSetting> vNewSettingSubject = BehaviorSubject.create();
|
||||
private static BehaviorSubject<VNewSetting> vNewSettingSubject = BehaviorSubject.create();
|
||||
private static GameGuidePopupEntity mGameGuidePopupEntity;
|
||||
private static SharedPreferences mDefaultSharedPreferences;
|
||||
|
||||
@ -212,6 +214,16 @@ public class Config {
|
||||
return mVNewSetting;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public static Observable<VNewSetting> getVNewSettingObservable() {
|
||||
if (mVNewSetting != null) {
|
||||
return Observable.just(mVNewSetting);
|
||||
} else {
|
||||
return vNewSettingSubject.hide();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Nullable
|
||||
public static AppEntity getNew32UpdateEntity() {
|
||||
return mNew32UpdateEntity;
|
||||
|
||||
@ -172,7 +172,7 @@ public class BindingAdapters {
|
||||
builder.addHandler(new OverseaDownloadHandler());
|
||||
builder.addHandler(new CheckDownloadHandler());
|
||||
|
||||
builder.setProcessEndCallback((asVGame, isSubscribe) -> {
|
||||
builder.setProcessEndCallback(gameEntity.getId(), (asVGame, isSubscribe) -> {
|
||||
download(v.getContext(),
|
||||
progressBar,
|
||||
gameEntity,
|
||||
@ -197,7 +197,7 @@ public class BindingAdapters {
|
||||
builder.addHandler(new GamePermissionHandler());
|
||||
builder.addHandler(new VersionNumberHandler());
|
||||
|
||||
builder.setProcessEndCallback((asVGame, isSubscribe) -> {
|
||||
builder.setProcessEndCallback(gameEntity.getId(), (asVGame, isSubscribe) -> {
|
||||
DownloadDialog.showDownloadDialog(
|
||||
v.getContext(),
|
||||
gameEntity,
|
||||
|
||||
@ -0,0 +1,52 @@
|
||||
package com.gh.common.prioritychain
|
||||
|
||||
import android.content.Context
|
||||
import android.view.LayoutInflater
|
||||
import android.widget.FrameLayout
|
||||
import com.airbnb.lottie.LottieAnimationView
|
||||
import com.gh.gamecenter.common.constant.Constants
|
||||
import com.gh.gamecenter.core.utils.SPUtils
|
||||
import com.gh.gamecenter.databinding.LayoutCommunityHomeVideoGuideBinding
|
||||
|
||||
class CommunityHomeGuideHandler(
|
||||
priority: Int,
|
||||
private val context: Context,
|
||||
private val decorView: FrameLayout?,
|
||||
private val videoLottie: LottieAnimationView?
|
||||
) : PriorityChainHandler(priority) {
|
||||
|
||||
init {
|
||||
updateStatus(STATUS_VALID)
|
||||
}
|
||||
|
||||
override fun onProcess(): Boolean {
|
||||
return if (SPUtils.getBoolean(Constants.SP_SHOW_COMMUNITY_HOME_VIDEO_GUIDE, true)) {
|
||||
showHomeVideoGuide(context, decorView, videoLottie)
|
||||
processNext()
|
||||
true
|
||||
} else {
|
||||
processNext()
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun showHomeVideoGuide(context: Context, decorView: FrameLayout?, videoLottie: LottieAnimationView?) {
|
||||
val guideLayoutBinding = LayoutCommunityHomeVideoGuideBinding.inflate(
|
||||
LayoutInflater.from(context),
|
||||
decorView,
|
||||
true
|
||||
)
|
||||
guideLayoutBinding.root.setOnClickListener { view ->
|
||||
decorView?.removeView(view)
|
||||
SPUtils.setBoolean(Constants.SP_SHOW_COMMUNITY_HOME_VIDEO_GUIDE, false)
|
||||
|
||||
videoLottie?.playAnimation()
|
||||
SPUtils.setLong(
|
||||
Constants.SP_COMMUNITY_HOME_VIDEO_LOTTIE_LAST_PLAY_TIME,
|
||||
System.currentTimeMillis()
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,16 @@
|
||||
package com.gh.common.prioritychain
|
||||
|
||||
import com.gh.gamecenter.home.video.ScrollCalculatorHelper
|
||||
|
||||
class VideoHandler(priority: Int, val scrollCalculatorHelper: ScrollCalculatorHelper): PriorityChainHandler(priority) {
|
||||
|
||||
init {
|
||||
updateStatus(STATUS_VALID)
|
||||
}
|
||||
|
||||
override fun onProcess(): Boolean {
|
||||
scrollCalculatorHelper.enableAndPlayIfValid()
|
||||
return true
|
||||
}
|
||||
|
||||
}
|
||||
@ -2,12 +2,15 @@ package com.gh.common.provider
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
import com.alibaba.android.arouter.facade.annotation.Route
|
||||
import com.gh.common.util.EntranceUtils
|
||||
import com.gh.gamecenter.common.avoidcallback.Callback
|
||||
import com.gh.gamecenter.common.constant.RouteConsts
|
||||
import com.gh.gamecenter.core.provider.IEntranceUtilsProvider
|
||||
import com.lightgame.utils.AppManager
|
||||
|
||||
@Route(path = RouteConsts.provider.entranceUtils, name = "EntranceUtils暴露服务")
|
||||
class EntranceUtilsProviderImpl : IEntranceUtilsProvider {
|
||||
@ -20,11 +23,16 @@ class EntranceUtilsProviderImpl : IEntranceUtilsProvider {
|
||||
}
|
||||
|
||||
override fun jumpActivityWithCallback(context: Context, bundle: Bundle, callback: () -> Unit) {
|
||||
EntranceUtils.jumpActivity(context, null, bundle, object : Callback {
|
||||
override fun onActivityResult(resultCode: Int, data: Intent?) {
|
||||
callback()
|
||||
}
|
||||
})
|
||||
if (context is FragmentActivity && !context.supportFragmentManager.isDestroyed) {
|
||||
EntranceUtils.jumpActivityCompat(context, bundle, null, object : Callback {
|
||||
override fun onActivityResult(resultCode: Int, data: Intent?) {
|
||||
callback()
|
||||
}
|
||||
})
|
||||
} else {
|
||||
EntranceUtils.jumpActivityCompat(AppManager.getInstance().currentActivity(), bundle)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
override fun init(context: Context?) {
|
||||
|
||||
@ -74,7 +74,7 @@ public class CheckLoginUtils {
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putString(EntranceConsts.KEY_ENTRANCE, entrance);
|
||||
bundle.putString(EntranceConsts.KEY_TO, LoginActivity.class.getName());
|
||||
EntranceUtils.jumpActivity(context, nextToBundle, bundle, (resultCode, data) -> {
|
||||
EntranceUtils.jumpActivityCompat(context, bundle, nextToBundle, (resultCode, data) -> {
|
||||
if (isTriggerNextStep && listener != null && isLogin()) {
|
||||
listener.onLogin();
|
||||
}
|
||||
|
||||
@ -19,8 +19,6 @@ import com.gh.common.util.EntranceUtils.jumpActivity
|
||||
import com.gh.common.util.EntranceUtils.jumpActivityCompat
|
||||
import com.gh.gamecenter.*
|
||||
import com.gh.gamecenter.amway.AmwayActivity
|
||||
import com.gh.gamecenter.catalog.CatalogActivity
|
||||
import com.gh.gamecenter.category.CategoryDirectoryActivity
|
||||
import com.gh.gamecenter.category2.CategoryV2Activity
|
||||
import com.gh.gamecenter.common.base.activity.BaseActivity
|
||||
import com.gh.gamecenter.common.base.activity.BaseActivity_TabLayout
|
||||
@ -151,14 +149,12 @@ object DirectUtils {
|
||||
"qqqun",
|
||||
"tag",
|
||||
"all_community_article",
|
||||
"category",
|
||||
"block",
|
||||
"column_collection",
|
||||
"server",
|
||||
"top_game_comment",
|
||||
"wechat_bind",
|
||||
"video",
|
||||
"catalog",
|
||||
"category_v2",
|
||||
"common_collection",
|
||||
"game_list",
|
||||
@ -285,10 +281,6 @@ object DirectUtils {
|
||||
)
|
||||
)
|
||||
|
||||
"category", "分类" -> directCategoryDirectory(context, linkEntity.link!!, linkEntity.text!!)
|
||||
|
||||
"catalog" -> directCatalog(context, linkEntity.link!!, linkEntity.text!!, entrance, path)
|
||||
|
||||
"category_v2" -> directCategoryV2(
|
||||
context,
|
||||
linkEntity.link!!,
|
||||
@ -1423,47 +1415,6 @@ object DirectUtils {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 跳转分类
|
||||
*/
|
||||
@JvmStatic
|
||||
fun directCategoryDirectory(
|
||||
context: Context,
|
||||
categoryId: String,
|
||||
categoryTitle: String,
|
||||
entrance: String? = null,
|
||||
path: String? = ""
|
||||
) {
|
||||
if (categoryId.isEmpty()) return
|
||||
val bundle = Bundle()
|
||||
bundle.putString(KEY_TO, CategoryDirectoryActivity::class.java.name)
|
||||
bundle.putString(KEY_CATEGORY_ID, categoryId)
|
||||
bundle.putString(KEY_CATEGORY_TITLE, categoryTitle)
|
||||
bundle.putString(KEY_ENTRANCE, entrance ?: ENTRANCE_BROWSER)
|
||||
bundle.putString(KEY_PATH, path)
|
||||
jumpActivity(context, bundle)
|
||||
}
|
||||
|
||||
/**
|
||||
* 跳转新分类
|
||||
*/
|
||||
@JvmStatic
|
||||
fun directCatalog(
|
||||
context: Context,
|
||||
catalogId: String,
|
||||
catalogTitle: String,
|
||||
entrance: String? = null,
|
||||
path: String? = "",
|
||||
) {
|
||||
if (catalogId.isEmpty()) return
|
||||
val bundle = Bundle()
|
||||
bundle.putString(KEY_TO, CatalogActivity::class.java.name)
|
||||
bundle.putString(KEY_CATALOG_ID, catalogId)
|
||||
bundle.putString(KEY_CATALOG_TITLE, catalogTitle)
|
||||
bundle.putString(KEY_ENTRANCE, BaseActivity.mergeEntranceAndPath(entrance, path))
|
||||
jumpActivity(context, bundle)
|
||||
}
|
||||
|
||||
/**
|
||||
* 跳转新分类2.0
|
||||
*/
|
||||
|
||||
@ -37,10 +37,10 @@ import com.gh.gamecenter.core.utils.*
|
||||
import com.gh.gamecenter.feature.entity.GameEntity
|
||||
import com.gh.gamecenter.feature.entity.PluginLocation
|
||||
import com.gh.gamecenter.feature.exposure.ExposureEvent
|
||||
import com.gh.gamecenter.feature.minigame.MiniGameItemHelper
|
||||
import com.gh.gamecenter.feature.view.DownloadButton
|
||||
import com.gh.gamecenter.gamedetail.dialog.GamePermissionDialogFragment
|
||||
import com.gh.gamecenter.manager.PackagesManager
|
||||
import com.gh.gamecenter.feature.minigame.MiniGameItemHelper
|
||||
import com.gh.gamecenter.teenagermode.TeenagerModeActivity
|
||||
import com.gh.vspace.VHelper
|
||||
import com.lightgame.download.DownloadConfig
|
||||
@ -697,7 +697,7 @@ object DownloadItemUtils {
|
||||
// 为 downloadButton 添加游戏实体,供点击的时候上报用
|
||||
downloadBtn.putObject(gameEntity)
|
||||
|
||||
val gamePermissionDialogFragment = (context as AppCompatActivity).supportFragmentManager.findFragmentByTag(
|
||||
val gamePermissionDialogFragment = (context as? AppCompatActivity)?.supportFragmentManager?.findFragmentByTag(
|
||||
GamePermissionDialogFragment::class.java.name
|
||||
) as GamePermissionDialogFragment?
|
||||
gamePermissionDialogFragment?.dismissAllowingStateLoss()
|
||||
@ -910,7 +910,7 @@ object DownloadItemUtils {
|
||||
addHandler(CheckStoragePermissionHandler())
|
||||
addHandler(VersionNumberHandler())
|
||||
}
|
||||
.setProcessEndCallback { _, _ ->
|
||||
.setProcessEndCallback(gameEntity.id) { _, _ ->
|
||||
DownloadDialog.showDownloadDialog(view.context, gameEntity, traceEvent, entrance, location)
|
||||
}
|
||||
.buildHandlerChain()
|
||||
@ -953,7 +953,7 @@ object DownloadItemUtils {
|
||||
addHandler(LandPageAddressHandler())
|
||||
addHandler(CheckDownloadHandler())
|
||||
}
|
||||
.setProcessEndCallback { asVGame, isSubscribe ->
|
||||
.setProcessEndCallback(gameEntity.id) { asVGame, isSubscribe ->
|
||||
download(context, gameEntity, downloadBtn, entrance, location, asVGame, isSubscribe as Boolean, traceEvent)
|
||||
}
|
||||
.buildHandlerChain()
|
||||
@ -972,7 +972,7 @@ object DownloadItemUtils {
|
||||
addHandler(OverseaDownloadHandler())
|
||||
addHandler(CheckDownloadHandler())
|
||||
}
|
||||
.setProcessEndCallback { asVGame, isSubscribe ->
|
||||
.setProcessEndCallback(gameEntity.id) { asVGame, isSubscribe ->
|
||||
download(context, gameEntity, downloadBtn, entrance, location, asVGame, isSubscribe as Boolean, traceEvent)
|
||||
}
|
||||
.buildHandlerChain()
|
||||
@ -991,7 +991,7 @@ object DownloadItemUtils {
|
||||
addHandler(ValidateVSpaceHandler())
|
||||
addHandler(CheckDownloadHandler())
|
||||
}
|
||||
.setProcessEndCallback { asVGame, isSubscribe ->
|
||||
.setProcessEndCallback(gameEntity.id) { asVGame, isSubscribe ->
|
||||
download(context, gameEntity, downloadBtn, entrance, location, asVGame, isSubscribe as Boolean, traceEvent)
|
||||
}
|
||||
.buildHandlerChain()
|
||||
@ -1004,7 +1004,7 @@ object DownloadItemUtils {
|
||||
addHandler(DownloadDialogHelperHandler())
|
||||
addHandler(CheckDownloadHandler())
|
||||
}
|
||||
.setProcessEndCallback { _, isSubscribe ->
|
||||
.setProcessEndCallback(gameEntity.id) { _, isSubscribe ->
|
||||
plugin(context, gameEntity, downloadBtn, entrance, location, isSubscribe as Boolean, traceEvent)
|
||||
}
|
||||
.buildHandlerChain()
|
||||
@ -1089,7 +1089,7 @@ object DownloadItemUtils {
|
||||
DownloadChainBuilder()
|
||||
.apply {
|
||||
addHandler(LandPageAddressHandler())
|
||||
}.setProcessEndCallback { asVGame, _ ->
|
||||
}.setProcessEndCallback(gameEntity.id) { asVGame, _ ->
|
||||
DownloadDialogHelper.findAvailableDialogAndShow(context, gameEntity, apk) {
|
||||
DialogUtils.checkDownload(
|
||||
context,
|
||||
|
||||
@ -69,11 +69,13 @@ object DownloadObserver {
|
||||
DownloadDataHelper.uploadDownloadEvent(downloadEntity)
|
||||
}
|
||||
|
||||
if (DownloadStatus.hijack == downloadEntity.status) {
|
||||
val status = downloadEntity.status
|
||||
|
||||
if (DownloadStatus.hijack == status) {
|
||||
// 链接被劫持
|
||||
processHijack(downloadEntity)
|
||||
return
|
||||
} else if (DownloadStatus.notfound == downloadEntity.status) {
|
||||
} else if (DownloadStatus.notfound == status) {
|
||||
// 404 Not Found
|
||||
// 删除任务
|
||||
downloadEntity.status = DownloadStatus.cancel
|
||||
@ -127,10 +129,9 @@ object DownloadObserver {
|
||||
extraConfig = DialogHelper.Config(centerTitle = true, centerContent = true)
|
||||
)
|
||||
return
|
||||
} else if (DownloadStatus.neterror == downloadEntity.status
|
||||
|| DownloadStatus.timeout == downloadEntity.status
|
||||
|| DownloadStatus.diskioerror == downloadEntity.status
|
||||
|| DownloadStatus.diskisfull == downloadEntity.status
|
||||
} else if (DownloadStatus.neterror == status
|
||||
|| DownloadStatus.diskioerror == status
|
||||
|| DownloadStatus.timeout == status
|
||||
) {
|
||||
if (mRetryableHashMap[downloadEntity.url] == true
|
||||
&& NetworkUtils.isWifiConnected(HaloApp.getInstance().application)
|
||||
@ -139,9 +140,7 @@ object DownloadObserver {
|
||||
mRetryableHashMap[downloadEntity.url] = false
|
||||
Utils.log(TAG, "下载重试->" + downloadEntity.toJson())
|
||||
} else {
|
||||
if (DownloadStatus.diskisfull == downloadEntity.status) {
|
||||
ToastUtils.toast("磁盘已满,请清理空间后重试下载")
|
||||
} else if (DownloadStatus.diskioerror == downloadEntity.status) {
|
||||
if (DownloadStatus.diskioerror == status) {
|
||||
ToastUtils.toast("磁盘 IO 异常,请稍后重试")
|
||||
} else {
|
||||
ToastUtils.toast("网络不稳定,下载任务已暂停")
|
||||
@ -150,17 +149,21 @@ object DownloadObserver {
|
||||
DataLogUtils.uploadNeterrorLog(mApplication, downloadEntity)
|
||||
Utils.log(TAG, "下载自动暂停->" + downloadEntity.toJson())
|
||||
}
|
||||
} else if (DownloadStatus.redirected == downloadEntity.status) {
|
||||
} else if (DownloadStatus.diskisfull == status) {
|
||||
ToastUtils.toast("磁盘已满,请清理空间后重试下载")
|
||||
|
||||
downloadManager.pause(downloadEntity.url)
|
||||
} else if (DownloadStatus.redirected == status) {
|
||||
Utils.log(TAG, "重定向完毕")
|
||||
DownloadDataHelper.uploadRedirectEvent(downloadEntity)
|
||||
} else if (DownloadStatus.unqualified == downloadEntity.status) {
|
||||
} else if (DownloadStatus.unqualified == status) {
|
||||
// 未成年
|
||||
RealNameHelper.showRealNameUnqualifiedDialog(downloadEntity)
|
||||
|
||||
// 删除任务
|
||||
downloadEntity.status = DownloadStatus.cancel
|
||||
downloadManager.cancel(downloadEntity.url)
|
||||
} else if (DownloadStatus.unavailable == downloadEntity.status) {
|
||||
} else if (DownloadStatus.unavailable == status) {
|
||||
// 未接入防沉迷系统
|
||||
val currentActivity = AppManager.getInstance().currentActivity()
|
||||
|
||||
@ -179,7 +182,7 @@ object DownloadObserver {
|
||||
// 删除任务
|
||||
downloadEntity.status = DownloadStatus.cancel
|
||||
downloadManager.cancel(downloadEntity.url)
|
||||
} else if (DownloadStatus.isCertificating == downloadEntity.status) {
|
||||
} else if (DownloadStatus.isCertificating == status) {
|
||||
// 未接入防沉迷系统
|
||||
val currentActivity = AppManager.getInstance().currentActivity()
|
||||
|
||||
@ -207,21 +210,21 @@ object DownloadObserver {
|
||||
// 删除任务
|
||||
downloadEntity.status = DownloadStatus.cancel
|
||||
downloadManager.cancel(downloadEntity.url)
|
||||
} else if (DownloadStatus.uncertificated == downloadEntity.status) {
|
||||
} else if (DownloadStatus.uncertificated == status) {
|
||||
// 未实名
|
||||
RealNameHelper.showRealNameUncertificatedDialog(downloadEntity)
|
||||
|
||||
// 删除任务
|
||||
downloadEntity.status = DownloadStatus.cancel
|
||||
downloadManager.cancel(downloadEntity.url)
|
||||
} else if (DownloadStatus.banned == downloadEntity.status) {
|
||||
} else if (DownloadStatus.banned == status) {
|
||||
ToastUtils.showToast("网络异常")
|
||||
// 删除任务
|
||||
downloadEntity.status = DownloadStatus.cancel
|
||||
downloadManager.cancel(downloadEntity.url)
|
||||
}
|
||||
|
||||
if (DownloadStatus.done == downloadEntity.status) {
|
||||
if (DownloadStatus.done == status) {
|
||||
if (mDoneDebouncePair?.first != downloadEntity.url) {
|
||||
mDoneDebouncePair = Pair(downloadEntity.url, System.currentTimeMillis())
|
||||
performDownloadCompleteAction(downloadEntity, downloadManager)
|
||||
@ -241,7 +244,7 @@ object DownloadObserver {
|
||||
DownloadNotificationHelper.addOrUpdateDownloadNotification(downloadEntity)
|
||||
|
||||
// 如果已下载大小发生变化,表示成功恢复下载,则重置重试标记
|
||||
if (downloadEntity.status == DownloadStatus.downloading) {
|
||||
if (status == DownloadStatus.downloading) {
|
||||
mRetryableHashMap[downloadEntity.url] = true
|
||||
}
|
||||
}
|
||||
|
||||
@ -27,7 +27,6 @@ import com.gh.gamecenter.core.utils.ClassUtils;
|
||||
import com.gh.gamecenter.core.utils.GsonUtils;
|
||||
import com.gh.gamecenter.core.utils.SPUtils;
|
||||
import com.halo.assistant.HaloApp;
|
||||
import com.lightgame.utils.AppManager;
|
||||
import com.lightgame.utils.Utils;
|
||||
|
||||
import org.json.JSONException;
|
||||
@ -38,7 +37,18 @@ import java.util.Set;
|
||||
|
||||
public class EntranceUtils {
|
||||
|
||||
public static void jumpActivity(Context context, Bundle bundle) {
|
||||
jumpActivityCompat(context, bundle, null, null);
|
||||
}
|
||||
|
||||
public static void jumpActivityCompat(Context context, Bundle bundle) {
|
||||
jumpActivityCompat(context, bundle, null,null);
|
||||
}
|
||||
|
||||
public static void jumpActivityCompat(Context context,
|
||||
Bundle bundle,
|
||||
@Nullable Bundle nextToBundle,
|
||||
@Nullable Callback callback) {
|
||||
bundle.putBoolean(KEY_REQUIRE_REDIRECT, true);
|
||||
|
||||
if (HaloApp.getInstance().isRunningForeground || HaloApp.getInstance().isAlreadyUpAndRunning) {
|
||||
@ -48,66 +58,27 @@ public class EntranceUtils {
|
||||
if (clazz == null) clazz = MainActivity.class;
|
||||
if (ToolbarFragment.class.isAssignableFrom(clazz)) { // 兼容ToolbarFragment
|
||||
ToolBarActivity.startFragmentNewTask(context, (Class<? extends ToolbarFragment>) clazz, bundle);
|
||||
} else {
|
||||
Intent intent1 = new Intent(context, clazz);
|
||||
intent1.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
// 如果 activity 名称有 singleton 的就添加 reorder_to_front 标签 (有点粗暴有点蠢,但暂时就先这样吧 :C )
|
||||
if (clazz.getSimpleName().toLowerCase().contains("singleton")) {
|
||||
intent1.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
|
||||
}
|
||||
intent1.putExtras(bundle);
|
||||
context.startActivity(intent1);
|
||||
}
|
||||
} else {
|
||||
// 应用未在运行
|
||||
context.startActivity(SplashScreenActivity.getSplashScreenIntent(context, bundle));
|
||||
}
|
||||
}
|
||||
|
||||
public static void jumpActivity(Context context, Bundle bundle) {
|
||||
bundle.putBoolean(KEY_REQUIRE_REDIRECT, true);
|
||||
|
||||
if (AppManager.getInstance().findActivity(MainActivity.class) != null) {
|
||||
// 应用正在运行,前台或后台,且MainActivity在栈中
|
||||
String to = bundle.getString(KEY_TO);
|
||||
Class<?> clazz = ClassUtils.forName(to);
|
||||
if (clazz == null) clazz = MainActivity.class;
|
||||
if (ToolbarFragment.class.isAssignableFrom(clazz)) { // 兼容ToolbarFragment
|
||||
ToolBarActivity.startFragmentNewTask(context, (Class<? extends ToolbarFragment>) clazz, bundle);
|
||||
} else {
|
||||
Intent intent1 = new Intent(context, clazz);
|
||||
intent1.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
// 如果 activity 名称有 singleton 的就添加 reorder_to_front 标签 (有点粗暴有点蠢,但暂时就先这样吧 :C )
|
||||
if (clazz.getSimpleName().toLowerCase().contains("singleton")) {
|
||||
intent1.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
|
||||
}
|
||||
intent1.putExtras(bundle);
|
||||
context.startActivity(intent1);
|
||||
}
|
||||
} else {
|
||||
// 应用未在运行
|
||||
context.startActivity(SplashScreenActivity.getSplashScreenIntent(context, bundle));
|
||||
}
|
||||
}
|
||||
|
||||
public static void jumpActivity(Context context, Bundle nextToBundle, Bundle bundle, Callback callback) {
|
||||
bundle.putBoolean(KEY_REQUIRE_REDIRECT, true);
|
||||
|
||||
if (AppManager.getInstance().findActivity(MainActivity.class) != null) {
|
||||
// 应用正在运行,前台或后台,且MainActivity在栈中
|
||||
String to = bundle.getString(KEY_TO);
|
||||
Class<?> clazz = ClassUtils.forName(to);
|
||||
if (clazz == null) clazz = MainActivity.class;
|
||||
if (ToolbarFragment.class.isAssignableFrom(clazz)) { // 兼容ToolbarFragment
|
||||
ToolBarActivity.startFragmentNewTask(context, (Class<? extends ToolbarFragment>) clazz, bundle);
|
||||
} else {
|
||||
} else if (callback != null ) {
|
||||
Intent intent1 = new Intent(context, clazz);
|
||||
//TODO:添加FLAG_ACTIVITY_NEW_TASK会导致一跳转页面callback就被调用
|
||||
//intent1.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
intent1.putExtras(bundle);
|
||||
|
||||
AvoidOnResultManager.Companion.getInstance((AppCompatActivity) context)
|
||||
.startForResult(intent1, callback);
|
||||
if (context instanceof AppCompatActivity) {
|
||||
AvoidOnResultManager.Companion.getInstance((AppCompatActivity) context)
|
||||
.startForResult(intent1, callback);
|
||||
} else {
|
||||
// 不要回调,正常跳转
|
||||
context.startActivity(intent1);
|
||||
}
|
||||
} else {
|
||||
Intent intent1 = new Intent(context, clazz);
|
||||
intent1.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
// 如果 activity 名称有 singleton 的就添加 reorder_to_front 标签 (有点粗暴有点蠢,但暂时就先这样吧 :C )
|
||||
if (clazz.getSimpleName().toLowerCase().contains("singleton")) {
|
||||
intent1.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
|
||||
}
|
||||
intent1.putExtras(bundle);
|
||||
context.startActivity(intent1);
|
||||
}
|
||||
} else {
|
||||
// 应用未在运行
|
||||
|
||||
@ -7,6 +7,7 @@ import com.gh.gamecenter.common.utils.toObject
|
||||
import com.gh.gamecenter.feature.entity.GameEntity
|
||||
import com.gh.gamecenter.entity.SubjectEntity
|
||||
import com.gh.gamecenter.common.retrofit.Response
|
||||
import com.gh.gamecenter.manager.PackagesManager
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager
|
||||
import com.halo.assistant.HaloApp
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
@ -111,6 +112,14 @@ object GameSubstituteRepositoryHelper {
|
||||
}
|
||||
}
|
||||
|
||||
// 检查是否已安装该游戏 id
|
||||
if (PackagesManager.getInstalledDataByGameId(game.id) != null) {
|
||||
// 将该位置的游戏标记为需要替换
|
||||
positionOfGameToBeReplacedList.add(index)
|
||||
thisPositionNeedToBeReplaced = true
|
||||
break
|
||||
}
|
||||
|
||||
// 若此游戏所包含的 apk 没有已安装,那么再检查是否已安装有预设相关包名
|
||||
if (!thisPositionNeedToBeReplaced) {
|
||||
var relatedPackageList = arrayListOf<String>()
|
||||
|
||||
@ -308,7 +308,7 @@ object GameUtils {
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否以畅玩游戏的形式来处理
|
||||
* 是否默认以畅玩游戏的形式来处理
|
||||
*/
|
||||
@JvmStatic
|
||||
fun shouldPerformAsVGame(gameEntity: GameEntity): Boolean {
|
||||
|
||||
@ -734,18 +734,6 @@ public class LogUtils {
|
||||
LoghubUtils.log(object, LOG_STORE_EVENT, false);
|
||||
}
|
||||
|
||||
public static void logNewCatalogAppearanceEvent(String entrance, String key) {
|
||||
logCatalogEvent("access_to_classification", entrance, key, -1, -1, -1, -1);
|
||||
}
|
||||
|
||||
public static void logSubCatalogClickEvent(String entrance, String key, int seq1) {
|
||||
logCatalogEvent("click_first_classification", entrance, key, seq1, -1, -1, -1);
|
||||
}
|
||||
|
||||
public static void logSubCatalogContentClickEvent(String entrance, String key, int seq1, int seq2) {
|
||||
logCatalogEvent("click_secondary_classification", entrance, key, seq1, seq2, -1, -1);
|
||||
}
|
||||
|
||||
public static void logSpecialCatalogContentClickEvent(String entrance, String key, int seq1, int seqContent) {
|
||||
logCatalogEvent("click_content", entrance, key, seq1, -1, seqContent, -1);
|
||||
}
|
||||
|
||||
@ -30,6 +30,9 @@ object NewFlatLogUtils {
|
||||
private const val EVENT_LOGIN_FROM_GHZS_SHOW = "halo_fun_login_from_ghzs_show"
|
||||
private const val EVENT_LOGIN_FROM_GHZS_CLICK = "halo_fun_login_from_ghzs_click"
|
||||
|
||||
private const val EVENT_INSTALLED_LAUNCH_DIALOG_SHOW = "halo_fun_installed_launch_dialog_show"
|
||||
private const val EVENT_INSTALLED_LAUNCH_DIALOG_CLICK = "halo_fun_installed_launch_dialog_click"
|
||||
|
||||
private fun log(jsonObject: JSONObject, logStore: String = "event", uploadImmediately: Boolean = false) {
|
||||
Utils.log("NewFlatLogUtils", jsonObject.toString(4))
|
||||
LoghubUtils.log(jsonObject, logStore, uploadImmediately, true)
|
||||
@ -550,6 +553,8 @@ object NewFlatLogUtils {
|
||||
// 搜索-点击搜索榜单内容
|
||||
@JvmStatic
|
||||
fun logSearchClickRankDetail(
|
||||
key: String,
|
||||
rankType: String,
|
||||
rankName: String,
|
||||
rankSequence: String,
|
||||
linkId: String,
|
||||
@ -558,6 +563,8 @@ object NewFlatLogUtils {
|
||||
) {
|
||||
val json = json {
|
||||
KEY_EVENT to "search_click_rank_detail"
|
||||
"key" to key
|
||||
"rank_type" to rankType
|
||||
"rank_name" to rankName
|
||||
"rank_sequence" to rankSequence
|
||||
"link_id" to linkId
|
||||
@ -2688,4 +2695,73 @@ object NewFlatLogUtils {
|
||||
parseAndPutMeta()(this)
|
||||
}.let(::log)
|
||||
}
|
||||
|
||||
fun logHaloFunInstalledLaunchDialogShow() {
|
||||
json {
|
||||
KEY_EVENT to EVENT_INSTALLED_LAUNCH_DIALOG_SHOW
|
||||
parseAndPutMeta()(this)
|
||||
}.let(::log)
|
||||
}
|
||||
|
||||
fun logHaloFunInstalledLaunchDialogClick(
|
||||
gameId: String,
|
||||
gameName: String,
|
||||
buttonType: String
|
||||
) {
|
||||
json {
|
||||
KEY_EVENT to EVENT_INSTALLED_LAUNCH_DIALOG_CLICK
|
||||
"game_id" to gameId
|
||||
"game_name" to gameName
|
||||
"button_type" to buttonType
|
||||
parseAndPutMeta()(this)
|
||||
}.let(::log)
|
||||
}
|
||||
|
||||
// 用户访问分流器
|
||||
fun logByPassBrowsing(
|
||||
source: String,
|
||||
bypassName: String,
|
||||
bypassId: String,
|
||||
branchId: String,
|
||||
branchName: String,
|
||||
inProcessTime: Int,
|
||||
bypassVisitTime: Int,
|
||||
linkType: String,
|
||||
linkId: String,
|
||||
linkText: String,
|
||||
bypassStatus: Int
|
||||
) {
|
||||
json {
|
||||
KEY_EVENT to "BypassBrowsing"
|
||||
"source" to source
|
||||
"bypass_name" to bypassName
|
||||
"bypass_id" to bypassId
|
||||
"branch_id" to branchId
|
||||
"branch_name" to branchName
|
||||
"inprocess_time" to inProcessTime
|
||||
"bypass_visit_time" to bypassVisitTime
|
||||
"link_type" to linkType
|
||||
"link_id" to linkId
|
||||
"link_text" to linkText
|
||||
"bypass_status" to bypassStatus
|
||||
parseAndPutMeta()(this)
|
||||
}.let(::log)
|
||||
}
|
||||
|
||||
// 分流失败
|
||||
fun logFailByPass(
|
||||
source: String,
|
||||
bypassName: String,
|
||||
bypassId: String,
|
||||
defeatedReason: String
|
||||
) {
|
||||
json {
|
||||
KEY_EVENT to "FailBypass"
|
||||
"source" to source
|
||||
"bypass_name" to bypassName
|
||||
"bypass_id" to bypassId
|
||||
"defeated_reason" to defeatedReason
|
||||
parseAndPutMeta()(this)
|
||||
}.let(::log)
|
||||
}
|
||||
}
|
||||
@ -90,7 +90,7 @@ object PackageChangeHelper : DefaultLifecycleObserver {
|
||||
pendingPackageTriple = null
|
||||
pendingGhId = null
|
||||
|
||||
PackageRepository.addInstalledGame(packageName)
|
||||
PackageRepository.addInstalledGame(PackageRepository.packageFilterManager, packageName)
|
||||
|
||||
// 添加到额外的包名白名单,下次启动同时查询此包的安装情况
|
||||
PackageHelper.updateAdditionalWhiteListPackageName(packageName = packageName, isAdd = true)
|
||||
|
||||
@ -81,23 +81,28 @@ object PackageHelper {
|
||||
|
||||
// 评论黑名单包名列表,避免用户安装了 Xposed Installer 这样的工具,也能在包含该安装包的游戏详情页评论
|
||||
private var _commentPackageNameBlackList = arrayListOf<String>()
|
||||
val commentPackageNameBlackList: ArrayList<String> = _commentPackageNameBlackList
|
||||
val commentPackageNameBlackList: ArrayList<String>
|
||||
get() = _commentPackageNameBlackList
|
||||
|
||||
// 关闭下载的包列表
|
||||
private var _downloadPackageNameBlackList = arrayListOf<String>()
|
||||
val downloadPackageNameBlackList: ArrayList<String> = _downloadPackageNameBlackList
|
||||
val downloadPackageNameBlackList: ArrayList<String>
|
||||
get() = _downloadPackageNameBlackList
|
||||
|
||||
// 本地已安装的包去掉关闭下载的包后的列表
|
||||
private var _validLocalPackageNameSet = hashSetOf<String>()
|
||||
val validLocalPackageNameSet: HashSet<String> = _validLocalPackageNameSet
|
||||
val validLocalPackageNameSet: HashSet<String>
|
||||
get() = _validLocalPackageNameSet
|
||||
|
||||
// 游戏包名匹配列表
|
||||
private var _relatedPackageList = arrayListOf<SettingsEntity.GameWithPackages>()
|
||||
val relatedPackageList: ArrayList<SettingsEntity.GameWithPackages> = _relatedPackageList
|
||||
val relatedPackageList: ArrayList<SettingsEntity.GameWithPackages>
|
||||
get() = _relatedPackageList
|
||||
|
||||
// 接口控制的已安装应用列表获取开关状态 (UI 显示)
|
||||
private var _installedPackageApiSwitchStatusLiveData = MutableLiveData<Boolean>()
|
||||
val installedPackageApiSwitchStatusLiveData: LiveData<Boolean> = _installedPackageApiSwitchStatusLiveData
|
||||
val installedPackageApiSwitchStatusLiveData: LiveData<Boolean>
|
||||
get() = _installedPackageApiSwitchStatusLiveData
|
||||
|
||||
// 本地已安装包的列表
|
||||
var localPackageNameSet = hashSetOf<String>()
|
||||
@ -541,6 +546,7 @@ object PackageHelper {
|
||||
Utils.log(TAG, "addInstalledButMissingPackages 需要请求接口获取的包数量为 ${installedPackageNameSet.size}")
|
||||
|
||||
PackageRepository.addInstalledGames(
|
||||
packageFilterManager = PackageRepository.packageFilterManager,
|
||||
pkgNameList = ArrayList(installedPackageNameSet),
|
||||
updateInstallStatus = true
|
||||
)
|
||||
|
||||
@ -14,6 +14,7 @@ import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.PowerManager;
|
||||
import android.text.TextUtils;
|
||||
import android.util.AndroidException;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
@ -222,8 +223,19 @@ public class PackageUtils {
|
||||
if (metaDate != null) {
|
||||
return metaDate.get(name);
|
||||
}
|
||||
} catch (NameNotFoundException e) {
|
||||
// e.printStackTrace();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
|
||||
if (e instanceof AndroidException) {
|
||||
// 有些设备会出现 DeadSystemException
|
||||
SentryHelper.INSTANCE.onEvent(
|
||||
"GET_META_DATA_ERROR",
|
||||
"packageName",
|
||||
packageName,
|
||||
"exception_digest",
|
||||
e.getLocalizedMessage()
|
||||
);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@ -627,8 +639,19 @@ public class PackageUtils {
|
||||
try {
|
||||
return HaloApp.getInstance().getApplication().getPackageManager().getPackageInfo(packageName,
|
||||
PackageManager.COMPONENT_ENABLED_STATE_DEFAULT).versionName;
|
||||
} catch (NameNotFoundException e) {
|
||||
// do nothing
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
|
||||
if (e instanceof AndroidException) {
|
||||
// 有些设备会出现 DeadSystemException
|
||||
SentryHelper.INSTANCE.onEvent(
|
||||
"GET_VERSION_NAME_ERROR",
|
||||
"packageName",
|
||||
packageName,
|
||||
"exception_digest",
|
||||
e.getLocalizedMessage()
|
||||
);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@ -640,8 +663,18 @@ public class PackageUtils {
|
||||
try {
|
||||
return HaloApp.getInstance().getApplication().getPackageManager().getPackageInfo(packageName,
|
||||
PackageManager.COMPONENT_ENABLED_STATE_DEFAULT).versionCode;
|
||||
} catch (NameNotFoundException e) {
|
||||
// do nothing
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
if (e instanceof AndroidException) {
|
||||
// 有些设备会出现 DeadSystemException
|
||||
SentryHelper.INSTANCE.onEvent(
|
||||
"GET_VERSION_CODE_ERROR",
|
||||
"packageName",
|
||||
packageName,
|
||||
"exception_digest",
|
||||
e.getLocalizedMessage()
|
||||
);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -654,8 +687,18 @@ public class PackageUtils {
|
||||
try {
|
||||
PackageManager packageManager = context.getApplicationContext().getPackageManager();
|
||||
return packageManager.getApplicationIcon(packageName);
|
||||
} catch (NameNotFoundException e) {
|
||||
// do nothing
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
if (e instanceof AndroidException) {
|
||||
// 有些设备会出现 DeadSystemException
|
||||
SentryHelper.INSTANCE.onEvent(
|
||||
"GET_ICON_ERROR",
|
||||
"packageName",
|
||||
packageName,
|
||||
"exception_digest",
|
||||
e.getLocalizedMessage()
|
||||
);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@ -706,8 +749,19 @@ public class PackageUtils {
|
||||
jsonObject.put("version", packageInfo.versionName);
|
||||
}
|
||||
return jsonObject;
|
||||
} catch (JSONException | NameNotFoundException e) {
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
if (e instanceof AndroidException) {
|
||||
// 有些设备会出现 DeadSystemException
|
||||
SentryHelper.INSTANCE.onEvent(
|
||||
"GET_APP_BASIC_INFO_BY_PACKAGE_NAME",
|
||||
"packageName",
|
||||
packageName,
|
||||
"exception_digest",
|
||||
e.getLocalizedMessage()
|
||||
);
|
||||
}
|
||||
|
||||
return jsonObject;
|
||||
}
|
||||
}
|
||||
|
||||
@ -82,6 +82,7 @@ object ViewPagerFragmentHelper {
|
||||
const val TYPE_TOOLKIT = "toolkit" // 工具箱
|
||||
|
||||
fun createFragment(parentFragment: Fragment?, bundle: Bundle, linkEntity: LinkEntity, isTabWrapper: Boolean): Fragment {
|
||||
val superiorChain = if (parentFragment is ISuperiorChain) parentFragment else null
|
||||
return when (linkEntity.type) {
|
||||
// 游戏详情页
|
||||
TYPE_GAME -> {
|
||||
@ -90,11 +91,12 @@ object ViewPagerFragmentHelper {
|
||||
}
|
||||
// 我的光环
|
||||
TYPE_MY_HALO -> {
|
||||
val superiorChain = if (parentFragment is ISuperiorChain) parentFragment else null
|
||||
HaloPersonalFragment().setSuperiorChain(superiorChain).with(bundle)
|
||||
}
|
||||
// 社区首页
|
||||
TYPE_COMMUNITY_HOME -> CommunityHomeFragment().with(bundle)
|
||||
TYPE_COMMUNITY_HOME -> {
|
||||
CommunityHomeFragment().setSuperiorChain(superiorChain).with(bundle)
|
||||
}
|
||||
// 视频信息流
|
||||
TYPE_VIDEO_STREAM -> {
|
||||
bundle.putBoolean(EntranceConsts.KEY_IS_HOME_VIDEO, true)
|
||||
@ -148,11 +150,11 @@ object ViewPagerFragmentHelper {
|
||||
NewQuestionDetailFragment().with(bundle)
|
||||
}
|
||||
// 其他原来带Toolbar的Fragment
|
||||
else -> createToolbarWrapperFragment(bundle, linkEntity, isTabWrapper)
|
||||
else -> createToolbarWrapperFragment(parentFragment, bundle, linkEntity, isTabWrapper)
|
||||
}
|
||||
}
|
||||
|
||||
private fun createToolbarWrapperFragment(bundle: Bundle, entity: LinkEntity, isTabWrapper: Boolean): Fragment {
|
||||
private fun createToolbarWrapperFragment(parentFragment: Fragment?, bundle: Bundle, entity: LinkEntity, isTabWrapper: Boolean): Fragment {
|
||||
var className = ReloadFragment::class.java.name
|
||||
|
||||
when (entity.type) {
|
||||
|
||||
@ -1,331 +0,0 @@
|
||||
package com.gh.common.view
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.Color
|
||||
import android.util.AttributeSet
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.ImageView
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.PopupWindow
|
||||
import android.widget.TextView
|
||||
import androidx.annotation.ColorInt
|
||||
import androidx.core.content.ContextCompat
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.utils.setDrawableEnd
|
||||
import com.gh.gamecenter.common.utils.toColor
|
||||
import com.gh.gamecenter.common.utils.visibleIf
|
||||
import com.gh.gamecenter.entity.CatalogEntity
|
||||
import com.gh.gamecenter.entity.SubjectSettingEntity
|
||||
import com.google.android.flexbox.FlexboxLayout
|
||||
|
||||
class CatalogFilterView @JvmOverloads constructor(
|
||||
context: Context,
|
||||
attrs: AttributeSet? = null,
|
||||
defStyleAttr: Int = 0
|
||||
) : LinearLayout(context, attrs, defStyleAttr) {
|
||||
|
||||
private var mTypeTv: TextView
|
||||
private var mCatalogTv: TextView
|
||||
private var mSizeTv: TextView
|
||||
private var mTypeContainer: View
|
||||
private var mCatalogContainer: View
|
||||
private var mSizeContainer: View
|
||||
|
||||
private var mTypeFilterArray = ArrayList<SortType>()
|
||||
private var mCatalogFilterArray = ArrayList<CatalogEntity.SubCatalogEntity>()
|
||||
private var sizeFilterArray: ArrayList<SubjectSettingEntity.Size>? = null
|
||||
|
||||
private var mOnCatalogFilterSetupListener: OnCatalogFilterSetupListener? = null
|
||||
|
||||
private var mTypePopupWindow: PopupWindow? = null
|
||||
private var mCatalogPopupWindow: PopupWindow? = null
|
||||
private var mSizePopupWindow: PopupWindow? = null
|
||||
|
||||
init {
|
||||
View.inflate(context, R.layout.layout_catalog_filter, this)
|
||||
|
||||
mTypeTv = findViewById(R.id.type_tv)
|
||||
mCatalogTv = findViewById(R.id.catalog_tv)
|
||||
mSizeTv = findViewById(R.id.size_tv)
|
||||
mTypeContainer = findViewById(R.id.container_type)
|
||||
mCatalogContainer = findViewById(R.id.container_catalog)
|
||||
mSizeContainer = findViewById(R.id.container_size)
|
||||
|
||||
mTypeContainer.setOnClickListener {
|
||||
showSelectTypePopupWindow(this, mTypeTv, mTypeTv.text.toString())
|
||||
}
|
||||
|
||||
mCatalogContainer.setOnClickListener {
|
||||
showSelectCatalogPopupWindow(this, mCatalogTv, mCatalogTv.text.toString())
|
||||
}
|
||||
|
||||
mSizeContainer.setOnClickListener {
|
||||
showSelectSizePopupWindow(this, mSizeTv, mSizeTv.text.toString())
|
||||
}
|
||||
}
|
||||
|
||||
fun setTypeList(switch: CatalogEntity.CatalogSwitch) {
|
||||
switch.run {
|
||||
if ("on" == hotSort) mTypeFilterArray.add(SortType.RECOMMENDED)
|
||||
if ("on" == newSort) mTypeFilterArray.add(SortType.NEWEST)
|
||||
if ("on" == starSort) mTypeFilterArray.add(SortType.RATING)
|
||||
}
|
||||
if (mTypeFilterArray.isNotEmpty()) mTypeTv.text = mTypeFilterArray[0].value
|
||||
}
|
||||
|
||||
fun setCatalogList(subCatalogList: List<CatalogEntity.SubCatalogEntity>, initCatalogName: String) {
|
||||
mCatalogFilterArray = ArrayList(subCatalogList)
|
||||
mCatalogTv.text = initCatalogName
|
||||
}
|
||||
|
||||
fun setOnConfigSetupListener(onCatalogFilterSetupListener: OnCatalogFilterSetupListener) {
|
||||
mOnCatalogFilterSetupListener = onCatalogFilterSetupListener
|
||||
}
|
||||
|
||||
private fun toggleHighlightedTextView(targetTextView: TextView, highlightIt: Boolean) {
|
||||
if (highlightIt) {
|
||||
targetTextView.background = ContextCompat.getDrawable(targetTextView.context, R.drawable.bg_tag_text)
|
||||
targetTextView.setTextColor(Color.WHITE)
|
||||
} else {
|
||||
targetTextView.background = null
|
||||
targetTextView.setTextColor(R.color.text_757575.toColor(context))
|
||||
}
|
||||
}
|
||||
|
||||
private fun showSelectTypePopupWindow(containerView: View, typeTv: TextView, typeText: String) {
|
||||
typeTv.setTextColor(R.color.text_theme.toColor(context))
|
||||
typeTv.setDrawableEnd(R.drawable.ic_filter_arrow_up)
|
||||
|
||||
val inflater = LayoutInflater.from(typeTv.context)
|
||||
val layout = inflater.inflate(R.layout.layout_filter_size, null)
|
||||
val popupWindow = PopupWindow(
|
||||
layout,
|
||||
LayoutParams.MATCH_PARENT,
|
||||
LayoutParams.WRAP_CONTENT
|
||||
).apply { mTypePopupWindow = this }
|
||||
|
||||
val flexboxLayout = layout.findViewById<FlexboxLayout>(R.id.flexbox)
|
||||
val backgroundView = layout.findViewById<View>(R.id.background)
|
||||
|
||||
backgroundView.setOnClickListener {
|
||||
popupWindow.dismiss()
|
||||
}
|
||||
|
||||
for (type in mTypeFilterArray) {
|
||||
val item = inflater.inflate(R.layout.item_filter_size, flexboxLayout, false)
|
||||
|
||||
// 单列 3 个,强行设置宽度为屏幕的 1/3
|
||||
val width = typeTv.context.resources.displayMetrics.widthPixels / 3
|
||||
val height = item.layoutParams.height
|
||||
|
||||
item.layoutParams = ViewGroup.LayoutParams(width, height)
|
||||
flexboxLayout.addView(item)
|
||||
|
||||
val tv = item.findViewById<TextView>(R.id.size_tv)
|
||||
tv.text = type.value
|
||||
|
||||
toggleHighlightedTextView(tv, typeText == type.value)
|
||||
|
||||
tv.tag = type.value
|
||||
|
||||
item.setOnClickListener {
|
||||
toggleHighlightedTextView(tv, true)
|
||||
popupWindow.dismiss()
|
||||
typeTv.text = type.value
|
||||
|
||||
mOnCatalogFilterSetupListener?.onSetupSortType(type)
|
||||
}
|
||||
}
|
||||
|
||||
popupWindow.setOnDismissListener {
|
||||
typeTv.setTextColor(R.color.text_757575.toColor(context))
|
||||
typeTv.setDrawableEnd(R.drawable.ic_filter_arrow_down)
|
||||
mTypePopupWindow = null
|
||||
}
|
||||
|
||||
popupWindow.isTouchable = true
|
||||
popupWindow.isFocusable = true
|
||||
popupWindow.animationStyle = 0
|
||||
popupWindow.showAsDropDown(containerView, 0, 0)
|
||||
}
|
||||
|
||||
private fun showSelectCatalogPopupWindow(containerView: View, catalogTv: TextView, catalogText: String) {
|
||||
catalogTv.setTextColor(R.color.text_theme.toColor(context))
|
||||
catalogTv.setDrawableEnd(R.drawable.ic_filter_arrow_up)
|
||||
|
||||
val inflater = LayoutInflater.from(catalogTv.context)
|
||||
val layout = inflater.inflate(R.layout.layout_filter_size, null)
|
||||
val popupWindow = PopupWindow(
|
||||
layout,
|
||||
LayoutParams.MATCH_PARENT,
|
||||
LayoutParams.WRAP_CONTENT
|
||||
).apply { mCatalogPopupWindow = this }
|
||||
|
||||
val flexboxLayout = layout.findViewById<FlexboxLayout>(R.id.flexbox)
|
||||
val backgroundView = layout.findViewById<View>(R.id.background)
|
||||
|
||||
backgroundView.setOnClickListener {
|
||||
popupWindow.dismiss()
|
||||
}
|
||||
|
||||
for (entity in mCatalogFilterArray) {
|
||||
val item = inflater.inflate(R.layout.item_filter_size, flexboxLayout, false)
|
||||
|
||||
// 单列 3 个,强行设置宽度为屏幕的 1/3
|
||||
val width = catalogTv.context.resources.displayMetrics.widthPixels / 3
|
||||
val height = item.layoutParams.height
|
||||
|
||||
item.layoutParams = ViewGroup.LayoutParams(width, height)
|
||||
flexboxLayout.addView(item)
|
||||
|
||||
val tv = item.findViewById<TextView>(R.id.size_tv)
|
||||
val iv = item.findViewById<ImageView>(R.id.recommend_iv)
|
||||
tv.text = entity.name
|
||||
iv.visibleIf(entity.recommended)
|
||||
|
||||
toggleHighlightedTextView(tv, catalogText == entity.name)
|
||||
|
||||
tv.tag = entity.name
|
||||
|
||||
item.setOnClickListener {
|
||||
toggleHighlightedTextView(tv, true)
|
||||
popupWindow.dismiss()
|
||||
catalogTv.text = entity.name
|
||||
|
||||
mOnCatalogFilterSetupListener?.onSetupSortCatalog(entity)
|
||||
}
|
||||
}
|
||||
|
||||
popupWindow.setOnDismissListener {
|
||||
catalogTv.setTextColor(R.color.text_757575.toColor(context))
|
||||
catalogTv.setDrawableEnd(R.drawable.ic_filter_arrow_down)
|
||||
mCatalogPopupWindow = null
|
||||
}
|
||||
|
||||
popupWindow.isTouchable = true
|
||||
popupWindow.isFocusable = true
|
||||
popupWindow.animationStyle = 0
|
||||
popupWindow.showAsDropDown(containerView, 0, 0)
|
||||
}
|
||||
|
||||
private fun showSelectSizePopupWindow(containerView: View, sizeTv: TextView, sizeText: String) {
|
||||
sizeTv.setTextColor(R.color.text_theme.toColor(context))
|
||||
sizeTv.setDrawableEnd(R.drawable.ic_filter_arrow_up)
|
||||
|
||||
val inflater = LayoutInflater.from(sizeTv.context)
|
||||
val layout = inflater.inflate(R.layout.layout_filter_size, null)
|
||||
val popupWindow = PopupWindow(
|
||||
layout,
|
||||
LayoutParams.MATCH_PARENT,
|
||||
LayoutParams.WRAP_CONTENT
|
||||
).apply { mSizePopupWindow = this }
|
||||
|
||||
val flexboxLayout = layout.findViewById<FlexboxLayout>(R.id.flexbox)
|
||||
val backgroundView = layout.findViewById<View>(R.id.background)
|
||||
|
||||
sizeFilterArray = if (sizeFilterArray == null) {
|
||||
getDefaultSizeFilterArray()
|
||||
} else {
|
||||
sizeFilterArray?.apply {
|
||||
if (firstOrNull()?.text != "全部大小") {
|
||||
add(0, SubjectSettingEntity.Size(min = -1, max = -1, text = "全部大小"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
backgroundView.setOnClickListener {
|
||||
popupWindow.dismiss()
|
||||
}
|
||||
|
||||
for (size in sizeFilterArray!!) {
|
||||
val item = inflater.inflate(R.layout.item_filter_size, flexboxLayout, false)
|
||||
|
||||
// 单列 3 个,强行设置宽度为屏幕的 1/3
|
||||
val width = sizeTv.context.resources.displayMetrics.widthPixels / 3
|
||||
val height = item.layoutParams.height
|
||||
|
||||
item.layoutParams = ViewGroup.LayoutParams(width, height)
|
||||
flexboxLayout.addView(item)
|
||||
|
||||
val tv = item.findViewById<TextView>(R.id.size_tv)
|
||||
tv.text = size.text
|
||||
|
||||
toggleHighlightedTextView(tv, sizeText == size.text)
|
||||
|
||||
tv.tag = size.text
|
||||
|
||||
item.setOnClickListener {
|
||||
toggleHighlightedTextView(tv, true)
|
||||
popupWindow.dismiss()
|
||||
sizeTv.text = size.text
|
||||
|
||||
mOnCatalogFilterSetupListener?.onSetupSortSize(size)
|
||||
}
|
||||
}
|
||||
|
||||
popupWindow.setOnDismissListener {
|
||||
sizeTv.setTextColor(R.color.text_757575.toColor(context))
|
||||
sizeTv.setDrawableEnd(R.drawable.ic_filter_arrow_down)
|
||||
mSizePopupWindow = null
|
||||
}
|
||||
|
||||
popupWindow.isTouchable = true
|
||||
popupWindow.isFocusable = true
|
||||
popupWindow.animationStyle = 0
|
||||
popupWindow.showAsDropDown(containerView, 0, 0)
|
||||
}
|
||||
|
||||
private fun getDefaultSizeFilterArray(): ArrayList<SubjectSettingEntity.Size> {
|
||||
return arrayListOf<SubjectSettingEntity.Size>().apply {
|
||||
add(SubjectSettingEntity.Size(min = -1, max = -1, text = "全部大小"))
|
||||
add(SubjectSettingEntity.Size(min = -1, max = 100, text = "100M以下"))
|
||||
add(SubjectSettingEntity.Size(min = 100, max = 300, text = "100-300M"))
|
||||
add(SubjectSettingEntity.Size(min = 300, max = 500, text = "300-500M"))
|
||||
add(SubjectSettingEntity.Size(min = 500, max = 1000, text = "500M-1G"))
|
||||
add(SubjectSettingEntity.Size(min = 1000, max = -1, text = "1G以上"))
|
||||
}
|
||||
}
|
||||
|
||||
fun setRootBackgroundColor(@ColorInt color: Int) {
|
||||
findViewById<View>(R.id.config_controller).setBackgroundColor(color)
|
||||
}
|
||||
|
||||
fun setItemTextColor(@ColorInt color: Int) {
|
||||
mTypeTv.setTextColor(color)
|
||||
mCatalogTv.setTextColor(color)
|
||||
mSizeTv.setTextColor(color)
|
||||
}
|
||||
|
||||
fun updatePopupWindow() {
|
||||
when {
|
||||
mTypePopupWindow != null && mTypePopupWindow!!.isShowing -> {
|
||||
mTypePopupWindow?.dismiss()
|
||||
showSelectTypePopupWindow(this, mTypeTv, mTypeTv.text.toString())
|
||||
}
|
||||
|
||||
mCatalogPopupWindow != null && mCatalogPopupWindow!!.isShowing -> {
|
||||
mCatalogPopupWindow?.dismiss()
|
||||
showSelectCatalogPopupWindow(this, mCatalogTv, mCatalogTv.text.toString())
|
||||
}
|
||||
|
||||
mSizePopupWindow != null && mSizePopupWindow!!.isShowing -> {
|
||||
mSizePopupWindow?.dismiss()
|
||||
showSelectSizePopupWindow(this, mSizeTv, mSizeTv.text.toString())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
interface OnCatalogFilterSetupListener {
|
||||
fun onSetupSortSize(sortSize: SubjectSettingEntity.Size)
|
||||
fun onSetupSortType(sortType: SortType)
|
||||
fun onSetupSortCatalog(sortCatalog: CatalogEntity.SubCatalogEntity)
|
||||
}
|
||||
|
||||
enum class SortType(val value: String) {
|
||||
RECOMMENDED("热门推荐"),
|
||||
NEWEST("最新上线"),
|
||||
RATING("最高评分")
|
||||
}
|
||||
}
|
||||
@ -1,64 +0,0 @@
|
||||
package com.gh.common.view
|
||||
|
||||
import android.content.Context
|
||||
import android.util.AttributeSet
|
||||
import android.view.View
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.TextView
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.category.CategoryListActivity
|
||||
import com.gh.gamecenter.entity.CategoryEntity
|
||||
|
||||
class SubCategoryView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0) :
|
||||
LinearLayout(context, attrs, defStyleAttr) {
|
||||
|
||||
var leftTv: TextView
|
||||
var centerTv: TextView
|
||||
var rightTv: TextView
|
||||
|
||||
var leftDivider: View
|
||||
var rightDivider: View
|
||||
|
||||
var primeCategory: CategoryEntity? = null
|
||||
var categoryTitle: String? = ""
|
||||
|
||||
init {
|
||||
View.inflate(context, R.layout.layout_sub_category, this)
|
||||
|
||||
leftTv = findViewById(R.id.tv_left_sub_category)
|
||||
centerTv = findViewById(R.id.tv_center_sub_category)
|
||||
rightTv = findViewById(R.id.tv_right_sub_category)
|
||||
|
||||
leftDivider = findViewById(R.id.divider_left)
|
||||
rightDivider = findViewById(R.id.divider_right)
|
||||
}
|
||||
|
||||
fun setLeftCategory(category: CategoryEntity) {
|
||||
setCategory(leftTv, category)
|
||||
}
|
||||
|
||||
fun setCenterCategory(category: CategoryEntity) {
|
||||
setCategory(centerTv, category)
|
||||
leftDivider.visibility = View.VISIBLE
|
||||
}
|
||||
|
||||
fun setRightCategory(category: CategoryEntity) {
|
||||
setCategory(rightTv, category)
|
||||
rightDivider.visibility = View.VISIBLE
|
||||
}
|
||||
|
||||
private fun setCategory(tv: TextView, category: CategoryEntity) {
|
||||
tv.text = category.name
|
||||
tv.setOnClickListener {
|
||||
tv.context.startActivity(
|
||||
CategoryListActivity.getIntent(
|
||||
tv.context,
|
||||
categoryTitle!!,
|
||||
primeCategory!!,
|
||||
category.name!!
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -59,8 +59,8 @@ class GameDetailActivity : DownloadToolbarActivity() {
|
||||
}
|
||||
|
||||
override fun getBusinessId(): Pair<String, String> {
|
||||
val fragment = targetFragment as GameDetailFragment
|
||||
return if (fragment.arguments != null) {
|
||||
val fragment = targetFragment as? GameDetailFragment?
|
||||
return if (fragment?.arguments != null) {
|
||||
Pair(fragment.requireArguments().getString(EntranceConsts.KEY_GAMEID) ?: "", "")
|
||||
} else {
|
||||
super.getBusinessId()
|
||||
|
||||
@ -48,6 +48,7 @@ import com.gh.gamecenter.common.entity.SensorsEvent
|
||||
import com.gh.gamecenter.common.retrofit.Response
|
||||
import com.gh.gamecenter.common.utils.*
|
||||
import com.gh.gamecenter.common.utils.ImageUtils.getIdealImageUrl
|
||||
import com.gh.gamecenter.common.view.DragListener
|
||||
import com.gh.gamecenter.common.view.DraggableBigImageView
|
||||
import com.gh.gamecenter.common.view.Gh_RelativeLayout
|
||||
import com.gh.gamecenter.core.runOnIoThread
|
||||
@ -815,18 +816,18 @@ class ImageViewerActivity : BaseActivity(), OnPageChangeListener {
|
||||
if (mBigImageView == null) {
|
||||
mBigImageView = imageView
|
||||
}
|
||||
imageView.setDragListener(object : DraggableBigImageView.DragListener {
|
||||
override fun onRelease(draggableBigImageView: DraggableBigImageView, scale: Float) {
|
||||
imageView.setDragListener(object : DragListener {
|
||||
override fun onRelease(scale: Float) {
|
||||
updateOriginPosition(mViewPager.currentItem)
|
||||
performExitAnimation(draggableBigImageView, scale, isFadeOnly())
|
||||
performExitAnimation(imageView, scale, isFadeOnly())
|
||||
}
|
||||
|
||||
override fun onDrag(draggableBigImageView: DraggableBigImageView, fraction: Float) {
|
||||
override fun onDrag(fraction: Float) {
|
||||
mBackgroundView.alpha = 1 - fraction
|
||||
mIndicatorMask.visibility = View.GONE
|
||||
}
|
||||
|
||||
override fun onRestore(draggableBigImageView: DraggableBigImageView, fraction: Float) {
|
||||
override fun onRestore(fraction: Float) {
|
||||
mBackgroundView.alpha = 1F
|
||||
// mIndicatorMask.goneIf(mUrlList?.size == 1)
|
||||
if (mUrlList?.size != 1 || mAnswerEntity != null) {
|
||||
|
||||
@ -138,7 +138,6 @@ import io.reactivex.functions.Function;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
import kotlin.Unit;
|
||||
import kotlin.jvm.functions.Function0;
|
||||
import kotlin.jvm.functions.Function1;
|
||||
import okhttp3.RequestBody;
|
||||
import okhttp3.ResponseBody;
|
||||
import retrofit2.HttpException;
|
||||
@ -149,6 +148,8 @@ public class MainActivity extends BaseActivity {
|
||||
public static final String SHOW_AD = "show_ad";
|
||||
public static final int COUNTDOWN_AD = 100;
|
||||
private int mCountdownMaxCount = 3;
|
||||
public static final int COUNTDOWN_SDK_AD = 101;
|
||||
public static final int COUNTDOWN_SDK_MAX_COUNT = 5;
|
||||
private int mCountdownCount = 0;
|
||||
|
||||
private static final String CURRENT_PAGE = "current_page";
|
||||
@ -490,6 +491,7 @@ public class MainActivity extends BaseActivity {
|
||||
if (AdDelegateHelper.INSTANCE.shouldShowStartUpAd(false)) {
|
||||
ViewGroup startAdContainer = findViewById(R.id.startAdContainer);
|
||||
ViewGroup sdkStartAdContainer = findViewById(R.id.sdkStartAdContainer);
|
||||
TextView sdkJumpBtn = findViewById(R.id.sdkJumpBtn);
|
||||
FrameLayout adsFl = findViewById(R.id.adsFl);
|
||||
View icpContainer = findViewById(R.id.sdkStartAdIcpContainer);
|
||||
if (icpContainer != null) {
|
||||
@ -518,6 +520,7 @@ public class MainActivity extends BaseActivity {
|
||||
screenHeightInDp,
|
||||
startAdContainer,
|
||||
sdkStartAdContainer,
|
||||
sdkJumpBtn,
|
||||
adsFl,
|
||||
(BaseHandler) mBaseHandler,
|
||||
false,
|
||||
@ -537,13 +540,19 @@ public class MainActivity extends BaseActivity {
|
||||
@Override
|
||||
protected void handleMessage(Message msg) {
|
||||
super.handleMessage(msg);
|
||||
if (msg.what == COUNTDOWN_AD) {
|
||||
if (msg.what == COUNTDOWN_AD || msg.what == COUNTDOWN_SDK_AD) {
|
||||
mCountdownCount++;
|
||||
if (mCountdownMaxCount < mCountdownCount) {
|
||||
int maxCount;
|
||||
if (msg.what == COUNTDOWN_AD) {
|
||||
maxCount = mCountdownMaxCount;
|
||||
} else {
|
||||
maxCount = COUNTDOWN_SDK_MAX_COUNT;
|
||||
}
|
||||
if (maxCount < mCountdownCount) {
|
||||
AdDelegateHelper.INSTANCE.setShowingSplashAd(false);
|
||||
hideSplashAd();
|
||||
|
||||
if (msg.obj instanceof StartupAdEntity) {
|
||||
if (msg.what == COUNTDOWN_AD && msg.obj instanceof StartupAdEntity) {
|
||||
StartupAdEntity ad = (StartupAdEntity) msg.obj;
|
||||
LinkEntity linkEntity = ad.getJump();
|
||||
SensorsBridge.trackEvent(
|
||||
@ -556,14 +565,26 @@ public class MainActivity extends BaseActivity {
|
||||
linkEntity.getLink(),
|
||||
"link_text",
|
||||
linkEntity.getText());
|
||||
} else if (msg.what == COUNTDOWN_SDK_AD) {
|
||||
SPUtils.setLong(Constants.SP_LAST_SPLASH_AD_SHOW_TIME, System.currentTimeMillis());
|
||||
}
|
||||
} else {
|
||||
TextView jumpBtn = findViewById(R.id.jumpBtn);
|
||||
jumpBtn.setText(getString(R.string.splash_jump, mCountdownMaxCount - mCountdownCount));
|
||||
Message newMsg = Message.obtain();
|
||||
newMsg.what = COUNTDOWN_AD;
|
||||
newMsg.obj = msg.obj;
|
||||
mBaseHandler.sendMessageDelayed(newMsg, 1000);
|
||||
if (msg.what == COUNTDOWN_AD) {
|
||||
TextView jumpBtn = findViewById(R.id.jumpBtn);
|
||||
if (jumpBtn != null) {
|
||||
jumpBtn.setText(getString(R.string.splash_jump, maxCount - mCountdownCount));
|
||||
}
|
||||
Message newMsg = Message.obtain();
|
||||
newMsg.what = COUNTDOWN_AD;
|
||||
newMsg.obj = msg.obj;
|
||||
mBaseHandler.sendMessageDelayed(newMsg, 1000);
|
||||
} else {
|
||||
TextView jumpBtn = findViewById(R.id.sdkJumpBtn);
|
||||
if (jumpBtn != null) {
|
||||
jumpBtn.setText(getString(R.string.splash_jump, maxCount - mCountdownCount));
|
||||
}
|
||||
mBaseHandler.sendEmptyMessageDelayed(COUNTDOWN_SDK_AD, 1000);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -601,7 +622,11 @@ public class MainActivity extends BaseActivity {
|
||||
ExtensionsKt.removeFromParent(startSdkAdContainer, true);
|
||||
AdDelegateHelper.INSTANCE.cancelSplashAd(this);
|
||||
}
|
||||
|
||||
TextView jumpBtn = findViewById(R.id.sdkJumpBtn);
|
||||
if (jumpBtn != null) {
|
||||
jumpBtn.setVisibility(View.GONE);
|
||||
ExtensionsKt.removeFromParent(jumpBtn, true);
|
||||
}
|
||||
View startSdkAdIcpContainer = findViewById(R.id.sdkStartAdIcpContainer);
|
||||
if (startSdkAdIcpContainer != null) {
|
||||
startSdkAdIcpContainer.setVisibility(View.GONE);
|
||||
|
||||
@ -10,6 +10,8 @@ import android.view.inputmethod.EditorInfo
|
||||
import android.widget.*
|
||||
import androidx.core.widget.doAfterTextChanged
|
||||
import androidx.core.widget.doOnTextChanged
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.FragmentTransaction
|
||||
import com.gh.common.util.*
|
||||
import com.gh.common.util.LogUtils
|
||||
import com.gh.gamecenter.DisplayType.*
|
||||
@ -118,7 +120,7 @@ open class SearchActivity : BaseActivity() {
|
||||
trackSearchPageShow()
|
||||
}
|
||||
|
||||
protected open fun trackSearchPageShow(){
|
||||
protected open fun trackSearchPageShow() {
|
||||
val bottomTab = intent.getStringExtra(EntranceConsts.KEY_BOTTOM_TAB_NAME) ?: ""
|
||||
val multiTabId = intent.getStringExtra(EntranceConsts.KEY_MULTI_TAB_NAV_ID) ?: ""
|
||||
val multiTabName = intent.getStringExtra(EntranceConsts.KEY_MULTI_TAB_NAV_NAME) ?: ""
|
||||
@ -179,10 +181,11 @@ open class SearchActivity : BaseActivity() {
|
||||
open fun search(type: SearchType, key: String?) {
|
||||
mSearchType = type
|
||||
mIsAutoSearchDisabled = true
|
||||
// 自动搜索,默认搜索,热门搜索,历史搜索,主动搜索
|
||||
// 自动搜索,默认搜索,热门搜索,历史搜索,主动搜索,榜单搜索
|
||||
when (type) {
|
||||
SearchType.AUTO -> handleAutoSearch(key)
|
||||
SearchType.DEFAULT -> handleDefaultSearch(key)
|
||||
SearchType.RANK -> handleRankSearch(key)
|
||||
SearchType.HOT -> handleHotSearch(key)
|
||||
SearchType.HISTORY -> handleHistorySearch(key)
|
||||
SearchType.MANUAL -> handleManualSearch()
|
||||
@ -213,6 +216,22 @@ open class SearchActivity : BaseActivity() {
|
||||
}
|
||||
}
|
||||
|
||||
protected open fun handleRankSearch(key: String?) {
|
||||
mSearchKey = key
|
||||
searchEt.setText(key)
|
||||
searchEt.setSelection(searchEt.text.length)
|
||||
updateDisplayType(GAME_DETAIL)
|
||||
LogUtils.uploadSearchGame("searching", "搜索页", key, "榜单搜索")
|
||||
|
||||
SensorsBridge.trackSearchButtonClick(
|
||||
GlobalActivityManager.getCurrentPageEntity().pageId,
|
||||
GlobalActivityManager.getCurrentPageEntity().pageName,
|
||||
key ?: "",
|
||||
TRACK_SEARCH_TYPE_DEFAULT,
|
||||
mSourceEntrance
|
||||
)
|
||||
}
|
||||
|
||||
protected open fun handleDefaultSearch(key: String?) {
|
||||
mSearchKey = key
|
||||
searchEt.setText(key)
|
||||
@ -286,38 +305,72 @@ open class SearchActivity : BaseActivity() {
|
||||
protected open fun provideDao(): ISearchHistoryDao = SearchHistoryDao(this)
|
||||
|
||||
open fun updateDisplayType(type: DisplayType) {
|
||||
val transaction = supportFragmentManager.beginTransaction()
|
||||
when (type) {
|
||||
DEFAULT -> {
|
||||
val fragment = supportFragmentManager.findFragmentByTag(SearchDefaultFragment::class.java.name)
|
||||
?: SearchDefaultFragment().apply {
|
||||
arguments = Bundle().also { it.putBoolean(SearchDefaultFragment.KEY_IS_GAME_SEARCH, true) }
|
||||
}
|
||||
transaction.replace(R.id.search_result, fragment, SearchDefaultFragment::class.java.name)
|
||||
val transaction = when (type) {
|
||||
DEFAULT -> showFragment(
|
||||
SearchDefaultFragment::class.java.name,
|
||||
{ SearchDefaultFragment() }
|
||||
) {
|
||||
it.arguments = Bundle().also { bundle ->
|
||||
bundle.putBoolean(SearchDefaultFragment.KEY_IS_GAME_SEARCH, true)
|
||||
}
|
||||
}
|
||||
|
||||
GAME_DIGEST -> {
|
||||
val digestListFragment =
|
||||
supportFragmentManager.findFragmentByTag(SearchGameIndexFragment::class.java.name) as? SearchGameIndexFragment
|
||||
?: SearchGameIndexFragment()
|
||||
digestListFragment.setParams(mSearchKey ?: "", mSearchType.value)
|
||||
transaction.replace(R.id.search_result, digestListFragment, SearchGameIndexFragment::class.java.name)
|
||||
GAME_DIGEST -> showFragment(
|
||||
SearchGameIndexFragment::class.java.name,
|
||||
{ SearchGameIndexFragment() }
|
||||
) {
|
||||
removeFragment(SearchGameResultFragment::class.java.name)
|
||||
it.setParams(mSearchKey ?: "", mSearchType.value)
|
||||
}
|
||||
|
||||
GAME_DETAIL -> {
|
||||
val detailListFragment =
|
||||
supportFragmentManager.findFragmentByTag(SearchGameResultFragment::class.java.name) as? SearchGameResultFragment
|
||||
?: SearchGameResultFragment()
|
||||
detailListFragment.setParams(mSearchKey ?: "", mSearchType.value)
|
||||
transaction.replace(R.id.search_result, detailListFragment, SearchGameResultFragment::class.java.name)
|
||||
GAME_DETAIL -> showFragment(
|
||||
SearchGameResultFragment::class.java.name,
|
||||
{ SearchGameResultFragment() }
|
||||
) {
|
||||
removeFragment(SearchGameIndexFragment::class.java.name)
|
||||
it.setParams(mSearchKey ?: "", mSearchType.value)
|
||||
}
|
||||
|
||||
else -> {
|
||||
//do nothing
|
||||
}
|
||||
else -> null
|
||||
}
|
||||
mDisplayType = type
|
||||
transaction.commitAllowingStateLoss()
|
||||
transaction?.let {
|
||||
mDisplayType = type
|
||||
it.commitAllowingStateLoss()
|
||||
}
|
||||
}
|
||||
|
||||
protected fun <T : Fragment> showFragment(
|
||||
tag: String,
|
||||
onFragmentCreate: () -> T,
|
||||
onFragmentCreated: ((T) -> Unit)? = null,
|
||||
): FragmentTransaction {
|
||||
val transaction = supportFragmentManager.beginTransaction()
|
||||
var createNewFragment = false
|
||||
var fragment = supportFragmentManager
|
||||
.findFragmentByTag(tag)
|
||||
if (fragment == null) {
|
||||
createNewFragment = true
|
||||
fragment = onFragmentCreate.invoke()
|
||||
}
|
||||
onFragmentCreated?.invoke(fragment as T)
|
||||
if (createNewFragment) {
|
||||
transaction.add(R.id.search_result, fragment, tag)
|
||||
transaction.addToBackStack(null)
|
||||
} else if (!fragment.isAdded) {
|
||||
transaction.show(fragment)
|
||||
transaction.addToBackStack(null)
|
||||
}
|
||||
return transaction
|
||||
}
|
||||
|
||||
protected fun removeFragment(tag: String) {
|
||||
val fragment = supportFragmentManager
|
||||
.findFragmentByTag(tag) ?: return
|
||||
supportFragmentManager
|
||||
.beginTransaction()
|
||||
.remove(fragment)
|
||||
.commit()
|
||||
supportFragmentManager.popBackStack()
|
||||
}
|
||||
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
@ -325,6 +378,7 @@ open class SearchActivity : BaseActivity() {
|
||||
when (search.type) {
|
||||
SearchType.HISTORY.value -> search(SearchType.HISTORY, search.key)
|
||||
SearchType.HOT.value -> search(SearchType.HOT, search.key)
|
||||
SearchType.RANK.value -> search(SearchType.RANK, search.key)
|
||||
|
||||
"click" -> DataCollectionUtils.uploadSearchClick(
|
||||
this, mSearchKey, mSearchType.value, "搜索页面",
|
||||
@ -341,9 +395,8 @@ open class SearchActivity : BaseActivity() {
|
||||
}
|
||||
|
||||
override fun handleBackPressed(): Boolean {
|
||||
val fragment = supportFragmentManager.findFragmentByTag(SearchDefaultFragment::class.java.name)
|
||||
if (fragment == null) {
|
||||
updateDisplayType(DEFAULT)
|
||||
if (supportFragmentManager.fragments.size == 1) {
|
||||
finish()
|
||||
return true
|
||||
}
|
||||
return super.handleBackPressed()
|
||||
@ -417,7 +470,8 @@ enum class SearchType(var value: String) {
|
||||
DEFAULT("default"),
|
||||
HISTORY("history"),
|
||||
MANUAL("initiative"),
|
||||
HOT("remen");
|
||||
HOT("remen"),
|
||||
RANK("rank");
|
||||
|
||||
fun toChinese() = when (this) {
|
||||
AUTO -> "自动搜索"
|
||||
@ -425,6 +479,7 @@ enum class SearchType(var value: String) {
|
||||
HISTORY -> "历史搜索"
|
||||
MANUAL -> "主动搜索"
|
||||
HOT -> "热门搜索"
|
||||
RANK -> "榜单搜索"
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
@ -5,7 +5,6 @@ import static com.gh.gamecenter.common.constant.EntranceConsts.ENTRANCE_PUSH;
|
||||
import static com.gh.gamecenter.common.constant.EntranceConsts.HOST_ANSWER;
|
||||
import static com.gh.gamecenter.common.constant.EntranceConsts.HOST_ARCHIVE_LOGIN;
|
||||
import static com.gh.gamecenter.common.constant.EntranceConsts.HOST_ARTICLE;
|
||||
import static com.gh.gamecenter.common.constant.EntranceConsts.HOST_CATEGORY;
|
||||
import static com.gh.gamecenter.common.constant.EntranceConsts.HOST_COLUMN;
|
||||
import static com.gh.gamecenter.common.constant.EntranceConsts.HOST_COLUMN_COLLECTION;
|
||||
import static com.gh.gamecenter.common.constant.EntranceConsts.HOST_COMMUNITY;
|
||||
@ -315,10 +314,6 @@ public class SkipActivity extends BaseActivity {
|
||||
DirectUtils.directToCommunityColumn(this, community, columnId, entrance, "");
|
||||
break;
|
||||
|
||||
case HOST_CATEGORY:
|
||||
title = uri.getQueryParameter("title");
|
||||
DirectUtils.directCategoryDirectory(this, path, title, entrance, pathName);
|
||||
break;
|
||||
case HOST_COLUMN_COLLECTION:
|
||||
DirectUtils.directToColumnCollection(this, path, -1, entrance, "", "", "", "", null,false);
|
||||
break;
|
||||
@ -424,7 +419,7 @@ public class SkipActivity extends BaseActivity {
|
||||
} else {
|
||||
Bundle newBundle = new Bundle();
|
||||
newBundle.putString(EntranceConsts.KEY_TO, LoginActivity.class.getName());
|
||||
EntranceUtils.jumpActivity(this, null, newBundle, (resultCode, data) -> {
|
||||
EntranceUtils.jumpActivityCompat(this, newBundle, null, (resultCode, data) -> {
|
||||
if(CheckLoginUtils.isLogin()) {
|
||||
VHelper.INSTANCE.updateAuthorizeInfo(true);
|
||||
}
|
||||
@ -447,7 +442,7 @@ public class SkipActivity extends BaseActivity {
|
||||
break;
|
||||
default:
|
||||
EntranceUtils.jumpActivity(this, new Bundle()); // 跳转至首页
|
||||
return;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if ("market".equals(uri.getScheme())) {
|
||||
|
||||
@ -12,8 +12,10 @@ import com.gh.ad.AdDelegateHelper
|
||||
import com.gh.ad.AdDelegateHelper.requestSplashAd
|
||||
import com.gh.ad.AdDelegateHelper.shouldShowStartUpAd
|
||||
import com.gh.gamecenter.common.base.activity.BaseActivity
|
||||
import com.gh.gamecenter.common.constant.Constants
|
||||
import com.gh.gamecenter.common.utils.dip2px
|
||||
import com.gh.gamecenter.core.utils.DisplayUtils
|
||||
import com.gh.gamecenter.core.utils.SPUtils
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
@ -37,6 +39,7 @@ class SplashAdActivity : BaseActivity() {
|
||||
if (shouldShowStartUpAd(true)) {
|
||||
val startAdContainer = findViewById<ViewGroup>(R.id.startAdContainer)
|
||||
val sdkStartAdContainer = findViewById<ViewGroup>(R.id.sdkStartAdContainer)
|
||||
val sdkJumpBtn = findViewById<TextView>(R.id.sdkJumpBtn)
|
||||
val adsFl = findViewById<FrameLayout>(R.id.adsFl)
|
||||
val icpContainer = findViewById<View>(R.id.sdkStartAdIcpContainer)
|
||||
|
||||
@ -58,6 +61,7 @@ class SplashAdActivity : BaseActivity() {
|
||||
screenHeightInDp,
|
||||
startAdContainer!!,
|
||||
sdkStartAdContainer!!,
|
||||
sdkJumpBtn!!,
|
||||
adsFl!!,
|
||||
(mBaseHandler as BaseHandler),
|
||||
true
|
||||
@ -81,15 +85,23 @@ class SplashAdActivity : BaseActivity() {
|
||||
|
||||
override fun handleMessage(msg: Message) {
|
||||
super.handleMessage(msg)
|
||||
if (msg.what == MainActivity.COUNTDOWN_AD) {
|
||||
if (msg.what == MainActivity.COUNTDOWN_AD || msg.what == MainActivity.COUNTDOWN_SDK_AD) {
|
||||
mCountdownCount++
|
||||
if (COUNTDOWN_MAX_COUNT < mCountdownCount) {
|
||||
val maxCount = if (msg.what == MainActivity.COUNTDOWN_AD) {
|
||||
COUNTDOWN_MAX_COUNT
|
||||
} else {
|
||||
MainActivity.COUNTDOWN_SDK_MAX_COUNT
|
||||
}
|
||||
if (maxCount < mCountdownCount) {
|
||||
AdDelegateHelper.isShowingSplashAd = false
|
||||
if (msg.what == MainActivity.COUNTDOWN_SDK_AD) {
|
||||
SPUtils.setLong(Constants.SP_LAST_SPLASH_AD_SHOW_TIME, System.currentTimeMillis())
|
||||
}
|
||||
finishActivity()
|
||||
} else {
|
||||
val jumpBtn = findViewById<TextView>(R.id.jumpBtn)
|
||||
jumpBtn.text = getString(R.string.splash_jump, COUNTDOWN_MAX_COUNT - mCountdownCount)
|
||||
mBaseHandler.sendEmptyMessageDelayed(MainActivity.COUNTDOWN_AD, 1000)
|
||||
val jumpBtn = findViewById<TextView>(if (msg.what == MainActivity.COUNTDOWN_AD) R.id.jumpBtn else R.id.sdkJumpBtn)
|
||||
jumpBtn?.text = getString(R.string.splash_jump, maxCount - mCountdownCount)
|
||||
mBaseHandler.sendEmptyMessageDelayed(msg.what, 1000)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -17,8 +17,11 @@ import androidx.core.text.color
|
||||
import com.alibaba.android.arouter.facade.annotation.Route
|
||||
import com.alibaba.android.arouter.launcher.ARouter
|
||||
import com.gh.common.dialog.NewPrivacyPolicyDialogFragment
|
||||
import com.gh.common.util.*
|
||||
import com.gh.common.util.DeviceTokenUtils
|
||||
import com.gh.common.util.DialogUtils
|
||||
import com.gh.common.util.GameSubstituteRepositoryHelper.updateGameSubstituteRepository
|
||||
import com.gh.common.util.PackageHelper
|
||||
import com.gh.common.util.PackageUtils
|
||||
import com.gh.common.util.UsageStatsHelper.checkAndPostUsageStats
|
||||
import com.gh.download.DownloadManager
|
||||
import com.gh.gamecenter.common.base.activity.BaseActivity
|
||||
@ -28,6 +31,7 @@ import com.gh.gamecenter.common.tracker.TrackerLogger
|
||||
import com.gh.gamecenter.common.utils.*
|
||||
import com.gh.gamecenter.core.provider.IAppProvider
|
||||
import com.gh.gamecenter.core.provider.IPackageUtilsProvider
|
||||
import com.gh.gamecenter.core.provider.IPushProvider
|
||||
import com.gh.gamecenter.core.runOnIoThread
|
||||
import com.gh.gamecenter.core.utils.DisplayUtils
|
||||
import com.gh.gamecenter.core.utils.SPUtils
|
||||
@ -55,6 +59,9 @@ class SplashScreenActivity : BaseActivity() {
|
||||
mSharedPreferences = PreferenceManager.getDefaultSharedPreferences(this)
|
||||
mIsNewForThisVersion = HaloApp.getInstance().isNewForThisVersion
|
||||
HaloApp.getInstance().isBrandNewInstall = SPUtils.getBoolean(Constants.SP_BRAND_NEW_USER, true)
|
||||
if (HaloApp.getInstance().isBrandNewInstall) {
|
||||
SPUtils.setLong(Constants.SP_BRAND_NEW_FIRST_LAUNCH_TIME, System.currentTimeMillis())
|
||||
}
|
||||
|
||||
// 用户不是新版本,但应用最后更新时间不是上次的时间代表用户重新安装了当前版本
|
||||
if (!mIsNewForThisVersion) {
|
||||
@ -274,6 +281,12 @@ class SplashScreenActivity : BaseActivity() {
|
||||
|
||||
SensorsBridge.init(HaloApp.getInstance(), HaloApp.getInstance().channel)
|
||||
SensorsBridge.setOAID(HaloApp.getInstance().oaid)
|
||||
|
||||
val pushProvider = ARouter.getInstance().build(RouteConsts.provider.push).navigation() as? IPushProvider
|
||||
val registrationId = pushProvider?.getRegistrationId(this)
|
||||
if (!registrationId.isNullOrEmpty()) {
|
||||
SensorsBridge.profileAppend(KEY_REGISTRATION_ID, registrationId)
|
||||
}
|
||||
}
|
||||
|
||||
private fun prefetchData() {
|
||||
@ -305,6 +318,7 @@ class SplashScreenActivity : BaseActivity() {
|
||||
|
||||
|
||||
companion object {
|
||||
private const val KEY_REGISTRATION_ID = "registration_id"
|
||||
|
||||
const val HONOR_CULPRIT_ID = 12324
|
||||
const val HONOR_CULPRIT_CHANNEL = "荣耀通道"
|
||||
|
||||
@ -24,6 +24,7 @@ import com.gh.gamecenter.R;
|
||||
import com.gh.gamecenter.adapter.viewholder.KcSelectGameViewHolder;
|
||||
import com.gh.gamecenter.common.retrofit.Response;
|
||||
import com.gh.gamecenter.common.utils.BitmapUtils;
|
||||
import com.gh.gamecenter.common.utils.FileUtils;
|
||||
import com.gh.gamecenter.core.utils.MtaHelper;
|
||||
import com.gh.gamecenter.core.utils.TimeUtils;
|
||||
import com.gh.gamecenter.core.utils.ToastUtils;
|
||||
@ -85,7 +86,7 @@ public class CleanApkAdapter extends BaseRecyclerAdapter<KcSelectGameViewHolder>
|
||||
Observable.create(emitter -> {
|
||||
// 扫描和获取apk数据 分步操作 尽量避免 StackoverflowError
|
||||
FindAllAPKPath(Environment.getExternalStorageDirectory());
|
||||
FindAllAPKPath(mContext.getFilesDir());
|
||||
FindAllAPKPath(new File(FileUtils.getDownloadDir(mContext)));
|
||||
LoadApkData();
|
||||
emitter.onComplete();
|
||||
})
|
||||
|
||||
@ -652,12 +652,12 @@ class DetailViewHolder(
|
||||
builder.addHandler(LandPageAddressHandler())
|
||||
builder.addHandler(OverseaDownloadHandler())
|
||||
builder.addHandler(CheckDownloadHandler())
|
||||
builder.setProcessEndCallback { asVGame: Boolean, isSubscribe: Any? ->
|
||||
builder.setProcessEndCallback(mGameEntity.id) { asVGame: Boolean, isSubscribe: Any? ->
|
||||
download(asVGame, isSubscribe as Boolean)
|
||||
}
|
||||
} else {
|
||||
builder.addHandler(VersionNumberHandler())
|
||||
builder.setProcessEndCallback { _: Boolean?, _: Any? ->
|
||||
builder.setProcessEndCallback(mGameEntity.id) { _: Boolean?, _: Any? ->
|
||||
DownloadDialog.showDownloadDialog(
|
||||
mViewHolder.context,
|
||||
mGameEntity,
|
||||
|
||||
@ -4,11 +4,10 @@ import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.text.TextUtils
|
||||
import com.gh.gamecenter.common.utils.viewModelProvider
|
||||
import com.gh.gamecenter.DisplayType
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.SearchActivity
|
||||
import com.gh.gamecenter.SearchType
|
||||
import com.gh.gamecenter.common.utils.viewModelProvider
|
||||
import com.gh.gamecenter.db.ISearchHistoryDao
|
||||
import com.gh.gamecenter.search.SearchDefaultFragment
|
||||
|
||||
@ -64,19 +63,16 @@ class AmwaySearchActivity : SearchActivity() {
|
||||
}
|
||||
|
||||
override fun updateDisplayType(type: DisplayType) {
|
||||
val transaction = supportFragmentManager.beginTransaction()
|
||||
when (type) {
|
||||
DisplayType.DEFAULT -> {
|
||||
val fragment = supportFragmentManager.findFragmentByTag(SearchDefaultFragment::class.java.name)
|
||||
?: AmwaySearchDefaultFragment()
|
||||
transaction.replace(R.id.search_result, fragment, SearchDefaultFragment::class.java.name)
|
||||
}
|
||||
val transaction = when (type) {
|
||||
DisplayType.DEFAULT -> showFragment(
|
||||
SearchDefaultFragment::class.java.name,
|
||||
{ AmwaySearchDefaultFragment() }
|
||||
)
|
||||
|
||||
else -> {
|
||||
val fragment = supportFragmentManager.findFragmentByTag(AmwaySearchListFragment::class.java.name)
|
||||
?: AmwaySearchListFragment()
|
||||
transaction.replace(R.id.search_result, fragment, AmwaySearchListFragment::class.java.name)
|
||||
}
|
||||
else -> showFragment(
|
||||
AmwaySearchListFragment::class.java.name,
|
||||
{ AmwaySearchListFragment() }
|
||||
)
|
||||
}
|
||||
mDisplayType = type
|
||||
transaction.commitAllowingStateLoss()
|
||||
|
||||
@ -33,7 +33,7 @@ class AmwaySearchDefaultFragment : SearchDefaultFragment() {
|
||||
mViewModel.playedGames.observeNonNull(viewLifecycleOwner) {
|
||||
defaultViewModel?.isExistHotSearch = it.isNotEmpty()
|
||||
updateView()
|
||||
mBinding.hotList.run {
|
||||
mBinding.searchDiscoveryList.run {
|
||||
layoutManager = LinearLayoutManager(context)
|
||||
adapter = AmwaySearchAdapter(context, mViewModel, "安利墙搜索-最近玩过").apply { setData(it) }
|
||||
}
|
||||
@ -45,7 +45,7 @@ class AmwaySearchDefaultFragment : SearchDefaultFragment() {
|
||||
override fun provideDao(): ISearchHistoryDao = AmwaySearchDao()
|
||||
override fun initView() {
|
||||
mBinding = mAmwayBinding.searchContent
|
||||
mBinding.hotHeadContainer.headTitle.text = "最近玩过"
|
||||
mBinding.searchDiscoveryHeadContainer.headTitle.text = "最近玩过"
|
||||
mBinding.historyFlexContainer.setLimitHeight(mFlexMaxHeight)
|
||||
|
||||
updateHistorySearchView(null)
|
||||
|
||||
@ -57,6 +57,7 @@ class AmwaySearchListFragment : ToolbarFragment() {
|
||||
when (it) {
|
||||
LoadStatus.INIT_LOADING -> {
|
||||
hideError()
|
||||
hideRvList()
|
||||
showLoading()
|
||||
hideNoDataHint()
|
||||
}
|
||||
@ -64,16 +65,19 @@ class AmwaySearchListFragment : ToolbarFragment() {
|
||||
hideError()
|
||||
hideLoading()
|
||||
hideNoDataHint()
|
||||
showRvList()
|
||||
}
|
||||
LoadStatus.INIT_FAILED -> {
|
||||
hideLoading()
|
||||
hideNoDataHint()
|
||||
showError()
|
||||
hideRvList()
|
||||
}
|
||||
LoadStatus.INIT_EMPTY -> {
|
||||
showNoDataHint()
|
||||
hideError()
|
||||
hideLoading()
|
||||
hideRvList()
|
||||
}
|
||||
else -> {
|
||||
// do nothing
|
||||
@ -82,6 +86,14 @@ class AmwaySearchListFragment : ToolbarFragment() {
|
||||
}
|
||||
}
|
||||
|
||||
private fun hideRvList() {
|
||||
mBinding.recyclerView.visibility = View.GONE
|
||||
}
|
||||
|
||||
private fun showRvList() {
|
||||
mBinding.recyclerView.visibility = View.VISIBLE
|
||||
}
|
||||
|
||||
private fun showLoading() {
|
||||
mBinding.loadingContainer.visibility = View.VISIBLE
|
||||
}
|
||||
|
||||
@ -44,6 +44,7 @@ class AmwaySearchViewModel(application: Application) : AndroidViewModel(applicat
|
||||
mTempSearchKey = searchKey
|
||||
currentSearchKey = searchKey
|
||||
loadStatus.postValue(LoadStatus.INIT_LOADING)
|
||||
searchGames.postValue(emptyList())
|
||||
RetrofitManager
|
||||
.getInstance().api
|
||||
.getSearchGame(Config.API_HOST + "games:search?keyword=" + searchKey + "&view=anliwall" + "&channel=" + HaloApp.getInstance().channel + "&version=" + BuildConfig.VERSION_NAME)
|
||||
|
||||
@ -1,43 +0,0 @@
|
||||
package com.gh.gamecenter.catalog
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import com.gh.base.DownloadToolbarActivity
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.constant.EntranceConsts
|
||||
import com.gh.gamecenter.common.utils.updateStatusBarColor
|
||||
|
||||
class CatalogActivity : DownloadToolbarActivity() {
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setToolbarMenu(R.menu.menu_download)
|
||||
updateStatusBarColor(R.color.ui_surface, R.color.ui_surface)
|
||||
}
|
||||
|
||||
override fun showDownloadMenu(): Boolean {
|
||||
return true
|
||||
}
|
||||
|
||||
override fun provideNormalIntent(): Intent {
|
||||
return getTargetIntent(this, CatalogActivity::class.java, CatalogFragment::class.java)
|
||||
}
|
||||
|
||||
override fun onDarkModeChanged() {
|
||||
super.onDarkModeChanged()
|
||||
updateStatusBarColor(R.color.ui_surface, R.color.ui_surface)
|
||||
}
|
||||
|
||||
override fun isAutoResetViewBackgroundEnabled() = true
|
||||
|
||||
companion object {
|
||||
fun getIntent(context: Context, catalogId: String, catalogTitle: String, entrance: String): Intent {
|
||||
val bundle = Bundle()
|
||||
bundle.putString(EntranceConsts.KEY_CATALOG_ID, catalogId)
|
||||
bundle.putString(EntranceConsts.KEY_CATALOG_TITLE, catalogTitle)
|
||||
bundle.putString(EntranceConsts.KEY_ENTRANCE, entrance)
|
||||
return getTargetIntent(context, CatalogActivity::class.java, CatalogFragment::class.java, bundle)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,53 +0,0 @@
|
||||
package com.gh.gamecenter.catalog
|
||||
|
||||
import android.content.Context
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import com.gh.gamecenter.common.base.BaseRecyclerViewHolder
|
||||
import com.gh.gamecenter.common.utils.goneIf
|
||||
import com.gh.gamecenter.common.utils.toBinding
|
||||
import com.gh.gamecenter.common.utils.toColor
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.databinding.CatalogItemBinding
|
||||
import com.gh.gamecenter.entity.CatalogEntity
|
||||
import com.lightgame.adapter.BaseRecyclerAdapter
|
||||
|
||||
class CatalogAdapter(
|
||||
context: Context,
|
||||
private val mFragment: CatalogFragment,
|
||||
private val mViewModel: CatalogViewModel,
|
||||
private val mList: List<CatalogEntity.SubCatalogEntity>
|
||||
) : BaseRecyclerAdapter<CatalogAdapter.CatalogItemViewHolder>(context) {
|
||||
|
||||
override fun getItemCount() = mList.size
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) =
|
||||
CatalogItemViewHolder(parent.toBinding())
|
||||
|
||||
override fun onBindViewHolder(holder: CatalogItemViewHolder, position: Int) {
|
||||
holder.binding.run {
|
||||
val catalogEntity = mList[position]
|
||||
catalogName.text = catalogEntity.name
|
||||
recommendTag.goneIf(!catalogEntity.recommended)
|
||||
if (catalogEntity.name == mViewModel.selectedCatalogName) {
|
||||
selectedTag.visibility = View.VISIBLE
|
||||
catalogName.setTextColor(R.color.text_theme.toColor(mContext))
|
||||
root.setBackgroundColor(R.color.ui_surface.toColor(mContext))
|
||||
} else {
|
||||
selectedTag.visibility = View.GONE
|
||||
catalogName.setTextColor(R.color.text_primary.toColor(mContext))
|
||||
root.background = null
|
||||
}
|
||||
root.setOnClickListener {
|
||||
if (catalogEntity.name != mViewModel.selectedCatalogName) {
|
||||
mViewModel.selectedCatalogName = catalogEntity.name
|
||||
mViewModel.logSubCatalogClick(position)
|
||||
mFragment.changeCatalog(position)
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class CatalogItemViewHolder(val binding: CatalogItemBinding) : BaseRecyclerViewHolder<Any>(binding.root)
|
||||
}
|
||||
@ -1,240 +0,0 @@
|
||||
package com.gh.gamecenter.catalog
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import androidx.core.os.bundleOf
|
||||
import androidx.lifecycle.Observer
|
||||
import com.gh.gamecenter.common.base.fragment.LazyFragment
|
||||
import com.gh.gamecenter.common.constant.EntranceConsts
|
||||
import com.gh.gamecenter.common.utils.dip2px
|
||||
import com.gh.gamecenter.common.utils.toColor
|
||||
import com.gh.gamecenter.common.utils.viewModelProviderFromParent
|
||||
import com.gh.gamecenter.common.view.FixLinearLayoutManager
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.databinding.FragmentCatalogBinding
|
||||
import com.gh.gamecenter.entity.CatalogEntity
|
||||
|
||||
class CatalogFragment : LazyFragment() {
|
||||
|
||||
private var mBinding: FragmentCatalogBinding? = null
|
||||
private var mViewModel: CatalogViewModel? = null
|
||||
private var mEntity: CatalogEntity? = null
|
||||
private var mSpecialCatalogFragment: SpecialCatalogFragment? = null
|
||||
private var mSubCatalogFragment: SubCatalogFragment? = null
|
||||
|
||||
private var mCatalogId: String = ""
|
||||
private var mCatalogTitle: String = ""
|
||||
private var mLastSelectedPosition = -1
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
savedInstanceState?.run {
|
||||
mLastSelectedPosition = getInt(EntranceConsts.KEY_LAST_SELECTED_POSITION)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onSaveInstanceState(outState: Bundle) {
|
||||
mViewModel?.run {
|
||||
outState.putInt(EntranceConsts.KEY_LAST_SELECTED_POSITION, selectedCatalogPosition)
|
||||
}
|
||||
super.onSaveInstanceState(outState)
|
||||
}
|
||||
|
||||
override fun getRealLayoutId() = R.layout.fragment_catalog
|
||||
|
||||
override fun onRealLayoutInflated(inflatedView: View) {
|
||||
mBinding = FragmentCatalogBinding.bind(inflatedView)
|
||||
}
|
||||
|
||||
override fun onFragmentFirstVisible() {
|
||||
mCatalogId = arguments?.getString(EntranceConsts.KEY_CATALOG_ID) ?: ""
|
||||
mCatalogTitle = arguments?.getString(EntranceConsts.KEY_CATALOG_TITLE) ?: ""
|
||||
mViewModel = viewModelProviderFromParent(CatalogViewModel.Factory(mCatalogId, mCatalogTitle), mCatalogId)
|
||||
|
||||
mViewModel?.validEntranceName = if (mEntrance.contains("首页")) "首页" else "板块"
|
||||
if (arguments?.getBoolean(EntranceConsts.KEY_IS_HOME) == true) {
|
||||
mViewModel?.validEntranceName = "首页Tab栏"
|
||||
}
|
||||
mViewModel?.logAppearance()
|
||||
|
||||
super.onFragmentFirstVisible()
|
||||
}
|
||||
|
||||
override fun initRealView() {
|
||||
super.initRealView()
|
||||
|
||||
setNavigationTitle(mCatalogTitle)
|
||||
mViewModel?.catalogs?.observe(viewLifecycleOwner, Observer {
|
||||
mBinding?.run {
|
||||
reuseLoading.root.visibility = View.GONE
|
||||
if (it != null) {
|
||||
reuseNoConnection.root.visibility = View.GONE
|
||||
if (it.subCatalog.isNotEmpty()) {
|
||||
containerCatalog.visibility = View.VISIBLE
|
||||
reuseNoneData.root.visibility = View.GONE
|
||||
mEntity = it
|
||||
if (mEntity!!.hasSpecial) {
|
||||
val specialEntity = CatalogEntity.SubCatalogEntity(name = "精选")
|
||||
(mEntity!!.subCatalog as ArrayList).add(0, specialEntity)
|
||||
}
|
||||
initView()
|
||||
} else {
|
||||
containerCatalog.visibility = View.GONE
|
||||
reuseNoneData.root.visibility = View.VISIBLE
|
||||
}
|
||||
} else {
|
||||
containerCatalog.visibility = View.GONE
|
||||
reuseNoneData.root.visibility = View.GONE
|
||||
reuseNoConnection.root.visibility = View.VISIBLE
|
||||
reuseNoConnection.root.setOnClickListener {
|
||||
reuseNoConnection.root.visibility = View.GONE
|
||||
reuseLoading.root.visibility = View.VISIBLE
|
||||
mViewModel?.getCatalogs()
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
// 嵌入在首页时特殊处理
|
||||
if (arguments?.getBoolean(EntranceConsts.KEY_IS_HOME) == true) {
|
||||
mBinding?.divider?.visibility = View.GONE
|
||||
mBinding?.root?.setBackgroundColor(R.color.ui_surface.toColor(requireContext()))
|
||||
mBinding?.root?.setPadding(0, 8F.dip2px(), 0, 0)
|
||||
mBinding?.rvCatalog?.setBackgroundColor(R.color.ui_background.toColor(requireContext()))
|
||||
}
|
||||
}
|
||||
|
||||
private fun initView() {
|
||||
mEntity?.run {
|
||||
mViewModel?.run {
|
||||
if (subCatalog.isNotEmpty()) {
|
||||
if (mLastSelectedPosition != -1) {
|
||||
selectedCatalogPosition = mLastSelectedPosition
|
||||
selectedCatalogName = subCatalog[mLastSelectedPosition].name
|
||||
} else {
|
||||
selectedCatalogPosition = 0
|
||||
selectedCatalogName = subCatalog[0].name
|
||||
}
|
||||
mBinding?.rvCatalog?.layoutManager = FixLinearLayoutManager(requireContext())
|
||||
mBinding?.rvCatalog?.adapter =
|
||||
CatalogAdapter(requireContext(), this@CatalogFragment, this, subCatalog)
|
||||
|
||||
if (hasSpecial && selectedCatalogPosition == 0) {
|
||||
mSpecialCatalogFragment =
|
||||
childFragmentManager.findFragmentByTag(SpecialCatalogFragment::class.java.name) as? SpecialCatalogFragment
|
||||
?: SpecialCatalogFragment()
|
||||
mSpecialCatalogFragment?.arguments = bundleOf(
|
||||
EntranceConsts.KEY_IS_CATEGORY_V2 to false,
|
||||
EntranceConsts.KEY_CATALOG_ID to id,
|
||||
EntranceConsts.KEY_CATALOG_TITLE to mCatalogTitle,
|
||||
EntranceConsts.KEY_EXPOSURE_SOURCE to arguments?.getParcelable(
|
||||
EntranceConsts.KEY_EXPOSURE_SOURCE
|
||||
)
|
||||
)
|
||||
childFragmentManager.beginTransaction().replace(
|
||||
R.id.container_sub_catalog,
|
||||
mSpecialCatalogFragment!!,
|
||||
SpecialCatalogFragment::class.java.name
|
||||
).commitAllowingStateLoss()
|
||||
} else {
|
||||
mSubCatalogFragment =
|
||||
childFragmentManager.findFragmentByTag(SubCatalogFragment::class.java.name) as? SubCatalogFragment
|
||||
?: SubCatalogFragment()
|
||||
mSubCatalogFragment?.arguments = bundleOf(
|
||||
EntranceConsts.KEY_CATALOG_ID to id,
|
||||
EntranceConsts.KEY_PRIMARY_CATALOG_ID to subCatalog[selectedCatalogPosition].id,
|
||||
EntranceConsts.KEY_CATALOG_TITLE to mCatalogTitle
|
||||
)
|
||||
childFragmentManager.beginTransaction().replace(
|
||||
R.id.container_sub_catalog,
|
||||
mSubCatalogFragment!!,
|
||||
SubCatalogFragment::class.java.name
|
||||
).commitAllowingStateLoss()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun changeCatalog(position: Int) {
|
||||
mEntity?.run {
|
||||
mViewModel?.run {
|
||||
if (hasSpecial) {
|
||||
changeCatalogIfHasSpecial(position)
|
||||
} else {
|
||||
changeSubCatalogInSubCatalogFragment(position)
|
||||
}
|
||||
selectedCatalogPosition = position
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun changeCatalogIfHasSpecial(position: Int) {
|
||||
mViewModel?.run {
|
||||
when {
|
||||
selectedCatalogPosition == 0 -> changeToSubCatalogFragment(position)
|
||||
position == 0 -> changeToSpecialCatalogFragment()
|
||||
else -> changeSubCatalogInSubCatalogFragment(position)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun changeToSubCatalogFragment(position: Int) {
|
||||
mEntity?.run {
|
||||
mSubCatalogFragment =
|
||||
childFragmentManager.findFragmentByTag(SubCatalogFragment::class.java.name) as? SubCatalogFragment
|
||||
?: SubCatalogFragment()
|
||||
mSubCatalogFragment?.arguments = bundleOf(
|
||||
EntranceConsts.KEY_CATALOG_ID to id,
|
||||
EntranceConsts.KEY_PRIMARY_CATALOG_ID to subCatalog[position].id,
|
||||
EntranceConsts.KEY_CATALOG_TITLE to mCatalogTitle
|
||||
)
|
||||
childFragmentManager.beginTransaction().replace(
|
||||
R.id.container_sub_catalog,
|
||||
mSubCatalogFragment!!,
|
||||
SubCatalogFragment::class.java.name
|
||||
).commitAllowingStateLoss()
|
||||
}
|
||||
}
|
||||
|
||||
private fun changeToSpecialCatalogFragment() {
|
||||
mEntity?.run {
|
||||
mSpecialCatalogFragment =
|
||||
childFragmentManager.findFragmentByTag(SpecialCatalogFragment::class.java.name) as? SpecialCatalogFragment
|
||||
?: SpecialCatalogFragment()
|
||||
mSpecialCatalogFragment?.arguments = bundleOf(
|
||||
EntranceConsts.KEY_IS_CATEGORY_V2 to false,
|
||||
EntranceConsts.KEY_CATALOG_ID to id,
|
||||
EntranceConsts.KEY_CATALOG_TITLE to mCatalogTitle,
|
||||
EntranceConsts.KEY_EXPOSURE_SOURCE to arguments?.getParcelable(
|
||||
EntranceConsts.KEY_EXPOSURE_SOURCE
|
||||
)
|
||||
)
|
||||
childFragmentManager.beginTransaction().replace(
|
||||
R.id.container_sub_catalog,
|
||||
mSpecialCatalogFragment!!,
|
||||
SpecialCatalogFragment::class.java.name
|
||||
).commitAllowingStateLoss()
|
||||
}
|
||||
}
|
||||
|
||||
private fun changeSubCatalogInSubCatalogFragment(position: Int) {
|
||||
mEntity?.run {
|
||||
if (mSubCatalogFragment?.isStateSaved == false) {
|
||||
mSubCatalogFragment?.arguments = bundleOf(
|
||||
EntranceConsts.KEY_CATALOG_ID to id,
|
||||
EntranceConsts.KEY_PRIMARY_CATALOG_ID to subCatalog[position].id,
|
||||
EntranceConsts.KEY_CATALOG_TITLE to mCatalogTitle
|
||||
)
|
||||
}
|
||||
mSubCatalogFragment?.changeSubCatalog(subCatalog[position].id)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDarkModeChanged() {
|
||||
super.onDarkModeChanged()
|
||||
mBinding?.rvCatalog?.adapter?.run {
|
||||
notifyItemRangeChanged(0, itemCount)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,72 +0,0 @@
|
||||
package com.gh.gamecenter.catalog
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.Application
|
||||
import androidx.lifecycle.AndroidViewModel
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import com.gh.common.util.LogUtils
|
||||
import com.gh.gamecenter.entity.CatalogEntity
|
||||
import com.gh.gamecenter.common.retrofit.BiResponse
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager
|
||||
import com.halo.assistant.HaloApp
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
|
||||
class CatalogViewModel(application: Application, val catalogId: String, val catalogTitle: String) :
|
||||
AndroidViewModel(application) {
|
||||
|
||||
private val api = RetrofitManager.getInstance().api
|
||||
var catalogs = MutableLiveData<CatalogEntity>()
|
||||
|
||||
var selectedCatalogName: String = ""
|
||||
var selectedCatalogPosition: Int = 0
|
||||
|
||||
var validEntranceName: String = ""
|
||||
|
||||
init {
|
||||
getCatalogs()
|
||||
}
|
||||
|
||||
@SuppressLint("CheckResult")
|
||||
fun getCatalogs() {
|
||||
api.getCatalogs(catalogId)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(object : BiResponse<CatalogEntity>() {
|
||||
override fun onSuccess(data: CatalogEntity) {
|
||||
catalogs.postValue(data)
|
||||
}
|
||||
|
||||
override fun onFailure(exception: Exception) {
|
||||
super.onFailure(exception)
|
||||
catalogs.postValue(null)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fun logAppearance() {
|
||||
LogUtils.logNewCatalogAppearanceEvent(validEntranceName, catalogTitle)
|
||||
}
|
||||
|
||||
fun logSubCatalogClick(position: Int) {
|
||||
LogUtils.logSubCatalogClickEvent(validEntranceName, "${catalogTitle}_${selectedCatalogName}", position)
|
||||
}
|
||||
|
||||
fun logSubCatalogContentClick(itemName: String, listPosition: Int) {
|
||||
LogUtils.logSubCatalogContentClickEvent(
|
||||
validEntranceName,
|
||||
"${catalogTitle}_${selectedCatalogName}_${itemName}",
|
||||
selectedCatalogPosition,
|
||||
listPosition
|
||||
)
|
||||
}
|
||||
|
||||
class Factory(private val catalogId: String, private val catalogTitle: String) :
|
||||
ViewModelProvider.NewInstanceFactory() {
|
||||
override fun <T : ViewModel> create(modelClass: Class<T>): T {
|
||||
return CatalogViewModel(HaloApp.getInstance().application, catalogId, catalogTitle) as T
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,56 +0,0 @@
|
||||
package com.gh.gamecenter.catalog
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import com.gh.base.DownloadToolbarActivity
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.constant.EntranceConsts
|
||||
import com.gh.gamecenter.common.utils.updateStatusBarColor
|
||||
import com.gh.gamecenter.entity.CatalogEntity
|
||||
|
||||
class NewCatalogListActivity : DownloadToolbarActivity() {
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setToolbarMenu(R.menu.menu_download)
|
||||
updateStatusBarColor(R.color.ui_surface, R.color.ui_surface)
|
||||
}
|
||||
|
||||
override fun showDownloadMenu(): Boolean {
|
||||
return true
|
||||
}
|
||||
|
||||
override fun onDarkModeChanged() {
|
||||
super.onDarkModeChanged()
|
||||
updateStatusBarColor(R.color.ui_surface, R.color.ui_surface)
|
||||
}
|
||||
|
||||
override fun isAutoResetViewBackgroundEnabled() = true
|
||||
|
||||
companion object {
|
||||
fun getIntent(
|
||||
context: Context,
|
||||
primaryCatalogId: String, // 一级分类 id
|
||||
primaryCatalogName: String, // 一级分类名
|
||||
catalogTitle: String,
|
||||
catalog: CatalogEntity,
|
||||
initTitle: String
|
||||
): Intent {
|
||||
val bundle = Bundle()
|
||||
bundle.putParcelable(EntranceConsts.KEY_DATA, catalog)
|
||||
bundle.putString(EntranceConsts.KEY_PRIMARY_CATALOG_ID, primaryCatalogId)
|
||||
bundle.putString(EntranceConsts.KEY_PRIMARY_CATALOG_NAME, primaryCatalogName)
|
||||
bundle.putString(EntranceConsts.KEY_NAME, catalog.name)
|
||||
bundle.putString(EntranceConsts.KEY_CATALOG_TITLE, catalogTitle)
|
||||
bundle.putString(EntranceConsts.KEY_CATALOG_INIT_TITLE, initTitle)
|
||||
return getTargetIntent(
|
||||
context,
|
||||
NewCatalogListActivity::class.java,
|
||||
NewCatalogListFragment::class.java,
|
||||
bundle
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,192 +0,0 @@
|
||||
package com.gh.gamecenter.catalog
|
||||
|
||||
import android.content.Context
|
||||
import android.util.SparseArray
|
||||
import android.view.ViewGroup
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.gh.common.exposure.IExposable
|
||||
import com.gh.common.util.DownloadItemUtils
|
||||
import com.gh.gamecenter.GameDetailActivity
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.adapter.viewholder.GameViewHolder
|
||||
import com.gh.gamecenter.common.baselist.ListAdapter
|
||||
import com.gh.gamecenter.common.constant.ItemViewType
|
||||
import com.gh.gamecenter.common.exposure.ExposureSource
|
||||
import com.gh.gamecenter.common.utils.dip2px
|
||||
import com.gh.gamecenter.common.utils.toBinding
|
||||
import com.gh.gamecenter.common.viewholder.FooterViewHolder
|
||||
import com.gh.gamecenter.core.utils.StringUtils
|
||||
import com.gh.gamecenter.eventbus.EBDownloadStatus
|
||||
import com.gh.gamecenter.feature.entity.GameEntity
|
||||
import com.gh.gamecenter.feature.exposure.ExposureEvent
|
||||
import com.gh.gamecenter.feature.exposure.ExposureType
|
||||
import com.gh.gamecenter.feature.game.GameItemViewHolder
|
||||
import com.lightgame.download.DownloadEntity
|
||||
|
||||
class NewCatalogListAdapter(
|
||||
context: Context,
|
||||
private val mBaseExposureSource: ExposureSource,
|
||||
private val mViewModel: NewCatalogListViewModel,
|
||||
private val mEntrance: String?
|
||||
) : ListAdapter<GameEntity>(context), IExposable {
|
||||
|
||||
private val mExposureEventSparseArray: SparseArray<ExposureEvent> = SparseArray()
|
||||
|
||||
val positionAndPackageMap = HashMap<String, Int>()
|
||||
|
||||
override fun setListData(updateData: MutableList<GameEntity>?) {
|
||||
// 记录游戏位置
|
||||
if (updateData != null) {
|
||||
for (i in 0 until updateData.size) {
|
||||
val gameEntity = updateData[i]
|
||||
var packages = gameEntity.id
|
||||
for (apkEntity in gameEntity.getApk()) {
|
||||
packages += apkEntity.packageName
|
||||
}
|
||||
positionAndPackageMap[packages + i] = i
|
||||
}
|
||||
}
|
||||
super.setListData(updateData)
|
||||
}
|
||||
|
||||
fun clearPositionAndPackageMap() {
|
||||
positionAndPackageMap.clear()
|
||||
}
|
||||
|
||||
override fun areItemsTheSame(oldItem: GameEntity?, newItem: GameEntity?): Boolean {
|
||||
return oldItem?.id == newItem?.id
|
||||
}
|
||||
|
||||
override fun getItemViewType(position: Int): Int {
|
||||
if (position == itemCount - 1) {
|
||||
return ItemViewType.ITEM_FOOTER
|
||||
}
|
||||
return ItemViewType.GAME_NORMAL
|
||||
}
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
|
||||
return when (viewType) {
|
||||
ItemViewType.GAME_NORMAL -> {
|
||||
GameItemViewHolder(parent.toBinding())
|
||||
}
|
||||
else -> {
|
||||
FooterViewHolder(mLayoutInflater.inflate(R.layout.refresh_footerview, parent, false))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int {
|
||||
return if (mEntityList == null || mEntityList.isEmpty()) return 0 else mEntityList.size + 1
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
|
||||
if (holder is GameItemViewHolder) {
|
||||
val padTop = if (position == 0) 16F.dip2px() else 8F.dip2px()
|
||||
holder.itemView.setPadding(16F.dip2px(), padTop, 16F.dip2px(), 8F.dip2px())
|
||||
|
||||
val gameEntity = mEntityList[position]
|
||||
|
||||
holder.bindGameItem(gameEntity)
|
||||
holder.initServerType(gameEntity)
|
||||
|
||||
val sortType = mViewModel.sortType.value
|
||||
val sortSize = mViewModel.sortSize.text
|
||||
val toolbarTitle = mViewModel.title
|
||||
val selectedCatalogName = mViewModel.selectedCatalog.name
|
||||
|
||||
val exposureSources = ArrayList<ExposureSource>()
|
||||
exposureSources.add(mBaseExposureSource)
|
||||
exposureSources.add(ExposureSource(toolbarTitle))
|
||||
exposureSources.add(ExposureSource("二级分类详情", "$selectedCatalogName+$sortType+$sortSize"))
|
||||
|
||||
val event = ExposureEvent.createEvent(gameEntity, exposureSources, null, ExposureType.EXPOSURE)
|
||||
mExposureEventSparseArray.put(position, event)
|
||||
|
||||
holder.itemView.setOnClickListener {
|
||||
GameDetailActivity.startGameDetailActivity(
|
||||
mContext,
|
||||
gameEntity,
|
||||
StringUtils.buildString(
|
||||
mEntrance,
|
||||
"+(",
|
||||
toolbarTitle,
|
||||
":列表[",
|
||||
selectedCatalogName,
|
||||
"=",
|
||||
sortType,
|
||||
"=",
|
||||
(position + 1).toString(),
|
||||
"])"
|
||||
),
|
||||
traceEvent = event
|
||||
)
|
||||
}
|
||||
DownloadItemUtils.setOnClickListener(
|
||||
mContext,
|
||||
holder.binding.downloadBtn,
|
||||
gameEntity,
|
||||
position,
|
||||
this,
|
||||
StringUtils.buildString(
|
||||
StringUtils.buildString(
|
||||
mEntrance,
|
||||
"+(",
|
||||
toolbarTitle,
|
||||
":列表[",
|
||||
selectedCatalogName,
|
||||
"=",
|
||||
sortType,
|
||||
"=",
|
||||
(position + 1).toString(),
|
||||
"])"
|
||||
)
|
||||
),
|
||||
location = StringUtils.buildString(selectedCatalogName, ":", gameEntity.name),
|
||||
traceEvent = event
|
||||
)
|
||||
|
||||
DownloadItemUtils.updateItem(mContext, gameEntity, GameViewHolder(holder.binding), "star&brief")
|
||||
} else if (holder is FooterViewHolder) {
|
||||
holder.initItemPadding()
|
||||
holder.initFooterViewHolder(mViewModel, mIsLoading, mIsNetworkError, mIsOver)
|
||||
}
|
||||
}
|
||||
|
||||
fun notifyItemByDownload(download: DownloadEntity) {
|
||||
for (key in positionAndPackageMap.keys) {
|
||||
// sentry上报download.packageName可能为空
|
||||
if (download.packageName != null
|
||||
&& download.gameId != null
|
||||
&& key.contains(download.packageName)
|
||||
&& key.contains(download.gameId)
|
||||
) {
|
||||
val position = positionAndPackageMap[key]
|
||||
if (position != null && mEntityList != null && position < mEntityList.size) {
|
||||
mEntityList[position].getEntryMap()[download.platform] = download
|
||||
notifyItemChanged(position)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun notifyItemAndRemoveDownload(status: EBDownloadStatus) {
|
||||
for (key in positionAndPackageMap.keys) {
|
||||
if (key.contains(status.packageName) && key.contains(status.gameId)) {
|
||||
val position = positionAndPackageMap[key]
|
||||
if (position != null && mEntityList != null && position < mEntityList.size) {
|
||||
mEntityList[position].getEntryMap().remove(status.platform)
|
||||
notifyItemChanged(position)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun getEventByPosition(pos: Int): ExposureEvent? {
|
||||
return mExposureEventSparseArray.get(pos)
|
||||
}
|
||||
|
||||
override fun getEventListByPosition(pos: Int): List<ExposureEvent>? {
|
||||
return null
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,209 +0,0 @@
|
||||
package com.gh.gamecenter.catalog
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import com.ethanhua.skeleton.Skeleton
|
||||
import com.gh.common.exposure.ExposureListener
|
||||
import com.gh.common.util.DialogUtils
|
||||
import com.gh.common.view.CatalogFilterView
|
||||
import com.gh.common.xapk.XapkInstaller
|
||||
import com.gh.common.xapk.XapkUnzipStatus
|
||||
import com.gh.download.DownloadManager
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.constant.Constants
|
||||
import com.gh.gamecenter.common.constant.EntranceConsts
|
||||
import com.gh.gamecenter.common.utils.observeNonNull
|
||||
import com.gh.gamecenter.common.baselist.ListFragment
|
||||
import com.gh.gamecenter.common.exposure.ExposureSource
|
||||
import com.gh.gamecenter.common.utils.toColor
|
||||
import com.gh.gamecenter.common.utils.viewModelProvider
|
||||
import com.gh.gamecenter.databinding.FragmentCatalogListBinding
|
||||
import com.gh.gamecenter.entity.CatalogEntity
|
||||
import com.gh.gamecenter.feature.entity.GameEntity
|
||||
import com.gh.gamecenter.entity.SubjectSettingEntity
|
||||
import com.gh.gamecenter.eventbus.EBDownloadStatus
|
||||
import com.gh.gamecenter.eventbus.EBPackage
|
||||
import com.lightgame.download.DataWatcher
|
||||
import com.lightgame.download.DownloadEntity
|
||||
import org.greenrobot.eventbus.Subscribe
|
||||
import org.greenrobot.eventbus.ThreadMode
|
||||
|
||||
class NewCatalogListFragment : ListFragment<GameEntity, NewCatalogListViewModel>() {
|
||||
|
||||
private var mPrimaryCatalogName: String = "" // 一级分类名
|
||||
private var mPrimaryCatalogId: String = "" // 一级分类 id
|
||||
private var mPrimeCatalog: CatalogEntity? = null
|
||||
private var mSubCatalogList = arrayListOf<CatalogEntity.SubCatalogEntity>()
|
||||
private var mInitCatalogName = ""
|
||||
private var mAdapter: NewCatalogListAdapter? = null
|
||||
private val mDataWatcher = object : DataWatcher() {
|
||||
override fun onDataChanged(downloadEntity: DownloadEntity) {
|
||||
mAdapter?.notifyItemByDownload(downloadEntity)
|
||||
|
||||
if (downloadEntity.meta[XapkInstaller.XAPK_UNZIP_STATUS] == XapkUnzipStatus.FAILURE.name) {
|
||||
showUnzipFailureDialog(downloadEntity)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDataInit(downloadEntity: DownloadEntity) {
|
||||
mAdapter?.notifyItemByDownload(downloadEntity)
|
||||
}
|
||||
}
|
||||
|
||||
private var mBinding: FragmentCatalogListBinding? = null
|
||||
private lateinit var mExposureListener: ExposureListener
|
||||
private lateinit var mViewModel: NewCatalogListViewModel
|
||||
|
||||
override fun getLayoutId() = 0
|
||||
|
||||
override fun getInflatedLayout() = FragmentCatalogListBinding.inflate(layoutInflater).apply { mBinding = this }.root
|
||||
|
||||
override fun provideListViewModel() = viewModelProvider<NewCatalogListViewModel>()
|
||||
|
||||
override fun provideListAdapter() = mAdapter
|
||||
?: NewCatalogListAdapter(
|
||||
requireContext(),
|
||||
ExposureSource(mPrimaryCatalogName),
|
||||
mViewModel,
|
||||
mEntrance
|
||||
).apply { mAdapter = this }
|
||||
|
||||
override fun getItemDecoration() = null
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
mViewModel = provideListViewModel()
|
||||
|
||||
mViewModel.title = arguments?.getString(EntranceConsts.KEY_NAME) ?: ""
|
||||
mViewModel.categoryTitle = arguments?.getString(EntranceConsts.KEY_CATALOG_TITLE) ?: ""
|
||||
mEntrance = arguments?.getString(EntranceConsts.KEY_ENTRANCE) ?: Constants.ENTRANCE_UNKNOWN
|
||||
mPrimeCatalog = arguments?.getParcelable(EntranceConsts.KEY_DATA)
|
||||
mSubCatalogList = mPrimeCatalog?.subCatalog as? ArrayList<CatalogEntity.SubCatalogEntity> ?: arrayListOf()
|
||||
|
||||
mInitCatalogName = arguments?.getString(EntranceConsts.KEY_CATALOG_INIT_TITLE) ?: ""
|
||||
mPrimaryCatalogName = arguments?.getString(EntranceConsts.KEY_PRIMARY_CATALOG_NAME) ?: ""
|
||||
mPrimaryCatalogId = arguments?.getString(EntranceConsts.KEY_PRIMARY_CATALOG_ID) ?: ""
|
||||
|
||||
mViewModel.selectedCatalog = mSubCatalogList.find { entity -> entity.name == mInitCatalogName }
|
||||
?: CatalogEntity.SubCatalogEntity()
|
||||
mViewModel.primaryCatalogId = mPrimaryCatalogId
|
||||
initSortType()
|
||||
|
||||
super.onCreate(savedInstanceState)
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
setNavigationTitle(mViewModel.title)
|
||||
|
||||
initFilterView()
|
||||
|
||||
mViewModel.refresh.observeNonNull(this) { onRefresh() }
|
||||
|
||||
mExposureListener = ExposureListener(this, mAdapter!!)
|
||||
mListRv.addOnScrollListener(mExposureListener)
|
||||
|
||||
mSkeletonScreen = Skeleton.bind(mBinding?.listSkeleton)
|
||||
.shimmer(true)
|
||||
.angle(Constants.SHIMMER_ANGLE)
|
||||
.color(R.color.ui_skeleton_highlight)
|
||||
.duration(Constants.SHIMMER_DURATION)
|
||||
.maskWidth(Constants.MASK_WIDTH)
|
||||
.gradientCenterColorWidth(Constants.GRADIENT_CENTER_COLOR_WIDTH)
|
||||
.load(R.layout.fragment_tags_skeleton)
|
||||
.show()
|
||||
}
|
||||
|
||||
private fun initSortType() {
|
||||
mPrimeCatalog?.switch?.run {
|
||||
if (hotSort == "on") {
|
||||
mViewModel.sortType = CatalogFilterView.SortType.RECOMMENDED
|
||||
return@run
|
||||
}
|
||||
if (newSort == "on") {
|
||||
mViewModel.sortType = CatalogFilterView.SortType.NEWEST
|
||||
return@run
|
||||
}
|
||||
if (starSort == "on") {
|
||||
mViewModel.sortType = CatalogFilterView.SortType.RATING
|
||||
return@run
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun initFilterView() {
|
||||
mBinding?.filterContainer?.run {
|
||||
visibility = View.VISIBLE
|
||||
setTypeList(mPrimeCatalog?.switch ?: CatalogEntity.CatalogSwitch())
|
||||
setCatalogList(mSubCatalogList, mInitCatalogName)
|
||||
setOnConfigSetupListener(object : CatalogFilterView.OnCatalogFilterSetupListener {
|
||||
override fun onSetupSortSize(sortSize: SubjectSettingEntity.Size) {
|
||||
mViewModel.updateSortConfig(sortSize = sortSize)
|
||||
}
|
||||
|
||||
override fun onSetupSortType(sortType: CatalogFilterView.SortType) {
|
||||
mViewModel.updateSortConfig(sortType = sortType)
|
||||
}
|
||||
|
||||
override fun onSetupSortCatalog(sortCatalog: CatalogEntity.SubCatalogEntity) {
|
||||
mViewModel.updateSortConfig(sortCatalog = sortCatalog)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
DownloadManager.getInstance().addObserver(mDataWatcher)
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
DownloadManager.getInstance().removeObserver(mDataWatcher)
|
||||
}
|
||||
|
||||
override fun onRefresh() {
|
||||
mAdapter?.clearPositionAndPackageMap()
|
||||
|
||||
super.onRefresh()
|
||||
}
|
||||
|
||||
// 下载被删除事件
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
fun onEventMainThread(status: EBDownloadStatus) {
|
||||
if ("delete" == status.status) {
|
||||
mAdapter?.notifyItemAndRemoveDownload(status)
|
||||
}
|
||||
}
|
||||
|
||||
// 安装/卸载 事件
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
fun onEventMainThread(busFour: EBPackage) {
|
||||
if (busFour.isInstalledOrUninstalled()) {
|
||||
mAdapter?.notifyDataSetChanged()
|
||||
}
|
||||
}
|
||||
|
||||
fun showUnzipFailureDialog(downloadEntity: DownloadEntity) {
|
||||
val data = mAdapter?.positionAndPackageMap ?: return
|
||||
for (gameAndPosition in data) {
|
||||
if (gameAndPosition.key.contains(downloadEntity.packageName)) {
|
||||
val targetView = mLayoutManager.findViewByPosition(gameAndPosition.value)
|
||||
if (targetView != null) {
|
||||
DialogUtils.showUnzipFailureDialog(requireContext(), downloadEntity)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDarkModeChanged() {
|
||||
super.onDarkModeChanged()
|
||||
mBinding?.filterContainer?.run {
|
||||
setRootBackgroundColor(R.color.ui_surface.toColor(requireContext()))
|
||||
setItemTextColor(R.color.text_secondary.toColor(requireContext()))
|
||||
updatePopupWindow()
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,98 +0,0 @@
|
||||
package com.gh.gamecenter.catalog
|
||||
|
||||
import android.app.Application
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import com.gh.gamecenter.common.entity.ExposureEntity
|
||||
import com.gh.common.exposure.ExposureUtils
|
||||
import com.gh.gamecenter.core.utils.UrlFilterUtils
|
||||
import com.gh.common.view.CatalogFilterView
|
||||
import com.gh.gamecenter.common.baselist.ListViewModel
|
||||
import com.gh.gamecenter.entity.CatalogEntity
|
||||
import com.gh.gamecenter.feature.entity.GameEntity
|
||||
import com.gh.gamecenter.entity.SubjectSettingEntity
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager
|
||||
import io.reactivex.Observable
|
||||
import io.reactivex.Single
|
||||
|
||||
class NewCatalogListViewModel(application: Application) : ListViewModel<GameEntity, GameEntity>(application) {
|
||||
|
||||
var title = "" // 显示在 Toolbar 的标题
|
||||
var categoryTitle = "" // 跳转进来的分类的标题
|
||||
|
||||
val refresh = MutableLiveData<Boolean>()
|
||||
|
||||
var selectedCatalog = CatalogEntity.SubCatalogEntity()
|
||||
var sortType = CatalogFilterView.SortType.RECOMMENDED
|
||||
var sortSize = SubjectSettingEntity.Size()
|
||||
|
||||
var primaryCatalogId = "" // 一级分类 id
|
||||
private val sensitiveApi = RetrofitManager.getInstance().api
|
||||
|
||||
override fun provideDataObservable(page: Int): Observable<List<GameEntity>>? = null
|
||||
|
||||
override fun provideDataSingle(page: Int): Single<List<GameEntity>> {
|
||||
return if (selectedCatalog.link.type == "column") { // column(专题)/tag(标签)
|
||||
sensitiveApi.getColumn(selectedCatalog.link.link, getSortType(), getSortSize(), page) // 专题
|
||||
} else {
|
||||
sensitiveApi.getGamesWithSpecificTag(getSortSize(), getSortType(), page) // 标签
|
||||
}
|
||||
}
|
||||
|
||||
override fun mergeResultLiveData() {
|
||||
mResultLiveData.addSource(mListLiveData) {
|
||||
it.forEach { game -> game.hideSizeInsideDes = true }
|
||||
ExposureUtils.updateExposureInfo(
|
||||
gameList = it,
|
||||
containerId = primaryCatalogId,
|
||||
containerType = ExposureEntity.CATEGORY_ID
|
||||
)
|
||||
mResultLiveData.postValue(it)
|
||||
}
|
||||
}
|
||||
|
||||
fun updateSortConfig(
|
||||
sortSize: SubjectSettingEntity.Size? = null,
|
||||
sortType: CatalogFilterView.SortType? = null,
|
||||
sortCatalog: CatalogEntity.SubCatalogEntity? = null
|
||||
) {
|
||||
when {
|
||||
sortSize != null && sortSize != this.sortSize -> {
|
||||
this.sortSize = sortSize
|
||||
refresh.postValue(true)
|
||||
}
|
||||
|
||||
sortType != null && sortType != this.sortType -> {
|
||||
this.sortType = sortType
|
||||
refresh.postValue(true)
|
||||
}
|
||||
|
||||
sortCatalog != null && sortCatalog != selectedCatalog -> {
|
||||
selectedCatalog = sortCatalog
|
||||
refresh.postValue(true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun getSortSize(): String? {
|
||||
return if (selectedCatalog.link.type == "column") {
|
||||
UrlFilterUtils.getFilterQuery(
|
||||
"min_size", sortSize.min.toString(),
|
||||
"max_size", sortSize.max.toString()
|
||||
)
|
||||
} else {
|
||||
UrlFilterUtils.getFilterQuery(
|
||||
"tag_id", selectedCatalog.link.link,
|
||||
"min_size", sortSize.min.toString(),
|
||||
"max_size", sortSize.max.toString()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun getSortType(): String? {
|
||||
return when (sortType) {
|
||||
CatalogFilterView.SortType.RECOMMENDED -> if (selectedCatalog.link.type == "column") "position:1" else "download:-1"
|
||||
CatalogFilterView.SortType.NEWEST -> "publish:-1"
|
||||
CatalogFilterView.SortType.RATING -> "star:-1"
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,54 +0,0 @@
|
||||
package com.gh.gamecenter.catalog
|
||||
|
||||
import android.content.Context
|
||||
import android.view.ViewGroup
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.base.BaseRecyclerViewHolder
|
||||
import com.gh.gamecenter.common.utils.*
|
||||
import com.gh.gamecenter.databinding.SubCatalogItemBinding
|
||||
import com.gh.gamecenter.entity.CatalogEntity
|
||||
import com.lightgame.adapter.BaseRecyclerAdapter
|
||||
|
||||
class SubCatalogAdapter(
|
||||
context: Context,
|
||||
private val mCatalogViewModel: CatalogViewModel,
|
||||
private val mPrimaryCatalog: CatalogEntity,
|
||||
private var mList: List<CatalogEntity.SubCatalogEntity>
|
||||
) : BaseRecyclerAdapter<SubCatalogAdapter.SubCatalogItemViewHolder>(context) {
|
||||
|
||||
private val mTypes = listOf("专题", "标签")
|
||||
|
||||
override fun getItemCount() = mList.size
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) =
|
||||
SubCatalogItemViewHolder(parent.toBinding())
|
||||
|
||||
override fun onBindViewHolder(holder: SubCatalogItemViewHolder, position: Int) {
|
||||
holder.binding.run {
|
||||
val catalogEntity = mList[position]
|
||||
ImageUtils.display(catalogIcon, catalogEntity.icon)
|
||||
catalogName.text = catalogEntity.name
|
||||
catalogName.setTextColor(R.color.text_primary.toColor(mContext))
|
||||
recommendTag.goneIf(!catalogEntity.recommended)
|
||||
root.setOnClickListener {
|
||||
mCatalogViewModel.logSubCatalogContentClick(catalogEntity.name, position)
|
||||
if (mTypes.contains(catalogEntity.type)) {
|
||||
root.context.startActivity(
|
||||
NewCatalogListActivity.getIntent(
|
||||
mContext,
|
||||
mCatalogViewModel.catalogId,
|
||||
mCatalogViewModel.catalogTitle,
|
||||
catalogEntity.name,
|
||||
mPrimaryCatalog,
|
||||
catalogEntity.name
|
||||
)
|
||||
)
|
||||
} else {
|
||||
DialogHelper.showUpgradeDialog(mContext)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class SubCatalogItemViewHolder(val binding: SubCatalogItemBinding) : BaseRecyclerViewHolder<Any>(binding.root)
|
||||
}
|
||||
@ -1,94 +0,0 @@
|
||||
package com.gh.gamecenter.catalog
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import androidx.lifecycle.Observer
|
||||
import androidx.recyclerview.widget.GridLayoutManager
|
||||
import com.gh.gamecenter.common.constant.EntranceConsts
|
||||
import com.gh.gamecenter.common.utils.viewModelProvider
|
||||
import com.gh.gamecenter.common.utils.viewModelProviderFromParent
|
||||
import com.gh.gamecenter.databinding.FragmentSubCatalogBinding
|
||||
import com.gh.gamecenter.entity.CatalogEntity
|
||||
import com.gh.gamecenter.common.base.fragment.ToolbarFragment
|
||||
|
||||
class SubCatalogFragment : ToolbarFragment() {
|
||||
|
||||
private var mBinding: FragmentSubCatalogBinding? = null
|
||||
private var mViewModel: SubCatalogViewModel? = null
|
||||
private var mCatalogViewModel: CatalogViewModel? = null
|
||||
private var mEntity: CatalogEntity? = null
|
||||
private var mCatalogId: String = ""
|
||||
private var mCatalogTitle: String = ""
|
||||
private var mPrimaryCatalogId: String = ""
|
||||
|
||||
override fun getLayoutId() = 0
|
||||
|
||||
override fun getInflatedLayout() = FragmentSubCatalogBinding.inflate(layoutInflater).apply { mBinding = this }.root
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
mCatalogId = arguments?.getString(EntranceConsts.KEY_CATALOG_ID) ?: ""
|
||||
mCatalogTitle = arguments?.getString(EntranceConsts.KEY_CATALOG_TITLE) ?: ""
|
||||
mPrimaryCatalogId = arguments?.getString(EntranceConsts.KEY_PRIMARY_CATALOG_ID) ?: ""
|
||||
mViewModel = viewModelProvider(SubCatalogViewModel.Factory(mCatalogId))
|
||||
mCatalogViewModel = viewModelProviderFromParent(CatalogViewModel.Factory(mCatalogId, mCatalogTitle), mCatalogId)
|
||||
mViewModel?.getSubCatalogs(mPrimaryCatalogId)
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
mViewModel?.catalogs?.observe(viewLifecycleOwner, Observer {
|
||||
mBinding?.run {
|
||||
reuseLoading.root.visibility = View.GONE
|
||||
if (it != null) {
|
||||
reuseNoConnection.root.visibility = View.GONE
|
||||
if (it.subCatalog.isNotEmpty()) {
|
||||
rvSubCatalog.visibility = View.VISIBLE
|
||||
reuseNoneData.root.visibility = View.GONE
|
||||
mEntity = it
|
||||
initView()
|
||||
} else {
|
||||
rvSubCatalog.visibility = View.GONE
|
||||
reuseNoneData.root.visibility = View.VISIBLE
|
||||
}
|
||||
} else {
|
||||
rvSubCatalog.visibility = View.GONE
|
||||
reuseNoneData.root.visibility = View.GONE
|
||||
reuseNoConnection.root.visibility = View.VISIBLE
|
||||
reuseNoConnection.root.setOnClickListener {
|
||||
reuseLoading.root.visibility = View.VISIBLE
|
||||
mViewModel?.getSubCatalogs(mPrimaryCatalogId)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private fun initView() {
|
||||
mEntity?.takeIf { mCatalogViewModel != null }?.run {
|
||||
mBinding?.rvSubCatalog?.layoutManager = GridLayoutManager(requireContext(), 3)
|
||||
mBinding?.rvSubCatalog?.adapter = SubCatalogAdapter(requireContext(), mCatalogViewModel!!, this, subCatalog)
|
||||
}
|
||||
}
|
||||
|
||||
fun changeSubCatalog(primaryCatalogId: String) {
|
||||
mBinding?.run {
|
||||
mPrimaryCatalogId = primaryCatalogId
|
||||
rvSubCatalog.visibility = View.GONE
|
||||
reuseNoneData.root.visibility = View.GONE
|
||||
reuseNoConnection.root.visibility = View.GONE
|
||||
reuseLoading.root.visibility = View.VISIBLE
|
||||
mViewModel?.getSubCatalogs(mPrimaryCatalogId)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDarkModeChanged() {
|
||||
super.onDarkModeChanged()
|
||||
mBinding?.rvSubCatalog?.adapter?.run {
|
||||
mBinding?.rvSubCatalog?.recycledViewPool?.clear()
|
||||
notifyItemRangeChanged(0, itemCount)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,44 +0,0 @@
|
||||
package com.gh.gamecenter.catalog
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.Application
|
||||
import androidx.lifecycle.AndroidViewModel
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import com.gh.gamecenter.entity.CatalogEntity
|
||||
import com.gh.gamecenter.common.retrofit.BiResponse
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager
|
||||
import com.halo.assistant.HaloApp
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
|
||||
class SubCatalogViewModel(application: Application, private val catalogId: String) : AndroidViewModel(application) {
|
||||
|
||||
private val api = RetrofitManager.getInstance().api
|
||||
var catalogs = MutableLiveData<CatalogEntity>()
|
||||
|
||||
|
||||
@SuppressLint("CheckResult")
|
||||
fun getSubCatalogs(primaryCatalogId: String) {
|
||||
api.getSubCatalogs(catalogId, primaryCatalogId)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(object : BiResponse<CatalogEntity>() {
|
||||
override fun onSuccess(data: CatalogEntity) {
|
||||
catalogs.postValue(data)
|
||||
}
|
||||
|
||||
override fun onFailure(exception: Exception) {
|
||||
super.onFailure(exception)
|
||||
catalogs.postValue(null)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
class Factory(private val catalogId: String) : ViewModelProvider.NewInstanceFactory() {
|
||||
override fun <T : ViewModel> create(modelClass: Class<T>): T {
|
||||
return SubCatalogViewModel(HaloApp.getInstance().application, catalogId) as T
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,51 +0,0 @@
|
||||
package com.gh.gamecenter.category
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import com.gh.base.DownloadToolbarActivity
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.constant.EntranceConsts
|
||||
import com.gh.gamecenter.common.utils.updateStatusBarColor
|
||||
|
||||
class CategoryDirectoryActivity : DownloadToolbarActivity() {
|
||||
|
||||
companion object {
|
||||
fun getIntent(context: Context, categoryId: String, categoryTitle: String): Intent {
|
||||
val bundle = Bundle()
|
||||
bundle.putString(EntranceConsts.KEY_CATEGORY_ID, categoryId)
|
||||
bundle.putString(EntranceConsts.KEY_CATEGORY_TITLE, categoryTitle)
|
||||
return getTargetIntent(
|
||||
context,
|
||||
CategoryDirectoryActivity::class.java,
|
||||
CategoryDirectoryFragment::class.java,
|
||||
bundle
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setToolbarMenu(R.menu.menu_download)
|
||||
updateStatusBarColor(R.color.ui_surface, R.color.ui_surface)
|
||||
}
|
||||
|
||||
override fun showDownloadMenu(): Boolean {
|
||||
return true
|
||||
}
|
||||
|
||||
override fun getActivityNameInChinese(): String {
|
||||
return "游戏分类"
|
||||
}
|
||||
|
||||
override fun provideNormalIntent(): Intent {
|
||||
return getTargetIntent(this, CategoryDirectoryActivity::class.java, CategoryDirectoryFragment::class.java)
|
||||
}
|
||||
|
||||
override fun isAutoResetViewBackgroundEnabled() = true
|
||||
|
||||
override fun onDarkModeChanged() {
|
||||
super.onDarkModeChanged()
|
||||
updateStatusBarColor(R.color.ui_surface, R.color.ui_surface)
|
||||
}
|
||||
}
|
||||
@ -1,157 +0,0 @@
|
||||
package com.gh.gamecenter.category
|
||||
|
||||
import android.content.Context
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.LinearLayout
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.gh.common.view.SubCategoryView
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.baselist.ListAdapter
|
||||
import com.gh.gamecenter.category.CategoryListActivity.Companion.getIntent
|
||||
import com.gh.gamecenter.common.utils.ImageUtils
|
||||
import com.gh.gamecenter.common.utils.toBinding
|
||||
import com.gh.gamecenter.common.utils.toColor
|
||||
import com.gh.gamecenter.core.utils.DisplayUtils
|
||||
import com.gh.gamecenter.databinding.ItemCategoryBinding
|
||||
import com.gh.gamecenter.entity.CategoryEntity
|
||||
import net.cachapa.expandablelayout.ExpandableLayout
|
||||
|
||||
class CategoryDirectoryAdapter(context: Context, var categoryTitle: String) : ListAdapter<CategoryEntity>(context) {
|
||||
|
||||
var recyclerView: RecyclerView? = null
|
||||
var expandStatusMap: HashMap<Int, Boolean> = HashMap()
|
||||
|
||||
private var sixteenDp: Int = 0
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
|
||||
if (sixteenDp == 0) sixteenDp = DisplayUtils.dip2px(parent.context, 16f)
|
||||
return CategoryViewHolder(parent.toBinding())
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int {
|
||||
return mEntityList.size
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
|
||||
when (holder) {
|
||||
is CategoryViewHolder -> {
|
||||
val category = mEntityList[position]
|
||||
holder.binding.run {
|
||||
divider.setBackgroundColor(R.color.ui_background.toColor(mContext))
|
||||
containerPrimaryCategory.setOnClickListener {
|
||||
root.context.startActivity(getIntent(root.context, categoryTitle, category, "全部"))
|
||||
}
|
||||
ImageUtils.display(iconIv, category.icon)
|
||||
categoryName.text = category.name
|
||||
}
|
||||
holder.bindCategory(
|
||||
category = mEntityList[position],
|
||||
expandableStatusMap = expandStatusMap,
|
||||
isExpended = expandStatusMap[position] != null && expandStatusMap[position] == true,
|
||||
marginTop = sixteenDp,
|
||||
categoryTitle = categoryTitle,
|
||||
expandedAction = { recyclerView?.smoothScrollToPosition(position) })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal class CategoryViewHolder(var binding: ItemCategoryBinding) : RecyclerView.ViewHolder(binding.root) {
|
||||
fun bindCategory(
|
||||
category: CategoryEntity,
|
||||
expandableStatusMap: HashMap<Int, Boolean>,
|
||||
isExpended: Boolean,
|
||||
marginTop: Int,
|
||||
categoryTitle: String,
|
||||
expandedAction: () -> Unit
|
||||
) {
|
||||
category.data?.let {
|
||||
var subCategoryView: SubCategoryView? = null
|
||||
|
||||
binding.containerUnexpandable.removeAllViews()
|
||||
val unexpandableSize = if (it.size > 6) 6 else it.size
|
||||
val unexpandableCategoryList = it.subList(0, unexpandableSize)
|
||||
unexpandableCategoryList.forEachIndexed { index, c ->
|
||||
when (index % 3) {
|
||||
0 -> {
|
||||
val params = LinearLayout.LayoutParams(
|
||||
LinearLayout.LayoutParams.MATCH_PARENT,
|
||||
LinearLayout.LayoutParams.MATCH_PARENT
|
||||
)
|
||||
if (subCategoryView != null) params.setMargins(0, marginTop, 0, 0)
|
||||
|
||||
subCategoryView = SubCategoryView(binding.root.context)
|
||||
|
||||
subCategoryView?.categoryTitle = categoryTitle
|
||||
subCategoryView?.primeCategory = category
|
||||
subCategoryView?.layoutParams = params
|
||||
|
||||
binding.containerUnexpandable.addView(subCategoryView)
|
||||
subCategoryView?.setLeftCategory(c)
|
||||
}
|
||||
1 -> subCategoryView?.setCenterCategory(c)
|
||||
2 -> subCategoryView?.setRightCategory(c)
|
||||
}
|
||||
}
|
||||
|
||||
if (it.size >= 7) {
|
||||
val extraCategoryList = it.subList(6, it.size)
|
||||
|
||||
binding.ivToggle.visibility = View.VISIBLE
|
||||
binding.ivToggle.setOnClickListener { binding.containerExpandable.toggle() }
|
||||
when {
|
||||
isExpended -> binding.ivToggle.setImageResource(R.drawable.ic_category_arrow_up)
|
||||
else -> binding.ivToggle.setImageResource(R.drawable.ic_category_arrow_down)
|
||||
}
|
||||
|
||||
val subCategoryViewLinearLayout = LinearLayout(binding.root.context)
|
||||
subCategoryViewLinearLayout.orientation = LinearLayout.VERTICAL
|
||||
subCategoryView = SubCategoryView(binding.root.context)
|
||||
|
||||
binding.containerExpandable.removeAllViews()
|
||||
binding.containerExpandable.addView(subCategoryViewLinearLayout)
|
||||
binding.containerExpandable.setExpanded(isExpended, false)
|
||||
binding.containerExpandable.setOnExpansionUpdateListener { _, state ->
|
||||
when (state) {
|
||||
ExpandableLayout.State.COLLAPSED -> {
|
||||
binding.ivToggle.setImageResource(R.drawable.ic_category_arrow_down)
|
||||
expandableStatusMap[adapterPosition] = false
|
||||
}
|
||||
ExpandableLayout.State.EXPANDED -> {
|
||||
binding.ivToggle.setImageResource(R.drawable.ic_category_arrow_up)
|
||||
expandableStatusMap[adapterPosition] = true
|
||||
expandedAction.invoke()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extraCategoryList.forEachIndexed { index, c ->
|
||||
when (index % 3) {
|
||||
0 -> {
|
||||
subCategoryView = SubCategoryView(binding.root.context)
|
||||
|
||||
val params = LinearLayout.LayoutParams(
|
||||
LinearLayout.LayoutParams.MATCH_PARENT,
|
||||
LinearLayout.LayoutParams.MATCH_PARENT
|
||||
)
|
||||
params.setMargins(0, marginTop, 0, 0)
|
||||
|
||||
subCategoryView?.categoryTitle = categoryTitle
|
||||
subCategoryView?.primeCategory = category
|
||||
subCategoryView?.layoutParams = params
|
||||
|
||||
subCategoryViewLinearLayout.addView(subCategoryView)
|
||||
subCategoryView?.setLeftCategory(c)
|
||||
}
|
||||
1 -> subCategoryView?.setCenterCategory(c)
|
||||
2 -> subCategoryView?.setRightCategory(c)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
binding.ivToggle.visibility = View.GONE
|
||||
binding.containerExpandable.removeAllViews()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,104 +0,0 @@
|
||||
package com.gh.gamecenter.category
|
||||
|
||||
import android.graphics.Color
|
||||
import android.view.View
|
||||
import androidx.lifecycle.ViewModelProviders
|
||||
import com.ethanhua.skeleton.Skeleton
|
||||
import com.gh.gamecenter.common.constant.Constants
|
||||
import com.gh.gamecenter.common.constant.EntranceConsts
|
||||
import com.gh.gamecenter.common.utils.toColor
|
||||
import com.gh.gamecenter.common.view.VerticalItemDecoration
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.baselist.LazyListFragment
|
||||
import com.gh.gamecenter.databinding.FragmentListBaseSkeletonBinding
|
||||
import com.gh.gamecenter.entity.CategoryEntity
|
||||
|
||||
class CategoryDirectoryFragment : LazyListFragment<CategoryEntity, CategoryDirectoryListViewModel>() {
|
||||
|
||||
private lateinit var mViewModel: CategoryDirectoryListViewModel
|
||||
private lateinit var mAdapter: CategoryDirectoryAdapter
|
||||
private var mBinding: FragmentListBaseSkeletonBinding? = null
|
||||
|
||||
override fun getRealLayoutId() = R.layout.fragment_list_base_skeleton
|
||||
|
||||
override fun onRealLayoutInflated(inflatedView: View) {
|
||||
super.onRealLayoutInflated(inflatedView)
|
||||
mBinding = FragmentListBaseSkeletonBinding.bind(inflatedView)
|
||||
}
|
||||
|
||||
override fun onFragmentFirstVisible() {
|
||||
mViewModel = ViewModelProviders.of(this).get(CategoryDirectoryListViewModel::class.java)
|
||||
mViewModel.categoryId = arguments?.getString(EntranceConsts.KEY_CATEGORY_ID) ?: ""
|
||||
mAdapter =
|
||||
CategoryDirectoryAdapter(requireContext(), arguments?.getString(EntranceConsts.KEY_CATEGORY_TITLE) ?: "")
|
||||
super.onFragmentFirstVisible()
|
||||
}
|
||||
|
||||
override fun initRealView() {
|
||||
super.initRealView()
|
||||
|
||||
setNavigationTitle(arguments?.getString(EntranceConsts.KEY_CATEGORY_TITLE))
|
||||
|
||||
mSkeletonScreen = Skeleton.bind(mBinding?.listSkeleton)
|
||||
.shimmer(true)
|
||||
.angle(Constants.SHIMMER_ANGLE)
|
||||
.color(R.color.ui_skeleton_highlight)
|
||||
.duration(Constants.SHIMMER_DURATION)
|
||||
.maskWidth(Constants.MASK_WIDTH)
|
||||
.gradientCenterColorWidth(Constants.GRADIENT_CENTER_COLOR_WIDTH)
|
||||
.load(R.layout.fragment_category_skeleton)
|
||||
.show()
|
||||
onLoadRefresh()
|
||||
|
||||
if (arguments?.getBoolean(EntranceConsts.KEY_IS_HOME) == true) {
|
||||
mListRv?.setPadding(
|
||||
0,
|
||||
context?.resources?.getDimension(R.dimen.home_recyclerview_padding_top)?.toInt() ?: 0,
|
||||
0,
|
||||
0
|
||||
)
|
||||
mListRv?.clipToPadding = false
|
||||
}
|
||||
|
||||
mListRv?.setBackgroundColor(R.color.ui_surface.toColor(requireContext()))
|
||||
mAdapter.recyclerView = mListRv
|
||||
mListRefresh?.isEnabled = false
|
||||
}
|
||||
|
||||
override fun isAutomaticLoad() = false
|
||||
|
||||
override fun provideListAdapter() = mAdapter
|
||||
|
||||
override fun provideListViewModel() = mViewModel
|
||||
|
||||
override fun getItemDecoration() = VerticalItemDecoration(context, 0F, false)
|
||||
|
||||
override fun onLoadRefresh() {
|
||||
mCachedView?.setBackgroundColor(R.color.ui_surface.toColor(requireContext()))
|
||||
super.onLoadRefresh()
|
||||
}
|
||||
|
||||
override fun onLoadDone() {
|
||||
mCachedView?.setBackgroundColor(Color.TRANSPARENT)
|
||||
super.onLoadDone()
|
||||
}
|
||||
|
||||
override fun onLoadEmpty() {
|
||||
mCachedView?.setBackgroundColor(Color.TRANSPARENT)
|
||||
super.onLoadEmpty()
|
||||
}
|
||||
|
||||
override fun onLoadError() {
|
||||
mCachedView?.setBackgroundColor(Color.TRANSPARENT)
|
||||
super.onLoadError()
|
||||
}
|
||||
|
||||
override fun onDarkModeChanged() {
|
||||
super.onDarkModeChanged()
|
||||
mListRv?.setBackgroundColor(R.color.ui_surface.toColor(requireContext()))
|
||||
mListRv?.adapter?.run {
|
||||
mListRv?.recycledViewPool?.clear()
|
||||
notifyItemRangeChanged(0, itemCount)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,21 +0,0 @@
|
||||
package com.gh.gamecenter.category
|
||||
|
||||
import android.app.Application
|
||||
import com.gh.gamecenter.common.baselist.ListViewModel
|
||||
import com.gh.gamecenter.entity.CategoryEntity
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager
|
||||
import io.reactivex.Observable
|
||||
|
||||
class CategoryDirectoryListViewModel(application: Application) :
|
||||
ListViewModel<CategoryEntity, CategoryEntity>(application) {
|
||||
|
||||
var categoryId = ""
|
||||
|
||||
override fun mergeResultLiveData() {
|
||||
mResultLiveData.addSource(mListLiveData, mResultLiveData::postValue)
|
||||
}
|
||||
|
||||
override fun provideDataObservable(page: Int): Observable<MutableList<CategoryEntity>> {
|
||||
return RetrofitManager.getInstance().api.getCategories(categoryId, page)
|
||||
}
|
||||
}
|
||||
@ -1,53 +0,0 @@
|
||||
package com.gh.gamecenter.category
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import com.gh.base.DownloadToolbarActivity
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.constant.EntranceConsts
|
||||
import com.gh.gamecenter.common.utils.updateStatusBarColor
|
||||
import com.gh.gamecenter.entity.CategoryEntity
|
||||
|
||||
class CategoryListActivity : DownloadToolbarActivity() {
|
||||
|
||||
companion object {
|
||||
fun getIntent(context: Context, categoryTitle: String, category: CategoryEntity, initTitle: String): Intent {
|
||||
val bundle = Bundle()
|
||||
if (category.data!!.isEmpty() || category.data!![0].name != "全部") {
|
||||
val plainCategory = CategoryEntity(id = category.id, name = "全部")
|
||||
((category.data) as ArrayList).add(0, plainCategory)
|
||||
}
|
||||
bundle.putParcelable(EntranceConsts.KEY_DATA, category)
|
||||
bundle.putString(EntranceConsts.KEY_NAME, category.name)
|
||||
bundle.putString(EntranceConsts.KEY_CATEGORY_TITLE, categoryTitle)
|
||||
bundle.putString(EntranceConsts.KEY_CATEGORY_INIT_TITLE, initTitle)
|
||||
return getTargetIntent(
|
||||
context,
|
||||
CategoryListActivity::class.java,
|
||||
NewCategoryListFragment::class.java,
|
||||
bundle
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setToolbarMenu(R.menu.menu_download)
|
||||
updateStatusBarColor(R.color.ui_surface, R.color.ui_surface)
|
||||
}
|
||||
|
||||
override fun showDownloadMenu(): Boolean {
|
||||
return true
|
||||
}
|
||||
|
||||
override fun getActivityNameInChinese(): String {
|
||||
return "游戏分类详情"
|
||||
}
|
||||
|
||||
override fun onDarkModeChanged() {
|
||||
super.onDarkModeChanged()
|
||||
updateStatusBarColor(R.color.ui_surface, R.color.ui_surface)
|
||||
}
|
||||
}
|
||||
@ -1,51 +0,0 @@
|
||||
package com.gh.gamecenter.category
|
||||
|
||||
import android.content.Context
|
||||
import android.view.ViewGroup
|
||||
import com.gh.gamecenter.common.base.BaseRecyclerViewHolder
|
||||
import com.gh.gamecenter.common.utils.toBinding
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.utils.toColor
|
||||
import com.gh.gamecenter.common.utils.toDrawable
|
||||
import com.gh.gamecenter.databinding.ItemTagBinding
|
||||
import com.gh.gamecenter.entity.CategoryEntity
|
||||
import com.lightgame.adapter.BaseRecyclerAdapter
|
||||
|
||||
class NewCategoryHorizontalAdapter(
|
||||
context: Context,
|
||||
private val mViewModel: NewCategoryListViewModel,
|
||||
private val mCategoryList: List<CategoryEntity>,
|
||||
private val mSmoothScrollAction: (position: Int) -> Unit
|
||||
) : BaseRecyclerAdapter<TagsViewHolder>(context) {
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): TagsViewHolder {
|
||||
return TagsViewHolder(parent.toBinding())
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: TagsViewHolder, position: Int) {
|
||||
val categoryEntity = mCategoryList[position]
|
||||
|
||||
if (mViewModel.selectedCategory.name == categoryEntity.name) {
|
||||
holder.binding.tagTv.background = R.drawable.bg_tag_text.toDrawable()
|
||||
holder.binding.tagTv.setTextColor(R.color.text_white.toColor(mContext))
|
||||
} else {
|
||||
holder.binding.tagTv.background = null
|
||||
holder.binding.tagTv.setTextColor(R.color.text_757575.toColor(mContext))
|
||||
}
|
||||
|
||||
holder.binding.tagTv.text = categoryEntity.name
|
||||
holder.binding.tagTv.setOnClickListener {
|
||||
mViewModel.changeSelectedCategory(categoryEntity)
|
||||
notifyDataSetChanged()
|
||||
|
||||
mSmoothScrollAction.invoke(position)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int {
|
||||
return mCategoryList.size
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class TagsViewHolder(val binding: ItemTagBinding) : BaseRecyclerViewHolder<Any>(binding.root)
|
||||
@ -1,185 +0,0 @@
|
||||
package com.gh.gamecenter.category
|
||||
|
||||
import android.content.Context
|
||||
import android.util.SparseArray
|
||||
import android.view.ViewGroup
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.gh.common.exposure.IExposable
|
||||
import com.gh.common.util.DownloadItemUtils
|
||||
import com.gh.gamecenter.GameDetailActivity
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.adapter.viewholder.GameViewHolder
|
||||
import com.gh.gamecenter.common.baselist.ListAdapter
|
||||
import com.gh.gamecenter.common.constant.ItemViewType
|
||||
import com.gh.gamecenter.common.exposure.ExposureSource
|
||||
import com.gh.gamecenter.common.utils.dip2px
|
||||
import com.gh.gamecenter.common.utils.toBinding
|
||||
import com.gh.gamecenter.common.viewholder.FooterViewHolder
|
||||
import com.gh.gamecenter.core.utils.StringUtils
|
||||
import com.gh.gamecenter.eventbus.EBDownloadStatus
|
||||
import com.gh.gamecenter.feature.entity.GameEntity
|
||||
import com.gh.gamecenter.feature.exposure.ExposureEvent
|
||||
import com.gh.gamecenter.feature.exposure.ExposureType
|
||||
import com.gh.gamecenter.feature.game.GameItemViewHolder
|
||||
import com.lightgame.download.DownloadEntity
|
||||
|
||||
class NewCategoryListAdapter(
|
||||
context: Context,
|
||||
private val mViewModel: NewCategoryListViewModel,
|
||||
private val mEntrance: String?
|
||||
) : ListAdapter<GameEntity>(context), IExposable {
|
||||
|
||||
private val mExposureEventSparseArray: SparseArray<ExposureEvent> = SparseArray()
|
||||
|
||||
val positionAndPackageMap = HashMap<String, Int>()
|
||||
|
||||
override fun setListData(updateData: MutableList<GameEntity>?) {
|
||||
// 记录游戏位置
|
||||
if (updateData != null) {
|
||||
for (i in 0 until updateData.size) {
|
||||
val gameEntity = updateData[i]
|
||||
var packages = gameEntity.id
|
||||
for (apkEntity in gameEntity.getApk()) {
|
||||
packages += apkEntity.packageName
|
||||
}
|
||||
positionAndPackageMap[packages + i] = i
|
||||
}
|
||||
}
|
||||
super.setListData(updateData)
|
||||
}
|
||||
|
||||
fun clearPositionAndPackageMap() {
|
||||
positionAndPackageMap.clear()
|
||||
}
|
||||
|
||||
override fun areItemsTheSame(oldItem: GameEntity?, newItem: GameEntity?): Boolean {
|
||||
return oldItem?.id == newItem?.id
|
||||
}
|
||||
|
||||
override fun getItemViewType(position: Int): Int {
|
||||
if (position == itemCount - 1) {
|
||||
return ItemViewType.ITEM_FOOTER
|
||||
}
|
||||
return ItemViewType.GAME_NORMAL
|
||||
}
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
|
||||
return when (viewType) {
|
||||
ItemViewType.GAME_NORMAL -> {
|
||||
GameItemViewHolder(parent.toBinding())
|
||||
}
|
||||
else -> {
|
||||
FooterViewHolder(mLayoutInflater.inflate(R.layout.refresh_footerview, parent, false))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int {
|
||||
return if (mEntityList == null || mEntityList.isEmpty()) return 0 else mEntityList.size + 1
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
|
||||
if (holder is GameItemViewHolder) {
|
||||
val gameEntity = mEntityList[position]
|
||||
|
||||
holder.bindGameItem(gameEntity)
|
||||
holder.initServerType(gameEntity)
|
||||
|
||||
val padTop = if (position == 0) 16F.dip2px() else 8F.dip2px()
|
||||
holder.itemView.setPadding(16F.dip2px(), padTop, 16F.dip2px(), 8F.dip2px())
|
||||
|
||||
val sortType = if ("download:-1" == mViewModel.getSortType()) "最热" else "最新"
|
||||
val toolbarTitle = mViewModel.title
|
||||
val categoryTitle = mViewModel.categoryTitle
|
||||
val selectedCategoryName = mViewModel.selectedCategory.name ?: ""
|
||||
|
||||
val exposureSources = ArrayList<ExposureSource>()
|
||||
exposureSources.add(ExposureSource(categoryTitle, selectedCategoryName))
|
||||
exposureSources.add(ExposureSource("二级分类", "$selectedCategoryName+$sortType"))
|
||||
|
||||
val event = ExposureEvent.createEvent(gameEntity, exposureSources, null, ExposureType.EXPOSURE)
|
||||
mExposureEventSparseArray.put(position, event)
|
||||
|
||||
holder.itemView.setOnClickListener {
|
||||
GameDetailActivity.startGameDetailActivity(
|
||||
mContext,
|
||||
gameEntity,
|
||||
StringUtils.buildString(
|
||||
mEntrance,
|
||||
"+(",
|
||||
toolbarTitle,
|
||||
":列表[",
|
||||
selectedCategoryName,
|
||||
"=",
|
||||
sortType,
|
||||
"=",
|
||||
(position + 1).toString(),
|
||||
"])"
|
||||
),
|
||||
traceEvent = event
|
||||
)
|
||||
}
|
||||
DownloadItemUtils.setOnClickListener(
|
||||
mContext,
|
||||
holder.binding.downloadBtn,
|
||||
gameEntity,
|
||||
position,
|
||||
this,
|
||||
StringUtils.buildString(
|
||||
StringUtils.buildString(
|
||||
mEntrance,
|
||||
"+(",
|
||||
toolbarTitle,
|
||||
":列表[",
|
||||
selectedCategoryName,
|
||||
"=",
|
||||
sortType,
|
||||
"=",
|
||||
(position + 1).toString(),
|
||||
"])"
|
||||
)
|
||||
),
|
||||
location = StringUtils.buildString(selectedCategoryName, ":", gameEntity.name),
|
||||
traceEvent = event
|
||||
)
|
||||
|
||||
DownloadItemUtils.updateItem(mContext, gameEntity, GameViewHolder(holder.binding))
|
||||
} else if (holder is FooterViewHolder) {
|
||||
holder.initItemPadding()
|
||||
holder.initFooterViewHolder(mViewModel, mIsLoading, mIsNetworkError, mIsOver)
|
||||
}
|
||||
}
|
||||
|
||||
fun notifyItemByDownload(download: DownloadEntity) {
|
||||
for (key in positionAndPackageMap.keys) {
|
||||
if (key.contains(download.packageName) && key.contains(download.gameId)) {
|
||||
val position = positionAndPackageMap[key]
|
||||
if (position != null && mEntityList != null && position < mEntityList.size) {
|
||||
mEntityList[position].getEntryMap()[download.platform] = download
|
||||
notifyItemChanged(position)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun notifyItemAndRemoveDownload(status: EBDownloadStatus) {
|
||||
for (key in positionAndPackageMap.keys) {
|
||||
if (key.contains(status.packageName) && key.contains(status.gameId)) {
|
||||
val position = positionAndPackageMap[key]
|
||||
if (position != null && mEntityList != null && position < mEntityList.size) {
|
||||
mEntityList[position].getEntryMap().remove(status.platform)
|
||||
notifyItemChanged(position)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun getEventByPosition(pos: Int): ExposureEvent? {
|
||||
return mExposureEventSparseArray.get(pos)
|
||||
}
|
||||
|
||||
override fun getEventListByPosition(pos: Int): List<ExposureEvent>? {
|
||||
return null
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,198 +0,0 @@
|
||||
package com.gh.gamecenter.category
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import com.ethanhua.skeleton.Skeleton
|
||||
import com.gh.common.exposure.ExposureListener
|
||||
import com.gh.common.util.DialogUtils
|
||||
import com.gh.common.view.ConfigFilterView
|
||||
import com.gh.common.xapk.XapkInstaller
|
||||
import com.gh.common.xapk.XapkUnzipStatus
|
||||
import com.gh.download.DownloadManager
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.constant.Constants
|
||||
import com.gh.gamecenter.common.baselist.ListAdapter
|
||||
import com.gh.gamecenter.common.baselist.ListFragment
|
||||
import com.gh.gamecenter.common.constant.EntranceConsts
|
||||
import com.gh.gamecenter.common.utils.observeNonNull
|
||||
import com.gh.gamecenter.common.utils.toColor
|
||||
import com.gh.gamecenter.common.utils.tryCatchInRelease
|
||||
import com.gh.gamecenter.common.utils.viewModelProvider
|
||||
import com.gh.gamecenter.databinding.FragmentTagsBinding
|
||||
import com.gh.gamecenter.entity.CategoryEntity
|
||||
import com.gh.gamecenter.feature.entity.GameEntity
|
||||
import com.gh.gamecenter.entity.SubjectSettingEntity
|
||||
import com.gh.gamecenter.eventbus.EBDownloadStatus
|
||||
import com.gh.gamecenter.eventbus.EBPackage
|
||||
import com.lightgame.download.DataWatcher
|
||||
import com.lightgame.download.DownloadEntity
|
||||
import org.greenrobot.eventbus.Subscribe
|
||||
import org.greenrobot.eventbus.ThreadMode
|
||||
|
||||
class NewCategoryListFragment : ListFragment<GameEntity, NewCategoryListViewModel>() {
|
||||
|
||||
private var mPrimeCategory: CategoryEntity? = null
|
||||
private var mSubCategoryList = arrayListOf<CategoryEntity>()
|
||||
private val mBinding by lazy { FragmentTagsBinding.inflate(layoutInflater) }
|
||||
|
||||
private var mAdapter: NewCategoryListAdapter? = null
|
||||
private val mDataWatcher = object : DataWatcher() {
|
||||
override fun onDataChanged(downloadEntity: DownloadEntity) {
|
||||
mAdapter?.notifyItemByDownload(downloadEntity)
|
||||
|
||||
if (downloadEntity.meta[XapkInstaller.XAPK_UNZIP_STATUS] == XapkUnzipStatus.FAILURE.name) {
|
||||
showUnzipFailureDialog(downloadEntity)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDataInit(downloadEntity: DownloadEntity) {
|
||||
mAdapter?.notifyItemByDownload(downloadEntity)
|
||||
}
|
||||
}
|
||||
|
||||
private lateinit var mExposureListener: ExposureListener
|
||||
private lateinit var mViewModel: NewCategoryListViewModel
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
mViewModel = provideListViewModel()
|
||||
|
||||
mViewModel.title = arguments?.getString(EntranceConsts.KEY_NAME) ?: ""
|
||||
mViewModel.categoryTitle = arguments?.getString(EntranceConsts.KEY_CATEGORY_TITLE) ?: ""
|
||||
mEntrance = arguments?.getString(EntranceConsts.KEY_ENTRANCE) ?: Constants.ENTRANCE_UNKNOWN
|
||||
mPrimeCategory = arguments?.getParcelable(EntranceConsts.KEY_DATA)
|
||||
mSubCategoryList = mPrimeCategory?.data as? ArrayList<CategoryEntity> ?: arrayListOf()
|
||||
|
||||
val initSelectedCategory = arguments?.getString(EntranceConsts.KEY_CATEGORY_INIT_TITLE)
|
||||
|
||||
mViewModel.selectedCategory =
|
||||
mSubCategoryList.find { categoryEntity -> categoryEntity.name == initSelectedCategory }
|
||||
?: CategoryEntity()
|
||||
|
||||
super.onCreate(savedInstanceState)
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
setNavigationTitle(mViewModel.title)
|
||||
|
||||
mViewModel.refresh.observeNonNull(this) { onRefresh() }
|
||||
|
||||
mBinding.configContainer.visibility = View.VISIBLE
|
||||
mBinding.configContainer.updateAllTextView(mViewModel.sortType)
|
||||
mBinding.configContainer.setOnConfigSetupListener(object : ConfigFilterView.OnConfigFilterSetupListener {
|
||||
override fun onShowSortSize() {}
|
||||
|
||||
override fun onSetupSortSize(sortSize: SubjectSettingEntity.Size) {
|
||||
mViewModel.updateSortConfig(sortSize = sortSize)
|
||||
}
|
||||
|
||||
override fun onSetupSortType(sortType: ConfigFilterView.SortType) {
|
||||
mViewModel.updateSortConfig(sortType = sortType)
|
||||
}
|
||||
})
|
||||
|
||||
mExposureListener = ExposureListener(this, mAdapter!!)
|
||||
mListRv.addOnScrollListener(mExposureListener)
|
||||
|
||||
updateCategoriesView(mSubCategoryList)
|
||||
|
||||
mSkeletonScreen =
|
||||
Skeleton.bind(mBinding.listSkeleton).shimmer(false).load(R.layout.fragment_subject_skeleton).show()
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
DownloadManager.getInstance().addObserver(mDataWatcher)
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
DownloadManager.getInstance().removeObserver(mDataWatcher)
|
||||
}
|
||||
|
||||
override fun getItemDecoration() = null
|
||||
|
||||
override fun getLayoutId() = 0
|
||||
|
||||
override fun getInflatedLayout() = mBinding.root
|
||||
|
||||
override fun provideListViewModel(): NewCategoryListViewModel {
|
||||
return viewModelProvider()
|
||||
}
|
||||
|
||||
override fun provideListAdapter(): ListAdapter<GameEntity> {
|
||||
return mAdapter
|
||||
?: NewCategoryListAdapter(requireContext(), mViewModel, mEntrance).apply { mAdapter = this }
|
||||
}
|
||||
|
||||
private fun updateCategoriesView(categoryList: ArrayList<CategoryEntity>) {
|
||||
mBinding.tagsRecyclerView.layoutManager =
|
||||
LinearLayoutManager(requireContext(), LinearLayoutManager.HORIZONTAL, false)
|
||||
mBinding.tagsRecyclerView.adapter = NewCategoryHorizontalAdapter(requireContext(), mViewModel, categoryList) {
|
||||
mBinding.tagsRecyclerView.smoothScrollToPosition(it)
|
||||
}
|
||||
|
||||
// 调整选中标签位置
|
||||
for (index in 0 until categoryList.size) {
|
||||
if (categoryList[index].name == mViewModel.selectedCategory.name) {
|
||||
mBinding.tagsRecyclerView.postDelayed({
|
||||
tryCatchInRelease { mBinding.tagsRecyclerView.smoothScrollToPosition(index) }
|
||||
}, 200)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onRefresh() {
|
||||
mAdapter?.clearPositionAndPackageMap()
|
||||
|
||||
super.onRefresh()
|
||||
}
|
||||
|
||||
// 下载被删除事件
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
fun onEventMainThread(status: EBDownloadStatus) {
|
||||
if ("delete" == status.status) {
|
||||
mAdapter?.notifyItemAndRemoveDownload(status)
|
||||
}
|
||||
}
|
||||
|
||||
// 安装/卸载 事件
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
fun onEventMainThread(busFour: EBPackage) {
|
||||
if (busFour.isInstalledOrUninstalled()) {
|
||||
mAdapter?.notifyDataSetChanged()
|
||||
}
|
||||
}
|
||||
|
||||
fun showUnzipFailureDialog(downloadEntity: DownloadEntity) {
|
||||
val data = mAdapter?.positionAndPackageMap ?: return
|
||||
for (gameAndPosition in data) {
|
||||
if (gameAndPosition.key.contains(downloadEntity.packageName)) {
|
||||
val targetView = mLayoutManager.findViewByPosition(gameAndPosition.value)
|
||||
if (targetView != null) {
|
||||
DialogUtils.showUnzipFailureDialog(requireContext(), downloadEntity)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDarkModeChanged() {
|
||||
super.onDarkModeChanged()
|
||||
mBinding.run {
|
||||
divider.setBackgroundColor(R.color.ui_background.toColor(requireContext()))
|
||||
tagsRecyclerView.setBackgroundColor(R.color.ui_surface.toColor(requireContext()))
|
||||
tagsRecyclerView.adapter?.run {
|
||||
notifyItemRangeChanged(0, itemCount)
|
||||
}
|
||||
configContainer.run {
|
||||
container.setBackgroundColor(R.color.ui_surface.toColor(requireContext()))
|
||||
updateAllTextView(mViewModel.sortType)
|
||||
updatePopupWindow()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,81 +0,0 @@
|
||||
package com.gh.gamecenter.category
|
||||
|
||||
import android.app.Application
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import com.gh.common.exposure.ExposureUtils
|
||||
import com.gh.gamecenter.core.utils.UrlFilterUtils
|
||||
import com.gh.common.view.ConfigFilterView
|
||||
import com.gh.gamecenter.common.baselist.ListViewModel
|
||||
import com.gh.gamecenter.entity.CategoryEntity
|
||||
import com.gh.gamecenter.feature.entity.GameEntity
|
||||
import com.gh.gamecenter.entity.SubjectSettingEntity
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager
|
||||
import io.reactivex.Observable
|
||||
import io.reactivex.Single
|
||||
|
||||
class NewCategoryListViewModel(application: Application) : ListViewModel<GameEntity, GameEntity>(application) {
|
||||
|
||||
var title = "" // 显示在 Toolbar 的标题
|
||||
var categoryTitle = "" // 跳转进来的分类的标题
|
||||
|
||||
val refresh = MutableLiveData<Boolean>()
|
||||
|
||||
var selectedCategory = CategoryEntity()
|
||||
|
||||
var sortType = ConfigFilterView.SortType.RECOMMENDED
|
||||
private var mSortSize = SubjectSettingEntity.Size()
|
||||
|
||||
override fun provideDataObservable(page: Int): Observable<List<GameEntity>>? {
|
||||
return null
|
||||
}
|
||||
|
||||
override fun provideDataSingle(page: Int): Single<List<GameEntity>> {
|
||||
return RetrofitManager.getInstance()
|
||||
.api
|
||||
.getGamesInCategory(selectedCategory.id, getSortType(), getSortSize(), page)
|
||||
}
|
||||
|
||||
override fun mergeResultLiveData() {
|
||||
mResultLiveData.addSource(mListLiveData) {
|
||||
ExposureUtils.updateExposureInfo(it)
|
||||
mResultLiveData.postValue(it)
|
||||
}
|
||||
}
|
||||
|
||||
fun changeSelectedCategory(category: CategoryEntity) {
|
||||
if (selectedCategory != category) {
|
||||
selectedCategory = category
|
||||
|
||||
refresh.postValue(true)
|
||||
}
|
||||
}
|
||||
|
||||
fun updateSortConfig(
|
||||
sortSize: SubjectSettingEntity.Size? = null,
|
||||
sortType: ConfigFilterView.SortType? = null
|
||||
) {
|
||||
if (sortSize != null && sortSize != mSortSize) {
|
||||
mSortSize = sortSize
|
||||
refresh.postValue(true)
|
||||
} else if (sortType != null && sortType != this.sortType) {
|
||||
this.sortType = sortType
|
||||
refresh.postValue(true)
|
||||
}
|
||||
}
|
||||
|
||||
private fun getSortSize(): String? {
|
||||
return UrlFilterUtils.getFilterQuery(
|
||||
"min_size", mSortSize.min.toString(),
|
||||
"max_size", mSortSize.max.toString()
|
||||
)
|
||||
}
|
||||
|
||||
fun getSortType(): String? {
|
||||
return if (sortType == ConfigFilterView.SortType.RECOMMENDED) {
|
||||
"download:-1"
|
||||
} else {
|
||||
"publish:-1"
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -160,7 +160,7 @@ class DownloadFragment : BaseFragment_TabLayout() {
|
||||
val ownerAd = downloadManagerAd?.ownerAd
|
||||
val showOnFailed = downloadManagerAd?.displayRule?.onFailedAction == "show"
|
||||
if ((showThirdPartyAd && thirdPartyAd != null) || (!showThirdPartyAd && thirdPartyAd != null && ownerAd == null)) {
|
||||
initThirdPartyAd(thirdPartyAd) { isSuccess ->
|
||||
initThirdPartyAd(downloadManagerAd, thirdPartyAd) { isSuccess ->
|
||||
mBinding.maskView.goneIf(!isSuccess)
|
||||
if (!isSuccess && ownerAd != null && showOnFailed) {
|
||||
mSlideInterval = ownerAd.adSource?.sliderInterval ?: -1
|
||||
@ -182,12 +182,34 @@ class DownloadFragment : BaseFragment_TabLayout() {
|
||||
}
|
||||
}
|
||||
|
||||
private fun initThirdPartyAd(thirdPartyAd: AdConfig.ThirdPartyAd, callback: (isSuccess: Boolean) -> Unit) {
|
||||
private fun initThirdPartyAd(adConfig: AdConfig?, thirdPartyAd: AdConfig.ThirdPartyAd, callback: (isSuccess: Boolean) -> Unit) {
|
||||
val onAdShowAction = {
|
||||
SensorsBridge.trackEvent("ThirdPartyAdShow",
|
||||
"ad_source", thirdPartyAd.sourceName,
|
||||
"ad_id", thirdPartyAd.slotId,
|
||||
"ad_format", adConfig?.typeChinese ?: "",
|
||||
"ad_placement", "下载管理",
|
||||
"ad_space_id", adConfig?.id ?: "",
|
||||
"ad_space_name", adConfig?.name ?: ""
|
||||
)
|
||||
}
|
||||
val onAdClickAction = {
|
||||
SensorsBridge.trackEvent("ThirdPartyAdClick",
|
||||
"ad_source", thirdPartyAd.sourceName,
|
||||
"ad_id", thirdPartyAd.slotId,
|
||||
"ad_format", adConfig?.typeChinese ?: "",
|
||||
"ad_placement", "下载管理",
|
||||
"ad_space_id", adConfig?.id ?: "",
|
||||
"ad_space_name", adConfig?.name ?: ""
|
||||
)
|
||||
}
|
||||
AdDelegateHelper.requestThirdPartyBannerAd(
|
||||
this,
|
||||
mBinding.adContainer,
|
||||
thirdPartyAd,
|
||||
DisplayUtils.getScreenWidthInDp(requireActivity()),
|
||||
onAdShowAction,
|
||||
onAdClickAction,
|
||||
callback
|
||||
)
|
||||
}
|
||||
@ -226,7 +248,7 @@ class DownloadFragment : BaseFragment_TabLayout() {
|
||||
if (it.isNullOrEmpty() && adConfig.displayRule.adSource == AdDelegateHelper.AD_TYPE_OWNER &&
|
||||
adConfig.displayRule.onFailedAction == "show" && adConfig.thirdPartyAd != null) {
|
||||
// 自有广告游戏为空时,显示第三方广告
|
||||
initThirdPartyAd(adConfig.thirdPartyAd) { isSuccess ->
|
||||
initThirdPartyAd(adConfig, adConfig.thirdPartyAd) { isSuccess ->
|
||||
mBinding.maskView.goneIf(!isSuccess)
|
||||
if (isSuccess) {
|
||||
SPUtils.setLong(Constants.SP_LAST_DOWNLOAD_MANAGER_AD_SHOW_TIME, System.currentTimeMillis())
|
||||
|
||||
@ -6,7 +6,7 @@ class AdConfig(
|
||||
@SerializedName("_id")
|
||||
val id: String = "",
|
||||
val name: String,
|
||||
val location: String, // 广告插入位置。光环启动:halo_launch 下载管理:download_manager 游戏搜索:game_search 助手启动:helper_launch
|
||||
val location: String, // 广告插入位置。光环启动:halo_launch 下载管理:download_manager 游戏搜索:game_search 畅玩启动:helper_launch
|
||||
val type: String, // 广告位类型。开屏广告:launch 信息流广告:native banner 广告:banner 插屏广告:interstitial
|
||||
val position: Int, // 定位,不存在的时候返回:-1
|
||||
@SerializedName("display_rules")
|
||||
@ -18,12 +18,19 @@ class AdConfig(
|
||||
@SerializedName("owner_ads")
|
||||
val ownerAd: OwnerAdEntity? = null,
|
||||
) {
|
||||
companion object {
|
||||
const val TYPE_LAUNCH = "launch"
|
||||
const val TYPE_NATIVE = "native"
|
||||
const val TYPE_BANNER = "banner"
|
||||
const val TYPE_INTERSTITIAL = "interstitial"
|
||||
}
|
||||
|
||||
val typeChinese
|
||||
get() = when (type) {
|
||||
"launch" -> "开屏"
|
||||
"native" -> "信息流"
|
||||
"banner" -> "banner"
|
||||
"interstitial" -> "插屏"
|
||||
TYPE_LAUNCH -> "开屏"
|
||||
TYPE_NATIVE -> "信息流"
|
||||
TYPE_BANNER -> "banner"
|
||||
TYPE_INTERSTITIAL -> "插屏"
|
||||
else -> ""
|
||||
}
|
||||
|
||||
|
||||
@ -26,7 +26,8 @@ data class BottomTab(
|
||||
@SerializedName("is_default_page")
|
||||
var default: Boolean = false, // 是否为默认显示页
|
||||
var guide: Guide? = null, // 引导文案
|
||||
var isTransparentStyle: Boolean = false // 本地字段,透明底部Tab
|
||||
var diverter: DiverterEntity? = null, // 分流器
|
||||
var isTransparentStyle: Boolean = false, // 本地字段,透明底部Tab
|
||||
) : Parcelable {
|
||||
@Parcelize
|
||||
data class SearchStyle(
|
||||
|
||||
@ -6,40 +6,6 @@ import com.gh.gamecenter.feature.entity.GameEntity
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import kotlinx.parcelize.Parcelize
|
||||
|
||||
@Parcelize
|
||||
data class CatalogEntity(
|
||||
@SerializedName("_id")
|
||||
var id: String = "",
|
||||
var name: String = "",
|
||||
var switch: CatalogSwitch = CatalogSwitch(),
|
||||
@SerializedName("has_special")
|
||||
var hasSpecial: Boolean = false,
|
||||
@SerializedName("sub_catalogs")
|
||||
var subCatalog: List<SubCatalogEntity> = emptyList()
|
||||
) : Parcelable {
|
||||
|
||||
@Parcelize
|
||||
data class SubCatalogEntity(
|
||||
@SerializedName("_id")
|
||||
var id: String = "",
|
||||
var name: String = "",
|
||||
var icon: String = "",
|
||||
var type: String = "",
|
||||
var link: LinkEntity = LinkEntity(),
|
||||
var recommended: Boolean = false
|
||||
) : Parcelable
|
||||
|
||||
@Parcelize
|
||||
data class CatalogSwitch(
|
||||
@SerializedName("sort_hot")
|
||||
var hotSort: String = "",
|
||||
@SerializedName("sort_new")
|
||||
var newSort: String = "",
|
||||
@SerializedName("sort_star")
|
||||
var starSort: String = ""
|
||||
) : Parcelable
|
||||
}
|
||||
|
||||
|
||||
@Parcelize
|
||||
class SpecialCatalogEntity(
|
||||
|
||||
31
app/src/main/java/com/gh/gamecenter/entity/DiverterData.kt
Normal file
31
app/src/main/java/com/gh/gamecenter/entity/DiverterData.kt
Normal file
@ -0,0 +1,31 @@
|
||||
package com.gh.gamecenter.entity
|
||||
|
||||
import android.os.Parcelable
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import kotlinx.parcelize.Parcelize
|
||||
|
||||
@Parcelize
|
||||
class DiverterData(
|
||||
@SerializedName("diverter_id")
|
||||
val diverterId: String = "",
|
||||
@SerializedName("diverter_name")
|
||||
val diverterName: String = "",
|
||||
@SerializedName("branch_id")
|
||||
val branchId: String = "",
|
||||
@SerializedName("branch_name")
|
||||
val branchName: String = "",
|
||||
@SerializedName("branch_type")
|
||||
val branchType: String = "",
|
||||
@SerializedName("inprocess_time")
|
||||
val inprocessTime: Int = 0,
|
||||
@SerializedName("bypass_visit_time")
|
||||
val bypassVisitTime: Int = 0,
|
||||
@SerializedName("link_id")
|
||||
val linkId: String = "",
|
||||
@SerializedName("link_type")
|
||||
val linkType: String = "",
|
||||
@SerializedName("link_text")
|
||||
val linkText: String = "",
|
||||
@SerializedName("bypass_status")
|
||||
val bypassStatus: Int = 0,
|
||||
): Parcelable
|
||||
15
app/src/main/java/com/gh/gamecenter/entity/DiverterEntity.kt
Normal file
15
app/src/main/java/com/gh/gamecenter/entity/DiverterEntity.kt
Normal file
@ -0,0 +1,15 @@
|
||||
package com.gh.gamecenter.entity
|
||||
|
||||
import android.os.Parcelable
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import kotlinx.parcelize.Parcelize
|
||||
|
||||
@Parcelize
|
||||
class DiverterEntity(
|
||||
@SerializedName("module_id")
|
||||
val moduleId: String = "",
|
||||
@SerializedName("module_index")
|
||||
val moduleIndex: Int = -1,
|
||||
@SerializedName("diverter_data")
|
||||
val diverterData: DiverterData = DiverterData()
|
||||
): Parcelable
|
||||
@ -73,8 +73,6 @@ data class SubjectRecommendEntity(
|
||||
"column" -> "专题"
|
||||
"column_collection" -> "专题合集"
|
||||
"block" -> "版块"
|
||||
"category" -> "分类"
|
||||
"catalog" -> "新分类"
|
||||
"category_v2" -> "新分类2.0"
|
||||
"column_test" -> "开测表"
|
||||
"server" -> "开服表"
|
||||
|
||||
@ -23,6 +23,9 @@ import com.airbnb.lottie.SimpleColorFilter
|
||||
import com.airbnb.lottie.model.KeyPath
|
||||
import com.airbnb.lottie.value.LottieValueCallback
|
||||
import com.gh.common.browse.BrowseTimer
|
||||
import com.gh.common.iinterface.ISuperiorChain
|
||||
import com.gh.common.prioritychain.CommunityHomeGuideHandler
|
||||
import com.gh.common.prioritychain.PriorityChain
|
||||
import com.gh.common.util.DirectUtils
|
||||
import com.gh.common.util.NewFlatLogUtils
|
||||
import com.gh.common.util.NewLogUtils
|
||||
@ -42,7 +45,6 @@ import com.gh.gamecenter.core.utils.MtaHelper
|
||||
import com.gh.gamecenter.core.utils.SPUtils
|
||||
import com.gh.gamecenter.core.utils.TimeUtils
|
||||
import com.gh.gamecenter.databinding.FragmentCommunityHomeBinding
|
||||
import com.gh.gamecenter.databinding.LayoutCommunityHomeVideoGuideBinding
|
||||
import com.gh.gamecenter.databinding.TabItemCommunityBinding
|
||||
import com.gh.gamecenter.eventbus.EBSkip
|
||||
import com.gh.gamecenter.eventbus.EBTypeChange
|
||||
@ -81,6 +83,8 @@ class CommunityHomeFragment : LazyFragment() {
|
||||
private var mNavigationBitmap: Bitmap? = null
|
||||
private var mShowVideo = true
|
||||
private var mBottomTabId = ""
|
||||
private val mPriorityChain by lazy { PriorityChain() }
|
||||
private var mSuperiorChain: ISuperiorChain? = null
|
||||
|
||||
private val browseTimer = BrowseTimer()
|
||||
.withResult {
|
||||
@ -156,6 +160,12 @@ class CommunityHomeFragment : LazyFragment() {
|
||||
})
|
||||
}
|
||||
|
||||
private fun addHomeVideoGuideHandler() {
|
||||
val decorView = activity?.window?.decorView as? FrameLayout
|
||||
val communityHomeGuideHandler = CommunityHomeGuideHandler(21, requireContext(), decorView, mBinding?.videoLottie)
|
||||
mPriorityChain.addHandler(communityHomeGuideHandler)
|
||||
}
|
||||
|
||||
override fun initRealView() {
|
||||
super.initRealView()
|
||||
|
||||
@ -166,24 +176,7 @@ class CommunityHomeFragment : LazyFragment() {
|
||||
mMainWrapperViewModel?.bottomTabListLiveData?.observe(this) { tabList ->
|
||||
mBinding?.videoAndSearchContainer?.goneIf(!mShowVideo) {
|
||||
val decorView = requireActivity().window.decorView as? FrameLayout
|
||||
|
||||
if (SPUtils.getBoolean(Constants.SP_SHOW_COMMUNITY_HOME_VIDEO_GUIDE, true)) {
|
||||
val guideLayoutBinding = LayoutCommunityHomeVideoGuideBinding.inflate(
|
||||
LayoutInflater.from(requireContext()),
|
||||
decorView,
|
||||
true
|
||||
)
|
||||
guideLayoutBinding.root.setOnClickListener { view ->
|
||||
decorView?.removeView(view)
|
||||
SPUtils.setBoolean(Constants.SP_SHOW_COMMUNITY_HOME_VIDEO_GUIDE, false)
|
||||
|
||||
mBinding?.videoLottie?.playAnimation()
|
||||
SPUtils.setLong(
|
||||
Constants.SP_COMMUNITY_HOME_VIDEO_LOTTIE_LAST_PLAY_TIME,
|
||||
System.currentTimeMillis()
|
||||
)
|
||||
}
|
||||
}
|
||||
addHomeVideoGuideHandler()
|
||||
|
||||
// 每日首次进入社区tab视频lottie播放3次
|
||||
val lastPlayTime = SPUtils.getLong(Constants.SP_COMMUNITY_HOME_VIDEO_LOTTIE_LAST_PLAY_TIME, 0L) / 1000
|
||||
@ -285,6 +278,14 @@ class CommunityHomeFragment : LazyFragment() {
|
||||
DisplayUtils.transparentStatusBar(requireActivity())
|
||||
DisplayUtils.setLightStatusBar(requireActivity(), !mIsDarkModeOn)
|
||||
NewLogUtils.logCommunityHomeEvent("view_community")
|
||||
|
||||
mSuperiorChain?.registerInferiorChain(mPriorityChain)
|
||||
}
|
||||
|
||||
override fun onFragmentPause() {
|
||||
super.onFragmentPause()
|
||||
|
||||
mSuperiorChain?.unregisterInferiorChain(mPriorityChain)
|
||||
}
|
||||
|
||||
fun setCurrentItem(index: Int) {
|
||||
@ -836,6 +837,11 @@ class CommunityHomeFragment : LazyFragment() {
|
||||
|
||||
fun getTopBgView() = mBinding?.topBg
|
||||
|
||||
fun setSuperiorChain(superiorChain: ISuperiorChain?): CommunityHomeFragment {
|
||||
this.mSuperiorChain = superiorChain
|
||||
return this
|
||||
}
|
||||
|
||||
companion object {
|
||||
var TAB_SELECTED_COLOR: Int = R.color.text_primary
|
||||
var TAB_DEFAULT_COLOR: Int = R.color.community_forum_more
|
||||
|
||||
@ -129,39 +129,40 @@ class ForumOrUserSearchActivity : SearchActivity() {
|
||||
}
|
||||
|
||||
override fun updateDisplayType(type: DisplayType) {
|
||||
val transaction = supportFragmentManager.beginTransaction()
|
||||
when (type) {
|
||||
DisplayType.DEFAULT -> {
|
||||
val fragment = supportFragmentManager.findFragmentByTag(SearchDefaultFragment::class.java.name)
|
||||
?: ForumOrUserSearchDefaultFragment()
|
||||
fragment.arguments = intent.extras
|
||||
transaction.replace(R.id.search_result, fragment, SearchDefaultFragment::class.java.name)
|
||||
val key = searchEt.text.toString().trim { it <= ' ' }
|
||||
if (key.isNotEmpty()) {
|
||||
val stayTime = (System.currentTimeMillis() - startPageTime) / 1000
|
||||
if (mEntrance != ForumDetailFragment.ENTRANCE) {
|
||||
NewFlatLogUtils.logViewSearchList(stayTime, key)
|
||||
} else {
|
||||
NewFlatLogUtils.logViewBbsSearchList(stayTime, key, mBbsId)
|
||||
val transaction = when (type) {
|
||||
DisplayType.DEFAULT -> showFragment(
|
||||
SearchDefaultFragment::class.java.name,
|
||||
onFragmentCreate = { ForumOrUserSearchDefaultFragment() }
|
||||
) { fragment ->
|
||||
fragment.arguments = intent.extras
|
||||
}.apply {
|
||||
val key = searchEt.text.toString().trim { it <= ' ' }
|
||||
if (key.isNotEmpty()) {
|
||||
val stayTime = (System.currentTimeMillis() - startPageTime) / 1000
|
||||
if (mEntrance != ForumDetailFragment.ENTRANCE) {
|
||||
NewFlatLogUtils.logViewSearchList(stayTime, key)
|
||||
} else {
|
||||
NewFlatLogUtils.logViewBbsSearchList(stayTime, key, mBbsId)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
else -> {
|
||||
if (mEntrance != ForumDetailFragment.ENTRANCE) {
|
||||
val fragment =
|
||||
supportFragmentManager.findFragmentByTag(ForumOrUserSearchFragment::class.java.name) as? ForumOrUserSearchFragment
|
||||
?: ForumOrUserSearchFragment()
|
||||
fragment.setSearchKeyAndType(mSearchKey ?: "", mSearchType.value)
|
||||
transaction.replace(R.id.search_result, fragment, ForumOrUserSearchFragment::class.java.name)
|
||||
else -> if (mEntrance != ForumDetailFragment.ENTRANCE) {
|
||||
showFragment(
|
||||
ForumOrUserSearchFragment::class.java.name,
|
||||
{ ForumOrUserSearchFragment() }
|
||||
) { fragment ->
|
||||
fragment.setSearchKeyAndType(mSearchKey ?: "", mSearchType.value)
|
||||
}
|
||||
} else {
|
||||
val fragment =
|
||||
supportFragmentManager.findFragmentByTag(ForumContentSearchListFragment::class.java.name) as? ForumContentSearchListFragment
|
||||
?: ForumContentSearchListFragment()
|
||||
fragment.setSearchKeyAndType(mSearchKey ?: "", mSearchType.value)
|
||||
fragment.arguments = intent.extras
|
||||
transaction.replace(R.id.search_result, fragment, ForumContentSearchListFragment::class.java.name)
|
||||
}
|
||||
showFragment(
|
||||
ForumOrUserSearchFragment::class.java.name,
|
||||
{ ForumContentSearchListFragment() }
|
||||
) { fragment ->
|
||||
fragment.setSearchKeyAndType(mSearchKey ?: "", mSearchType.value)
|
||||
fragment.arguments = intent.extras
|
||||
}
|
||||
}.apply {
|
||||
startPageTime = System.currentTimeMillis()
|
||||
}
|
||||
}
|
||||
|
||||
@ -42,14 +42,14 @@ class ForumOrUserSearchDefaultFragment : SearchDefaultFragment() {
|
||||
|
||||
override fun initView() {
|
||||
mBinding = FragmentSearchDefaultBinding.bind(mCachedView)
|
||||
mBinding.hotTagHeadContainer.root.visibility = View.GONE
|
||||
mBinding.hotTagFlexContainer.visibility = View.GONE
|
||||
mBinding.searchDiscoveryTagHeadContainer.root.visibility = View.GONE
|
||||
mBinding.searchDiscoveryTagFlexContainer.visibility = View.GONE
|
||||
if (mEntrance == "论坛首页" || mEntrance == "搜索栏") {
|
||||
mBinding.hotHeadContainer.headTitle.text = "热门论坛"
|
||||
mBinding.searchDiscoveryHeadContainer.headTitle.text = "热门论坛"
|
||||
mViewModel.getForumSearchHotContent()
|
||||
} else {
|
||||
mBinding.hotHeadContainer.root.visibility = View.GONE
|
||||
mBinding.hotList.visibility = View.GONE
|
||||
mBinding.searchDiscoveryHeadContainer.root.visibility = View.GONE
|
||||
mBinding.searchDiscoveryList.visibility = View.GONE
|
||||
}
|
||||
val params = mBinding.historyHeadContainer.root.layoutParams as ConstraintLayout.LayoutParams
|
||||
params.topMargin = 0.5f.dip2px()
|
||||
|
||||
@ -11,8 +11,6 @@ import androidx.fragment.app.Fragment
|
||||
import androidx.viewpager.widget.ViewPager
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.amway.AmwayFragment
|
||||
import com.gh.gamecenter.catalog.CatalogFragment
|
||||
import com.gh.gamecenter.category.CategoryDirectoryFragment
|
||||
import com.gh.gamecenter.category2.CategoryV2Fragment
|
||||
import com.gh.gamecenter.common.base.adapter.FragmentAdapter
|
||||
import com.gh.gamecenter.common.constant.EntranceConsts
|
||||
@ -159,16 +157,6 @@ abstract class HomeTabWrapperFragment : SearchToolWrapperFragment() {
|
||||
putString(GameServersTestFragment.TEST_COLUMN_ID, tabEntity.link)
|
||||
})
|
||||
|
||||
"category" -> CategoryDirectoryFragment().with(Bundle().apply {
|
||||
putString(EntranceConsts.KEY_CATEGORY_ID, tabEntity.link)
|
||||
putString(EntranceConsts.KEY_CATEGORY_TITLE, tabEntity.text)
|
||||
})
|
||||
|
||||
"catalog" -> CatalogFragment().with(Bundle().apply {
|
||||
putString(EntranceConsts.KEY_CATALOG_ID, tabEntity.link)
|
||||
putString(EntranceConsts.KEY_CATALOG_TITLE, tabEntity.text)
|
||||
})
|
||||
|
||||
"category_v2" -> CategoryV2Fragment().with(Bundle().apply {
|
||||
putString(EntranceConsts.KEY_CATEGORY_ID, tabEntity.link)
|
||||
putString(EntranceConsts.KEY_CATEGORY_TITLE, tabEntity.text)
|
||||
|
||||
@ -23,7 +23,7 @@ class ReloadFragment: BaseLazyFragment() {
|
||||
super.onCreate(savedInstanceState)
|
||||
mBinding.reuseLoading.root.visibility = View.VISIBLE
|
||||
mBinding.reuseNoConnection.connectionReloadTv.setOnClickListener {
|
||||
MainWrapperRepository.getInstance().getDataUnion()
|
||||
MainWrapperRepository.getInstance().init()
|
||||
mBinding.reuseNoConnection.root.visibility = View.GONE
|
||||
mBinding.reuseLoading.root.visibility = View.VISIBLE
|
||||
}
|
||||
|
||||
@ -26,7 +26,6 @@ import com.gh.gamecenter.adapter.viewholder.GameHeadViewHolder
|
||||
import com.gh.gamecenter.adapter.viewholder.GameImageViewHolder
|
||||
import com.gh.gamecenter.adapter.viewholder.GameViewHolder
|
||||
import com.gh.gamecenter.adapter.viewholder.GameViewPagerViewHolder
|
||||
import com.gh.gamecenter.category.CategoryDirectoryActivity
|
||||
import com.gh.gamecenter.common.baselist.LoadStatus
|
||||
import com.gh.gamecenter.common.callback.OnViewClickListener
|
||||
import com.gh.gamecenter.common.constant.EntranceConsts
|
||||
@ -980,14 +979,6 @@ class GameFragmentAdapter(
|
||||
)
|
||||
)
|
||||
|
||||
"category" -> mContext.startActivity(
|
||||
CategoryDirectoryActivity.getIntent(
|
||||
mContext,
|
||||
entity.link!!,
|
||||
entity.text!!
|
||||
)
|
||||
)
|
||||
|
||||
"column" -> {
|
||||
SubjectActivity.startSubjectActivity(
|
||||
mContext,
|
||||
|
||||
@ -2,8 +2,8 @@ package com.gh.gamecenter.game.columncollection.detail
|
||||
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import com.gh.gamecenter.common.base.activity.ToolBarActivity
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.base.activity.ToolBarActivity
|
||||
import com.gh.gamecenter.common.constant.EntranceConsts
|
||||
import com.gh.gamecenter.common.utils.updateStatusBarColor
|
||||
|
||||
@ -34,8 +34,8 @@ class ColumnCollectionDetailActivity : ToolBarActivity() {
|
||||
}
|
||||
|
||||
override fun getBusinessId(): Pair<String, String> {
|
||||
val fragment = targetFragment as ColumnCollectionDetailFragment
|
||||
return if (fragment.arguments != null) {
|
||||
val fragment = targetFragment as? ColumnCollectionDetailFragment?
|
||||
return if (fragment?.arguments != null) {
|
||||
Pair(fragment.requireArguments().getString(EntranceConsts.KEY_COLLECTION_ID) ?: "", "")
|
||||
} else {
|
||||
super.getBusinessId()
|
||||
|
||||
@ -36,8 +36,8 @@ class CommonCollectionDetailActivity : ToolBarActivity() {
|
||||
}
|
||||
|
||||
override fun getBusinessId(): Pair<String, String> {
|
||||
val fragment = targetFragment as CommonCollectionDetailFragment
|
||||
return if (fragment.arguments != null) {
|
||||
val fragment = targetFragment as? CommonCollectionDetailFragment?
|
||||
return if (fragment?.arguments != null) {
|
||||
Pair(
|
||||
fragment.requireArguments().getString(EntranceConsts.KEY_COLLECTION_ID) ?: "",
|
||||
fragment.requireArguments().getString(EntranceConsts.KEY_BLOCK_ID) ?: ""
|
||||
|
||||
@ -36,8 +36,8 @@ class CustomCommonCollectionDetailActivity : ToolBarActivity() {
|
||||
}
|
||||
|
||||
override fun getBusinessId(): Pair<String, String> {
|
||||
val fragment = targetFragment as CustomCommonCollectionDetailFragment
|
||||
return if (fragment.arguments != null) {
|
||||
val fragment = targetFragment as? CustomCommonCollectionDetailFragment?
|
||||
return if (fragment?.arguments != null) {
|
||||
Pair(
|
||||
fragment.requireArguments().getString(EntranceConsts.KEY_COLLECTION_ID) ?: "",
|
||||
fragment.requireArguments().getString(EntranceConsts.KEY_BLOCK_ID) ?: ""
|
||||
|
||||
@ -3,7 +3,6 @@ package com.gh.gamecenter.game.upload
|
||||
import android.app.Dialog
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.provider.MediaStore
|
||||
import android.text.SpannableStringBuilder
|
||||
import android.text.Spanned
|
||||
import android.text.TextPaint
|
||||
@ -29,18 +28,21 @@ import com.gh.gamecenter.WebActivity
|
||||
import com.gh.gamecenter.common.base.fragment.ToolbarFragment
|
||||
import com.gh.gamecenter.common.callback.OnListClickListener
|
||||
import com.gh.gamecenter.common.constant.EntranceConsts
|
||||
import com.gh.gamecenter.feature.selector.LocalMediaActivity
|
||||
import com.gh.gamecenter.common.utils.*
|
||||
import com.gh.gamecenter.common.view.choosepic.ChoosePicAdapter
|
||||
import com.gh.gamecenter.core.utils.GsonUtils
|
||||
import com.gh.gamecenter.core.utils.MtaHelper
|
||||
import com.gh.gamecenter.core.utils.SpanBuilder
|
||||
import com.gh.gamecenter.core.utils.ToastUtils
|
||||
import com.gh.gamecenter.databinding.FragmentGameUploadBinding
|
||||
import com.gh.gamecenter.feature.entity.InstallGameEntity
|
||||
import com.gh.gamecenter.feature.game.SelectGameAdapter
|
||||
import com.gh.gamecenter.feature.selector.ChooseType
|
||||
import com.halo.assistant.HaloApp
|
||||
import com.lightgame.utils.Util_System_Keyboard
|
||||
import com.lightgame.utils.Utils
|
||||
import com.zhihu.matisse.Matisse
|
||||
import com.zhihu.matisse.internal.utils.PathUtils
|
||||
import io.reactivex.disposables.Disposable
|
||||
import okhttp3.MediaType
|
||||
import okhttp3.RequestBody
|
||||
@ -86,7 +88,6 @@ class GameUploadFragment : ToolbarFragment() {
|
||||
mViewModel.upLoadSuccess.observe(viewLifecycleOwner, Observer {
|
||||
if (it) {
|
||||
ToastUtils.showToast("上传成功")
|
||||
MtaHelper.onEvent("游戏上传", "游戏上传", "上传成功")
|
||||
mUploadDialog.dismiss()
|
||||
requireActivity().finish()
|
||||
} else {
|
||||
@ -119,17 +120,11 @@ class GameUploadFragment : ToolbarFragment() {
|
||||
5,
|
||||
object : OnListClickListener {
|
||||
override fun <T : Any?> onListClick(view: View?, position: Int, data: T) {
|
||||
MtaHelper.onEvent("游戏上传", "游戏图片", "添加图片")
|
||||
val intent = Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI)
|
||||
val intent = LocalMediaActivity.getIntent(requireContext(), ChooseType.IMAGE, 1, "游戏上传")
|
||||
startActivityForResult(intent, MEDIA_STORE_REQUEST)
|
||||
}
|
||||
}
|
||||
) {
|
||||
MtaHelper.onEvent(
|
||||
"游戏上传",
|
||||
"游戏图片",
|
||||
"删除图片"
|
||||
)
|
||||
}
|
||||
mAdapter?.setPicItem(R.layout.game_upload_pic_item)
|
||||
mAdapter?.setSuggestAddPicIcon(R.drawable.icon_pic_add)
|
||||
@ -147,19 +142,13 @@ class GameUploadFragment : ToolbarFragment() {
|
||||
1,
|
||||
object : OnListClickListener {
|
||||
override fun <T : Any?> onListClick(view: View?, position: Int, data: T) {
|
||||
MtaHelper.onEvent("游戏上传", "游戏图标", "添加图片")
|
||||
PermissionHelper.checkStoragePermissionBeforeAction(requireActivity()) {
|
||||
val intent = Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI)
|
||||
val intent = LocalMediaActivity.getIntent(requireContext(), ChooseType.IMAGE, 1, "游戏上传")
|
||||
startActivityForResult(intent, MEDIA_ICON_STORE_REQUEST)
|
||||
}
|
||||
}
|
||||
}
|
||||
) {
|
||||
MtaHelper.onEvent(
|
||||
"游戏上传",
|
||||
"游戏图标",
|
||||
"删除图片"
|
||||
)
|
||||
}
|
||||
mIconAdapter?.setPicItem(R.layout.game_upload_pic_item)
|
||||
mIconAdapter?.setSuggestAddPicIcon(R.drawable.icon_pic_add)
|
||||
@ -194,18 +183,15 @@ class GameUploadFragment : ToolbarFragment() {
|
||||
private fun initListener() {
|
||||
|
||||
mBinding.chooseGameLl.setOnClickListener {
|
||||
MtaHelper.onEvent("游戏上传", "安装包", "点我选择")
|
||||
showSelectDialog()
|
||||
}
|
||||
mBinding.gameIsNetworkingRg.setOnCheckedChangeListener { _, checkedId ->
|
||||
when (checkedId) {
|
||||
R.id.gameNetworkingRb -> {
|
||||
mIsOnline = "yes"
|
||||
MtaHelper.onEvent("游戏上传", "是否联网", "需要联网")
|
||||
}
|
||||
R.id.gameNoNetworkingRb -> {
|
||||
mIsOnline = "no"
|
||||
MtaHelper.onEvent("游戏上传", "是否联网", "无需联网")
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -213,15 +199,12 @@ class GameUploadFragment : ToolbarFragment() {
|
||||
when (checkedId) {
|
||||
R.id.gameLanguageChineseRb -> {
|
||||
mGameLanguage = "中文"
|
||||
MtaHelper.onEvent("游戏上传", "游戏语言", "中文")
|
||||
}
|
||||
R.id.gameLanguageEnglishRb -> {
|
||||
mGameLanguage = "英文"
|
||||
MtaHelper.onEvent("游戏上传", "游戏语言", "英文")
|
||||
}
|
||||
R.id.gameLanguageOtherRb -> {
|
||||
mGameLanguage = "其他"
|
||||
MtaHelper.onEvent("游戏上传", "游戏语言", "其他")
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -229,21 +212,17 @@ class GameUploadFragment : ToolbarFragment() {
|
||||
when (checkedId) {
|
||||
R.id.gameTypeLocalRb -> {
|
||||
mGameType = "local"
|
||||
MtaHelper.onEvent("游戏上传", "游戏类型", "单机")
|
||||
}
|
||||
R.id.gameTypeOnlineRb -> {
|
||||
mGameType = "online"
|
||||
MtaHelper.onEvent("游戏上传", "游戏类型", "网游")
|
||||
}
|
||||
R.id.gameTypeOtherRb -> {
|
||||
mGameType = "other"
|
||||
MtaHelper.onEvent("游戏上传", "游戏类型", "其他")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mBinding.addGameLabeTv.setOnClickListener {
|
||||
MtaHelper.onEvent("游戏上传", "游戏标签", "添加标签")
|
||||
if (mTags.size < mMaxTagSize) {
|
||||
showAddTagDialog()
|
||||
} else {
|
||||
@ -256,7 +235,6 @@ class GameUploadFragment : ToolbarFragment() {
|
||||
}
|
||||
|
||||
private fun commit() {
|
||||
MtaHelper.onEvent("游戏上传", "提交", "提交")
|
||||
if (TextUtils.isEmpty(mBinding.tvChoose.text.toString())) {
|
||||
ToastUtils.showToast("请先选择游戏安装包")
|
||||
return
|
||||
@ -471,11 +449,9 @@ class GameUploadFragment : ToolbarFragment() {
|
||||
}
|
||||
|
||||
back.setOnClickListener {
|
||||
MtaHelper.onEvent("游戏上传", "安装包", "关闭")
|
||||
mSelectGameDialog?.cancel()
|
||||
}
|
||||
manualBtn.setOnClickListener {
|
||||
MtaHelper.onEvent("游戏上传", "安装包", "从设备上选择")
|
||||
val intent = CleanApkActivity.getIntent(requireContext(), true)
|
||||
PermissionHelper.checkManageAllFilesOrStoragePermissionBeforeAction(requireActivity()) {
|
||||
startActivityForResult(intent, CHOOSE_LOCAL_APK)
|
||||
@ -499,32 +475,20 @@ class GameUploadFragment : ToolbarFragment() {
|
||||
super.onActivityResult(requestCode, resultCode, data)
|
||||
if (data == null) return
|
||||
if (requestCode == MEDIA_STORE_REQUEST || requestCode == MEDIA_ICON_STORE_REQUEST) {
|
||||
val selectedImage = data.data ?: return
|
||||
val filePathColumn = arrayOf(MediaStore.Images.Media.DATA)
|
||||
val selectedPaths = Matisse.obtainResult(data) ?: return
|
||||
val picturePath = PathUtils.getPath(requireContext(), selectedPaths[0])
|
||||
|
||||
val cursor = requireContext().contentResolver.query(selectedImage, filePathColumn, null, null, null)
|
||||
?: return
|
||||
cursor.moveToFirst()
|
||||
Utils.log("picturePath = $picturePath")
|
||||
|
||||
try {
|
||||
val columnIndex = cursor.getColumnIndex(filePathColumn[0])
|
||||
val picturePath = cursor.getString(columnIndex)
|
||||
cursor.close()
|
||||
|
||||
Utils.log("picturePath = $picturePath")
|
||||
|
||||
val file = File(picturePath)
|
||||
if (file.length() > 5 * 1024 * 1024) {
|
||||
ToastUtils.showToast(getString(R.string.pic_max_hint, 5))
|
||||
val file = File(picturePath)
|
||||
if (file.length() > 5 * 1024 * 1024) {
|
||||
ToastUtils.showToast(getString(R.string.pic_max_hint, 5))
|
||||
} else {
|
||||
if (requestCode == MEDIA_STORE_REQUEST) {
|
||||
mAdapter!!.addFileList(picturePath)
|
||||
} else {
|
||||
if (requestCode == MEDIA_STORE_REQUEST) {
|
||||
mAdapter!!.addFileList(picturePath)
|
||||
} else {
|
||||
mIconAdapter!!.addFileList(picturePath)
|
||||
}
|
||||
mIconAdapter!!.addFileList(picturePath)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
ToastUtils.showToast(e.message ?: "")
|
||||
}
|
||||
} else if (requestCode == CHOOSE_LOCAL_APK) {
|
||||
val packageName = data.getStringExtra(EntranceConsts.KEY_PACKAGENAME) ?: ""
|
||||
@ -610,7 +574,6 @@ class GameUploadFragment : ToolbarFragment() {
|
||||
labelTv.text = tag
|
||||
labelView.findViewById<View>(R.id.picDelIv).setOnClickListener {
|
||||
if (mTags.contains(tag)) {
|
||||
MtaHelper.onEvent("游戏上传", "游戏标签", "删除标签")
|
||||
mBinding.gameLabelFl.removeView(labelView)
|
||||
mTags.remove(tag)
|
||||
mBinding.gameLabelFl.goneIf(mTags.isEmpty())
|
||||
|
||||
@ -182,7 +182,9 @@ class AddGamesDialogFragment : BaseDialogFragment() {
|
||||
return super.onBack()
|
||||
}
|
||||
|
||||
private fun showGuidePopupWindow(): PopupWindow {
|
||||
private fun showGuidePopupWindow(): PopupWindow? {
|
||||
if (!isAdded) return null
|
||||
|
||||
val guideBinding = LayoutGameCollectionAddGamesGuideBinding.inflate(layoutInflater)
|
||||
val popupWindow = BugFixedPopupWindow(
|
||||
guideBinding.root,
|
||||
|
||||
@ -7,8 +7,8 @@ import android.view.View
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.base.activity.ToolBarActivity
|
||||
import com.gh.gamecenter.common.constant.EntranceConsts
|
||||
import com.gh.gamecenter.core.utils.DisplayUtils
|
||||
import com.gh.gamecenter.common.exposure.ExposureSource
|
||||
import com.gh.gamecenter.core.utils.DisplayUtils
|
||||
|
||||
/**
|
||||
* 游戏单详情
|
||||
@ -30,8 +30,8 @@ class GameCollectionDetailActivity : ToolBarActivity() {
|
||||
}
|
||||
|
||||
override fun getBusinessId(): Pair<String, String> {
|
||||
val fragment = targetFragment as GameCollectionDetailFragment
|
||||
return if (fragment.arguments != null) {
|
||||
val fragment = targetFragment as? GameCollectionDetailFragment?
|
||||
return if (fragment?.arguments != null) {
|
||||
Pair(fragment.requireArguments().getString(EntranceConsts.KEY_GAME_COLLECTION_ID) ?: "", "")
|
||||
} else {
|
||||
super.getBusinessId()
|
||||
|
||||
@ -16,12 +16,13 @@ import com.gh.gamecenter.common.constant.EntranceConsts
|
||||
import com.gh.common.util.NewLogUtils
|
||||
import com.gh.gamecenter.common.utils.PermissionHelper
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.feature.selector.LocalMediaActivity
|
||||
import com.gh.gamecenter.common.utils.setRootBackgroundDrawable
|
||||
import com.gh.gamecenter.common.utils.toColor
|
||||
import com.gh.gamecenter.common.utils.toDrawable
|
||||
import com.gh.gamecenter.databinding.DialogChooseGameCollectionCoverTypeBinding
|
||||
import com.gh.gamecenter.feature.selector.ChooseType
|
||||
import com.gh.gamecenter.gamecollection.publish.GameCollectionEditActivity.Companion.REQUEST_CODE_IMAGE
|
||||
import com.gh.gamecenter.qa.editor.LocalMediaActivity
|
||||
import com.halo.assistant.HaloApp
|
||||
|
||||
class ChooseGameCollectionCoverTypeDialog : BaseDialogFragment() {
|
||||
@ -42,7 +43,7 @@ class ChooseGameCollectionCoverTypeDialog : BaseDialogFragment() {
|
||||
startActivityForResult(
|
||||
LocalMediaActivity.getIntent(
|
||||
requireContext(),
|
||||
LocalMediaActivity.ChooseType.IMAGE,
|
||||
ChooseType.IMAGE,
|
||||
1,
|
||||
"创建游戏单"
|
||||
), REQUEST_CODE_IMAGE
|
||||
|
||||
@ -285,7 +285,7 @@ class GameCollectionSquareAdapter(
|
||||
}
|
||||
})
|
||||
addOnScrollListener(ScrollEventListener(this).apply {
|
||||
setOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
|
||||
registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
|
||||
override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {
|
||||
super.onPageScrolled(position, positionOffset, positionOffsetPixels)
|
||||
binding.bannerIndicator.onPageScrolled(
|
||||
|
||||
@ -410,7 +410,7 @@ class GameCollectionSquareFragment : LazyListFragment<GamesCollectionEntity, Gam
|
||||
}
|
||||
})
|
||||
addOnScrollListener(ScrollEventListener(this).apply {
|
||||
setOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
|
||||
registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
|
||||
override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {
|
||||
super.onPageScrolled(position, positionOffset, positionOffsetPixels)
|
||||
mDefaultBinding.headerContainer.bannerIndicator.onPageScrolled(
|
||||
|
||||
@ -63,7 +63,10 @@ import com.gh.gamecenter.databinding.*
|
||||
import com.gh.gamecenter.entity.GameUpdateEntity
|
||||
import com.gh.gamecenter.entity.RecommendPopupEntity
|
||||
import com.gh.gamecenter.eventbus.*
|
||||
import com.gh.gamecenter.feature.entity.*
|
||||
import com.gh.gamecenter.feature.entity.GameEntity
|
||||
import com.gh.gamecenter.feature.entity.PluginLocation
|
||||
import com.gh.gamecenter.feature.entity.SimpleGame
|
||||
import com.gh.gamecenter.feature.entity.TagStyleEntity
|
||||
import com.gh.gamecenter.feature.eventbus.EBConcernChanged
|
||||
import com.gh.gamecenter.feature.exposure.ExposureEvent
|
||||
import com.gh.gamecenter.feature.utils.ApkActiveUtils
|
||||
@ -71,11 +74,7 @@ import com.gh.gamecenter.feature.utils.SentryHelper
|
||||
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
|
||||
import com.gh.gamecenter.gamedetail.dialog.GameDetailMoreDialog
|
||||
import com.gh.gamecenter.gamedetail.dialog.GameTagsDialog
|
||||
import com.gh.gamecenter.gamedetail.dialog.SpecialDownloadDialogFragment
|
||||
import com.gh.gamecenter.gamedetail.dialog.SpecialDownloadVisibilityViewModel
|
||||
import com.gh.gamecenter.gamedetail.dialog.*
|
||||
import com.gh.gamecenter.gamedetail.entity.ContentCardEntity
|
||||
import com.gh.gamecenter.gamedetail.entity.NewGameDetailEntity
|
||||
import com.gh.gamecenter.gamedetail.entity.Video
|
||||
@ -149,8 +148,6 @@ class GameDetailFragment : BaseLazyFragment(), IScrollable {
|
||||
|
||||
private var mShowConcernOnMenu = false
|
||||
|
||||
private var mSpecialDownloadDetailFragmentIsShowing = false
|
||||
|
||||
private val mFragmentsList = ArrayList<Fragment>()
|
||||
private val mTabTitleList = ArrayList<String>()
|
||||
private val mTabTypeList = ArrayList<String>() // tab 类型的列表,用于确定某个类型的 tab 在第几个位置
|
||||
@ -167,7 +164,7 @@ class GameDetailFragment : BaseLazyFragment(), IScrollable {
|
||||
|| downloadEntity.status == DownloadStatus.redirected
|
||||
) {
|
||||
// 特殊下载弹窗
|
||||
if (isSpecialDownloadDialogAvailable() && !mSpecialDownloadDetailFragmentIsShowing) {
|
||||
if (isSpecialDownloadDialogAvailable(downloadEntity) && !isSpecialDownloadDetailFragmentIsShowing()) {
|
||||
updateSpecialDownloadDialogIcon(true)
|
||||
|
||||
if (downloadEntity.status == DownloadStatus.add) {
|
||||
@ -868,8 +865,10 @@ class GameDetailFragment : BaseLazyFragment(), IScrollable {
|
||||
|
||||
showConcernIconAtBottomBarIfAvailable()
|
||||
|
||||
if (isSpecialDownloadDialogAvailable()
|
||||
&& DownloadManager.getInstance().getDownloadEntitySnapshot(mGameEntity) != null) {
|
||||
val downloadEntitySnapshot = DownloadManager.getInstance().getDownloadEntitySnapshot(mGameEntity)
|
||||
|
||||
if (isSpecialDownloadDialogAvailable(downloadEntitySnapshot)
|
||||
&& downloadEntitySnapshot != null) {
|
||||
updateSpecialDownloadDialogIcon(true)
|
||||
}
|
||||
|
||||
@ -1180,6 +1179,11 @@ class GameDetailFragment : BaseLazyFragment(), IScrollable {
|
||||
}
|
||||
|
||||
private fun doShowAlertDialog(dialog: GameEntity.Dialog) {
|
||||
SensorsBridge.trackEvent("GameDetailDialogShow",
|
||||
"game_id", mGameEntity?.id ?: "",
|
||||
"game_name", mGameEntity?.name ?: "",
|
||||
"game_type", mGameEntity?.categoryChinese ?: ""
|
||||
)
|
||||
DialogHelper.showDialogWithHtmlContent(
|
||||
requireContext(),
|
||||
dialog.title,
|
||||
@ -1187,8 +1191,33 @@ class GameDetailFragment : BaseLazyFragment(), IScrollable {
|
||||
dialog.confirmButton.text.toString(),
|
||||
dialog.closeButtonText,
|
||||
{
|
||||
SensorsBridge.trackEvent("GameDetailDialogClick",
|
||||
"game_id", mGameEntity?.id ?: "",
|
||||
"game_name", mGameEntity?.name ?: "",
|
||||
"game_type", mGameEntity?.categoryChinese ?: "",
|
||||
"link_type", dialog.confirmButton.type ?: "",
|
||||
"link_id", dialog.confirmButton.link ?: "",
|
||||
"link_text", dialog.confirmButton.linkText ?: "",
|
||||
"button_name", dialog.confirmButton.text.toString()
|
||||
)
|
||||
dialog.confirmButton.text = dialog.confirmButton.linkText
|
||||
DirectUtils.directToLinkPage(requireContext(), dialog.confirmButton, mEntrance, "")
|
||||
},
|
||||
{
|
||||
SensorsBridge.trackEvent("GameDetailDialogClick",
|
||||
"game_id", mGameEntity?.id ?: "",
|
||||
"game_name", mGameEntity?.name ?: "",
|
||||
"game_type", mGameEntity?.categoryChinese ?: "",
|
||||
"button_name", dialog.closeButtonText
|
||||
)
|
||||
},
|
||||
{
|
||||
SensorsBridge.trackEvent("GameDetailDialogClick",
|
||||
"game_id", mGameEntity?.id ?: "",
|
||||
"game_name", mGameEntity?.name ?: "",
|
||||
"game_type", mGameEntity?.categoryChinese ?: "",
|
||||
"button_name", "关闭弹窗"
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
@ -2562,12 +2591,15 @@ class GameDetailFragment : BaseLazyFragment(), IScrollable {
|
||||
* 2. 未获取到游戏详情数据
|
||||
* 3. 当前游戏 APK 不为 1 个
|
||||
* 4. 当前游戏类型不为畅玩
|
||||
* 5. 当前游戏不是双下载时使用本地下载进行下载
|
||||
*/
|
||||
private fun isSpecialDownloadDialogAvailable(): Boolean {
|
||||
private fun isSpecialDownloadDialogAvailable(downloadEntity: DownloadEntity? = null): Boolean {
|
||||
if (Config.getNewApiSettingsEntity()?.install?.questionTip?.linkEntity == null) return false
|
||||
if (mNewGameDetailEntity == null || mGameEntity == null) return false
|
||||
if (mGameEntity?.getApk()?.size != 1) return false
|
||||
if (GameUtils.shouldPerformAsVGame(mGameEntity!!)) return false
|
||||
if (downloadEntity?.asVGame() == true) return false
|
||||
if (downloadEntity?.isSimulatorGame() == true) return false
|
||||
if (downloadEntity?.isLocalDownloadInDualDownloadMode() == true) return false
|
||||
|
||||
return true
|
||||
}
|
||||
@ -2585,7 +2617,6 @@ class GameDetailFragment : BaseLazyFragment(), IScrollable {
|
||||
if (fragment == null) {
|
||||
if (!visibilityViewModel.specialDownloadVisibleLiveData.hasObservers()) {
|
||||
visibilityViewModel.specialDownloadVisibleLiveData.observe(viewLifecycleOwner) {
|
||||
mSpecialDownloadDetailFragmentIsShowing = it
|
||||
updateSpecialDownloadDialogIcon(visible = !it)
|
||||
}
|
||||
}
|
||||
@ -2601,6 +2632,10 @@ class GameDetailFragment : BaseLazyFragment(), IScrollable {
|
||||
}
|
||||
}
|
||||
|
||||
private fun isSpecialDownloadDetailFragmentIsShowing(): Boolean {
|
||||
return childFragmentManager.findFragmentByTag(TAG_SPECIAL_DOWNLOAD_DIALOG) != null
|
||||
}
|
||||
|
||||
override fun scrollToTop() {
|
||||
val fragment = mFragmentsList.safelyGetInRelease(mBodyBinding.gamedetailVp.currentItem)
|
||||
if (fragment is IScrollable && fragment.isAdded) {
|
||||
|
||||
@ -17,6 +17,7 @@ import com.gh.common.iinterface.ISuperiorChain
|
||||
import com.gh.common.prioritychain.CustomFloatingWindowHandler
|
||||
import com.gh.common.prioritychain.PriorityChain
|
||||
import com.gh.common.prioritychain.PullDownPushHandler
|
||||
import com.gh.common.prioritychain.VideoHandler
|
||||
import com.gh.common.util.DefaultSearchHintHelper
|
||||
import com.gh.common.util.DialogUtils
|
||||
import com.gh.common.util.DirectUtils
|
||||
@ -468,9 +469,9 @@ class CustomPageFragment : LazyFragment(), ISmartRefreshContent, IScrollable {
|
||||
|
||||
binding = FragmentCustomBinding.bind(mCachedView)
|
||||
|
||||
buildPriorityChain()
|
||||
scrollCalculatorHelper = ScrollCalculatorHelper(binding.gameList, R.id.autoVideoView, 0, false)
|
||||
|
||||
scrollCalculatorHelper = ScrollCalculatorHelper(binding.gameList, R.id.autoVideoView, 0)
|
||||
buildPriorityChain()
|
||||
|
||||
adapter = CustomPageAdapter(
|
||||
viewModel,
|
||||
@ -512,9 +513,11 @@ class CustomPageFragment : LazyFragment(), ISmartRefreshContent, IScrollable {
|
||||
|
||||
private fun buildPriorityChain() {
|
||||
val floatingWindowHandler = CustomFloatingWindowHandler(23)
|
||||
val videoHandler = VideoHandler(24, scrollCalculatorHelper)
|
||||
|
||||
priorityChain.addHandler(pullDownPushHandler)
|
||||
priorityChain.addHandler(floatingWindowHandler)
|
||||
priorityChain.addHandler(videoHandler)
|
||||
(parentFragment as? BaseTabWrapperFragment)?.addTabGuideHandlerIfExists(priorityChain)
|
||||
|
||||
viewModel.floatingWindows.observe(viewLifecycleOwner, EventObserver {
|
||||
|
||||
@ -146,7 +146,7 @@ class CustomFoldSlideLargeImageItemAdapter(
|
||||
if (dataList.isEmpty()) {
|
||||
0
|
||||
} else {
|
||||
Int.MAX_VALUE / 2 - Int.MAX_VALUE % dataList.size
|
||||
Int.MAX_VALUE / 2 - (Int.MAX_VALUE / 2) % dataList.size
|
||||
}
|
||||
|
||||
class ImageItemViewHolder(
|
||||
|
||||
@ -140,7 +140,7 @@ class CommonContentHomeSLideListUi(
|
||||
}
|
||||
|
||||
binding.recyclerView.addOnScrollListener(scrollEventListener.apply {
|
||||
setOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
|
||||
registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
|
||||
override fun onPageScrollStateChanged(state: Int) {
|
||||
super.onPageScrollStateChanged(state)
|
||||
|
||||
|
||||
@ -163,7 +163,7 @@ class CommonContentHomeSlideWithCardsUi(
|
||||
}
|
||||
})
|
||||
binding.recyclerView.addOnScrollListener(ScrollEventListener(binding.recyclerView).apply {
|
||||
setOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
|
||||
registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
|
||||
override fun onPageSelected(position: Int) {
|
||||
_currentDataPosition = adapter.getDataPosition(position)
|
||||
}
|
||||
|
||||
@ -101,7 +101,7 @@ class NotificationColumnViewHolder(
|
||||
|
||||
private val scrollEventListener by lazy(LazyThreadSafetyMode.NONE) {
|
||||
ScrollEventListener(binding.rvNotification).apply {
|
||||
setOnPageChangeCallback(object : OnPageChangeCallback() {
|
||||
registerOnPageChangeCallback(object : OnPageChangeCallback() {
|
||||
override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {
|
||||
if (positionOffset > 0F) {
|
||||
// position 代表的是正在移出屏幕的 itemView 的位置
|
||||
|
||||
@ -132,7 +132,7 @@ class HomeSlideListViewHolder(
|
||||
updateImmersiveColor(slideList[0].placeholderColor.hexStringToIntColor())
|
||||
|
||||
binding.recyclerView.addOnScrollListener(ScrollEventListener(binding.recyclerView).apply {
|
||||
setOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
|
||||
registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
|
||||
var lastStatePosition = -1
|
||||
var lastScrollState = RecyclerView.SCROLL_STATE_IDLE
|
||||
|
||||
|
||||
@ -153,7 +153,7 @@ class HomeSlideWithCardsViewHolder(
|
||||
}
|
||||
})
|
||||
binding.recyclerView.addOnScrollListener(ScrollEventListener(binding.recyclerView).apply {
|
||||
setOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
|
||||
registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
|
||||
var lastStatePosition = -1
|
||||
var lastScrollState = RecyclerView.SCROLL_STATE_IDLE
|
||||
|
||||
|
||||
@ -5,7 +5,6 @@ import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.core.view.forEach
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.gh.gamecenter.common.constant.Constants
|
||||
@ -15,13 +14,28 @@ import com.gh.gamecenter.core.utils.SPUtils
|
||||
import com.gh.gamecenter.video.detail.CustomManager
|
||||
import com.halo.assistant.HaloApp
|
||||
|
||||
class ScrollCalculatorHelper(val mListRv: RecyclerView, private val mPlayId: Int, private val mRangeTop: Int) {
|
||||
class ScrollCalculatorHelper(
|
||||
val mListRv: RecyclerView,
|
||||
private val mPlayId: Int,
|
||||
private val mRangeTop: Int,
|
||||
private var isEnabled: Boolean = true
|
||||
) {
|
||||
|
||||
private var mFirstVisible = -1
|
||||
private var mLastVisible = 0
|
||||
private var mRunnable: PlayRunnable? = null
|
||||
private val mPlayHandler = Handler(Looper.getMainLooper())
|
||||
var currentPlayer: AutomaticVideoView? = null
|
||||
|
||||
fun enableAndPlayIfValid() {
|
||||
isEnabled = true
|
||||
|
||||
if (mListRv.isAttachedToWindow
|
||||
&& mListRv.scrollState == RecyclerView.SCROLL_STATE_IDLE) {
|
||||
playVideo(mListRv)
|
||||
}
|
||||
}
|
||||
|
||||
fun onScrollStateChanged(scrollState: Int) {
|
||||
if (scrollState == RecyclerView.SCROLL_STATE_IDLE) {
|
||||
playVideo(mListRv)
|
||||
@ -80,7 +94,7 @@ class ScrollCalculatorHelper(val mListRv: RecyclerView, private val mPlayId: Int
|
||||
}
|
||||
|
||||
private fun playVideo(view: RecyclerView?) {
|
||||
if (view == null) return
|
||||
if (view == null || !view.isAttachedToWindow || !isEnabled) return
|
||||
val layoutManager = view.layoutManager
|
||||
var gsyBaseVideoPlayer: AutomaticVideoView
|
||||
for (i in mFirstVisible until mLastVisible + 1) {
|
||||
|
||||
@ -130,6 +130,24 @@ object PackagesManager {
|
||||
return null
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据游戏 ID 获取已安装的信息
|
||||
*
|
||||
* @param gameId 游戏 Id
|
||||
* @return 如果为空:未安装
|
||||
*/
|
||||
fun getInstalledDataByGameId(gameId: String?): GameInstall? {
|
||||
if (TextUtils.isEmpty(gameId)) {
|
||||
return null
|
||||
}
|
||||
for (gameInstall in mInstalledList) {
|
||||
if (gameInstall.id == gameId) {
|
||||
return gameInstall
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 判断包名是否可以更新
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user